|
WinAVR-20070122 еще сырой?, ошибки оптимизации |
|
|
|
Feb 17 2007, 04:29
|
Группа: Участник
Сообщений: 8
Регистрация: 6-03-06
Из: Новосибирск
Пользователь №: 15 027

|
Вот пример генерации кода. опции -Os
---------------------------------------------------------
int g;
int func(void) { int res; { uint8_t _SReg; asm volatile("in %0,__SREG__\n\tcli" : "=r" (_SReg));
res = g;
asm volatile( "out __SREG__,%0" :: "r" (_SReg)); } return res; } -------------------------------------------------------- WinAVR 20060421 (правильно)
28 0000 2FB7 in r18,__SREG__ 29 0002 F894 cli 32 0004 8091 0000 lds r24,g 33 0008 9091 0000 lds r25,(g)+1 36 000c 2FBF out __SREG__,r18 40 000e 0895 ret
--------------------------------------------------------- WinAVR 20070122 (неправильно)
32 0006 8FB7 in r24,__SREG__ 33 0008 F894 cli 37 000a 8FBF out __SREG__,r24 40 000c 8091 0000 lds r24,g 41 0010 9091 0000 lds r25,(g)+1 46 0014 0895 ret
---------------------------------------------------------
|
|
|
|
|
Feb 17 2007, 14:10
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
К сожалению это не компилятор сырой, а ваш код. Правильно писать так: Код #include <stdint.h> int g;
int func(void) { int res; { uint8_t _SReg; // asm volatile("in %0,__SREG__\n\tcli" : "=r" (_SReg)); asm volatile("in %0,__SREG__\n\tcli" : "=r" (_SReg)::"memory");
res = g;
// asm volatile( "out __SREG__,%0" :: "r" (_SReg)); asm volatile( "out __SREG__,%0" :: "r" (_SReg): "memory"); } return res; } Анатолий.
|
|
|
|
|
Feb 17 2007, 15:31
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 22-06-06
Из: Kharkiv, UA
Пользователь №: 18 284

|
Заметил, что по сравнению с WinAVR 20060125 код стал занимать немного больше места. Например, bootloader занимал 2034 байта, стал 2078 байт (написан на с + макросы из boot.h и pgmspace.h). В 2к boot sector уже не влазит. В чем отличия, еще еще не разбирался, но, похоже, придется менять "трюки" для уменьшения размера кода.
|
|
|
|
|
Feb 17 2007, 16:44
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(ahulap @ Feb 17 2007, 15:31)  Заметил, что по сравнению с WinAVR 20060125 код стал занимать немного больше места. Например, bootloader занимал 2034 байта, стал 2078 байт (написан на с + макросы из boot.h и pgmspace.h). В 2к boot sector уже не влазит. В чем отличия, еще еще не разбирался, но, похоже, придется менять "трюки" для уменьшения размера кода. Если у вас есть локальные переменные в 'main()', сделайте их временно глобальными. 40 байт не обещаю, но байт на 20 код должен уменьшиться. Анатолий.
|
|
|
|
|
Feb 17 2007, 19:00
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 22-06-06
Из: Kharkiv, UA
Пользователь №: 18 284

|
[/quote] Если у вас есть локальные переменные в 'main()', сделайте их временно глобальными. 40 байт не обещаю, но байт на 20 код должен уменьшиться. [/quote] Нет в main() локальных переменных. Из нее в зависимости от джамперов вызываются две static функции (для обновления "себя" или "соседа"). В них несколько локальных переменных (счетчики и байт, принятый по UART), остальные и массивы static. Я этот загрузчик долго сворачивал, так что думаю, дело в сохранении многобайтовых переменных, принимаемых по UART, идущих старшим байтом вперед. Если записать так: static unsigned char buf[512]; unsigned int size; *( (unsigned char *)&size + 1) = buf[0]; *( (unsigned char *)&size + 0) = buf[1]; то компиллятор расположит переменную в памяти, что для счетчика не хорошо. Если записать так: size = (buf[0] <<8) | buf[1]; то будут лишняя операция ИЛИ 2х-байтных чисел. Как это все-таки правильно реализовать на С? Или только через ассемблерные вставки? P.S.: если собрать этот bootloader в IAR 4.12 со средней оптимизацией по размеру, то получится 1940 байт. Есть за чем гнаться
|
|
|
|
|
Feb 18 2007, 00:16
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 22-06-06
Из: Kharkiv, UA
Пользователь №: 18 284

|
Провел эксперименты, вот что получил:
unsigned int size;
size = ((unsigned int)mess[1] << 8) | mess[2]; 3cd0: 80 91 63 00 lds r24, 0x0063 3cd4: 99 27 eor r25, r25 3cd6: d8 2f mov r29, r24 3cd8: cc 27 eor r28, r28 3cda: 80 91 64 00 lds r24, 0x0064 3cde: 99 27 eor r25, r25 3ce0: c8 2b or r28, r24 3ce2: d9 2b or r29, r25
size = ((unsigned int)mess[1] << 8) + mess[2]; 3cd0: 80 91 63 00 lds r24, 0x0063 3cd4: 99 27 eor r25, r25 3cd6: d8 2f mov r29, r24 3cd8: cc 27 eor r28, r28 3cda: 80 91 64 00 lds r24, 0x0064 3cde: c8 0f add r28, r24 3ce0: d1 1d adc r29, r1
typedef union { unsigned int i; unssigned char c[2]; } un_int; un_int size;
size.c[1] = mess[1]; size.c[0] = mess[2]; 3cd0: d0 91 63 00 lds r29, 0x0063 3cd4: c0 91 64 00 lds r28, 0x0064
Наилучший результат дают union'ы, но программа теряет в читаемости: if (size.i) {...}, do {...} while (--size.i) ... Есть еще какие-нибудь способы на С, без ассеблерных вставок?
|
|
|
|
|
Feb 23 2007, 15:55
|
Участник

Группа: Участник
Сообщений: 44
Регистрация: 22-06-06
Из: Kharkiv, UA
Пользователь №: 18 284

|
Нашел отличие: 00003900 <main>: 3900: 2f 92 push r2 3902: 3f 92 push r3 ... 3920: cf 93 push r28 3922: df 93 push r29 3924: 88 e0 ldi r24, 0x08 ; 8 3926: 88 bb out 0x18, r24 ; 24 Всего 18 push при входе в main и соотв 18 pop. WinAVR 20060125 такого не делал. Как указать, что при входе/выходе из функции не надо сохранять/восстанивливать регистры? (для main в частности)
|
|
|
|
|
Feb 23 2007, 23:43
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(ahulap @ Feb 23 2007, 15:55)  Нашел отличие: 00003900 <main>: 3900: 2f 92 push r2 3902: 3f 92 push r3 ... 3920: cf 93 push r28 3922: df 93 push r29 3924: 88 e0 ldi r24, 0x08 ; 8 3926: 88 bb out 0x18, r24 ; 24 Всего 18 push при входе в main и соотв 18 pop. WinAVR 20060125 такого не делал. Как указать, что при входе/выходе из функции не надо сохранять/восстанивливать регистры? (для main в частности) Никак, эта проблемма обсуждалась в 'avr-libc-dev' майллисте и возможно будет решена в следуещей версии WinAVR. Анатолий.
Сообщение отредактировал aesok - Feb 23 2007, 23:43
|
|
|
|
|
Feb 23 2007, 23:58
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(gormih @ Feb 23 2007, 23:51)  WinAVR еще долго будет сырым по определению.
Все таки продукт не коммерческий...
Хотите получить оптимизаию - пользуйте IAR или на худой конец CodeVision Уважаемый gormih, этот топик о проблеммах в WinAVR. Если Вы хотите пообсуждать какой компилятор лучше, пожалуйста начните новую тему. Анатолий.
|
|
|
|
|
Feb 24 2007, 00:34
|

nofb
  
Группа: Свой
Сообщений: 430
Регистрация: 18-05-06
Из: Москва, Зеленоград
Пользователь №: 17 218

|
Цитата(aesok @ Feb 23 2007, 23:58)  Уважаемый gormih, этот топик о проблеммах в WinAVR. Если Вы хотите пообсуждать какой компилятор лучше, пожалуйста начните новую тему. Анатолий. Уважаемый Анатолий! Я понимаю Вашу озабоченность по поводу того, что здесь может начаться дискуссия по поводу сравнения характеристик того или иного компилятора, однако смею Вас уверить, что мой пост имеет прямое отношение к проблеме оптимизации, как ни крути. Однако, если Вам не нравится перспектива обсуждать данную тему - то по моему ее можно просто закрыть - было сказано, что проблема будет решена в следующих версиях... возможно лет через 10...
--------------------
Это не то что вы подумали ...
|
|
|
|
|
Feb 24 2007, 00:42
|
Участник

Группа: Новичок
Сообщений: 73
Регистрация: 10-01-07
Пользователь №: 24 292

|
Он же не пишет - "лучше-хуже" он именно сообщает свое мнение чего в WinAVR не хватает. Хотя я с этим мнением не согласен.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|