|
"Оптимизация" в WinAVR и как с этим бороться |
|
|
|
Nov 16 2011, 18:07
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Перейдя с ассемблера на WinAVR, невольно стал обращать на размер кода. Когда стал разбираться в конкретике генерируемого кода , хваленный на многих сайтах WinAVR обнажил свое несовершенство. Короче, программка : Код #include <avr/io.h> #include <inttypes.h>
#define Btn1 PB2 #define Btn2 PB3
#define KeyMask (1<<Btn1)|(1<<Btn2) #define sbi(p,b) (p |= (1<<b)) //Установить бит
volatile register int8_t Cnt asm("r19"); // фоновый счетчик volatile register int8_t a asm ("r16");
int main (void) { asm("nop"); a = 1;
while(1) { if (~(PINB)&(KeyMask)) { a |= 0x01; } if ((--Cnt)==0) { if (a==1 ) { a=0; sbi (PINB,PB2); } } } } Соответственно , полученный код: Код a = 1; ldi r16, 0x01
while(1) { [color="#FF00FF"]if (~(PINB)&(KeyMask)) in r24, 0x16 ldi r25, 0x00 com r24 com r25 andi r24, 0x0C andi r25, 0x00 or r24, r25 breq .+2[/color] { a |= 0x01; } ori r16, 0x01
[color="#FF0000"]if ((--Cnt)==0) mov r24, r19 subi r24, 0x01 mov r19, r24[/color] brne .-26 { if (a==1 ) cpi r16, 0x01 brne .-30 { a=0; ldi r16, 0x00
sbi (PINB,PB2); sbi 0x16, 2 rjmp .-36 Конструкцию if ((--Cnt)==0) выделенную крас.цветом может заменить всего одна машинная команда: dec r19! Вопрос: как заставить компилятор это делать ? Во втором случае: if (~(PINB)&(KeyMask)) , невижу смысла во втором парном регистре r25. Можно использовать "tst r24". Можно как нибудь с этим бороться ?! Не хочеться чтобы потом код получался неоправданно раздутым! Может быть стоит подождать другую версию компилятора (пользуюсь WinAVR-20100110) или уже пререходить на совсем другой ?
|
|
|
|
|
 |
Ответов
|
Nov 16 2011, 19:58
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(MaxiMuz @ Nov 17 2011, 00:07)  Перейдя с ассемблера на WinAVR, невольно стал обращать на размер кода. И зря. Если код помещается в чип и успевает сделать то, что должен, то какая разница, какого он размера? Цитата(MaxiMuz @ Nov 17 2011, 00:07)  Конструкцию if ((--Cnt)==0) выделенную крас.цветом может заменить всего одна машинная команда: dec r19! Вам же написали, что volatile register писать нельзя. Какие претензии? Что касается второго, то целочисленные константы по умолчанию имеют тип int. Попробуйте написать if (~(PINB)&((unsigned char)KeyMask)). ЗЫ. Выделение цветом не работает в блоке code, если сильно надо, то пользуйтесь блоком codebox - там вроде работает.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Nov 18 2011, 09:00
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Цитата(AHTOXA @ Nov 16 2011, 22:58)  Вам же написали, что volatile register писать нельзя. Какие претензии? Это неправильное утверждение! Если из выражения "volatile register int8_t a asm ("r16");" убрать квалификатор volatile, то компилятор воообще обходит использование указанных регистров, используя свои. И хотя код получается короче, неизвестно как дальще поведет себя "оптимизатор" , если программа усложниться ! Цитата(neiver @ Nov 18 2011, 11:44)  Неа, результат другой: Код 6c: 86 b3 in r24, 0x16; 22 6e: 8c 70 andi r24, 0x0C; 12 70: 09 f4 brne .+2 ; 0x74 <main+0x8> На ЦЕЛУЮ команду меньше  На ОДНУ команду не считается  Так исторически сложилось что я проверяю на нулевой рез-т (не нажата не одна кнопка) и зацикливаю в начало
|
|
|
|
|
Nov 18 2011, 10:59
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(MaxiMuz @ Nov 18 2011, 13:00)  На ОДНУ команду не считается Если Вы пытатесь заставить GCC генерить вместо if(!(PINB & KeyMask)) одну команду SBRS (или SBRC), то у Вас ничего не получится. Хотя Atmel и утверждает, что система команд AVR ориентированна на язык Си, то компиляторописатели так не считают... В Вашем первом и втором случаях компилятор действует по шаблону: 1) берёт значение на регистр r24 (то, что Вы расположили некую переменную в регистр - изменит только источник данных: значение будет взято из другого регистра или из ОЗУ): 2) на регистре r24 вычисляет выражение; 3) при необходимости, из регистра r24 сохраняет вычисленное выражение; 4) сравнивает значение выражения (регистр r24) с нулём... Только ну очень хороший оптимизатор заменит эту последовательность одной командой. GCC так сделать не сможет. Для AVR я не знаю компилятора, в который встроен настолько сильный оптимизатор, что сможет повторить Вашу программу на ассемблере. Имхо, если компилятор с ЯВУ генерит код "съедающий" на 10-15% больше ресурсов, чем аналогичная программа на ассемблере, на сегодняшний день - это ОЧЕНЬ хороший компилятор. Заметьте - программа(!!!, причем обычно довольно большая), а не отдельный оператор.
|
|
|
|
|
Nov 18 2011, 16:06
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Цитата(Палыч @ Nov 18 2011, 13:59)  Если Вы пытатесь заставить GCC генерить вместо if(!(PINB & KeyMask)) одну команду SBRS (или SBRC), то у Вас ничего не получится. ..... с этим место собственно я разобрался. Цитата(_Pasha @ Nov 18 2011, 17:36)  ГЦЦ не умеет сливать ПП из разных точек входа в поток с одной командой возврата. ..... Не понятно о чем вы говорите Цитата(_Pasha @ Nov 18 2011, 17:36)  ...... А большую программу на асме еще написать надо, чтобы "сделать" современный Си на эти 10-15%. большая - маленькая зависит от типа МК. Привожу конкретный пример: Код http://www.radio.ru/archive/2010/07/a19.shtml программка писалась на асме под ATtiny2313, нехватило памяти программ под вторую таблицу мелодий для звонка. Если бы тогда писал на Си то вообще не хватилобы памяти на одну таблицу ! Это при том что я еще проводил оптимизацию программы в ассеблере  Цитата(Палыч @ Nov 18 2011, 14:17)  Да, согласен... Я собирался написать об операторе if ((--Cnt)==0) и команде DEC, но обширное обсуждение в этой теме оператора if(!(PINB & KeyMask)) сбило с мысли... Что хотели написать то ?
|
|
|
|
|
Nov 18 2011, 22:38
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(MaxiMuz @ Nov 18 2011, 18:06)  большая - маленькая зависит от типа МК. Привожу конкретный пример: Код http://www.radio.ru/archive/2010/07/a19.shtml программка писалась на асме под ATtiny2313, нехватило памяти программ под вторую таблицу мелодий для звонка. Если бы тогда писал на Си то вообще не хватилобы памяти на одну таблицу ! Это при том что я еще проводил оптимизацию программы в ассеблере  Поверьте старому С-шнику, избегающему по мере возможности написания программ на асме -- Вам показалось. Что Вы проводили оптимизацию этой ассемблерной программы. Бегло просмотрел программу из архива, даже толком не вникая в алгоритмы. Просто мелкая местная оптимизация — и несколько десятков байт как с куста. А если ещё вникнуть в алгоритмы, то и того более найдётся. Примеры: Код #ifndef OPTIMISED sbrc ModeR,BitModeAlrm rjmp Begin sbrc ModeR,BitModeWtch rjmp Begin #else;;; -2 sbrs ModeR,BitModeAlrm sbrc ModeR,BitModeWtch rjmp Begin #endif Там таких два места. На этой мелочи — уже 4 байта. Любой уважающий себя С-компилятор покраснел бы от стыда за такой код: Код ; Определение интервала 1 #ifndef OPTIMISED ; if ( MemdP <= Thr_AdP ) goto TCAdi11; else goto TCAdi12; cpi MemdPH,Thr_AdPH brcs TCAdi11 brne TCAdi12 cpi MemdPL,Thr_AdPL brcs TCAdi11 brne TCAdi12 #else;;; -4 bytes ; if MemdP >= (Thr_AdP + 1) ) goto TCAdi12 ldi temp, high( Thr_AdP + 1 ) cpi MemdPL, low( Thr_AdP + 1) cpc MemdPH, temp brcc TCAdi12 #endif Код #ifndef OPTIMISED ; if ( MemdP <= DeltaT ) goto TCA12; esle goto TCA11; cp MemdPH,DeltaTH brcs TCA12 brne TCA11 cp MemdPL,DeltaTL brcs TCA12 brne TCA11 #else ;;; -6 ; if ( DeltaT >= MemdP ) goto TCA11; cp DeltaTL,MemdPL cpc DeltaTH,MemdPH brcc TCA11 #endif И таких мест там не одно. Тут вообще что-то странное было. CODE ;_________ Запись таблицы регистрации нажатий в EEPROM ;* ;* CLI push temp2 push ZL push ZH #ifndef OPTIMISED clr ZL clr ZH b4: mov temp,ZL ldi temp2,low(Edata1) add temp,temp2 OUT EEAR,temp ldi temp2,low(data1) add ZL,temp2 LD temp,Z sub ZL,temp2 OUT EEDR,temp SBI EECR,EEMPE; SBI EECR,EEPE b5: sbic EECR,EEPE rjmp b5 cpi ZL,MaxCount*2-1 breq b6 ld temp,Z+ rjmp b4 b6: ldi temp,low(EMrk1) OUT EEAR,temp ldi temp,0xab OUT EEDR,temp SBI EECR,EEMPE; SBI EECR,EEPE
#else ;;; -14b
ldi ZL, low(data1) clr ZH ldi temp2, Edata1 b4: ld temp, Z+ rcall WrEE inc temp2 cpi temp2, MaxCount*2-1 brne b4 b6: ldi temp2,low(EMrk1) ldi temp,0xab rcall WrEE #endif
pop ZH pop ZL pop temp2 SEI
m9: CLR EnGen clr count m11: ;______ Задержка ldi temp,ZDelayL mov CL,temp rcall DelayTime Begin__: rjmp Begin
#ifdef OPTIMISED WrEE: OUT EEAR,temp2 OUT EEDR,tempЯ SBI EECR,EEMPE; SBI EECR,EEPE WrEEw: sbic EECR,EEPE rjmp WrEEw ret #endif Эта запись вообще дважды повторяется, в слегка разном окружении. Её всю в подпрограмму надо пустить. Ещё tiny2313 есть регистры GPIOR, аж три штуки. Все флаги успешно летят туда без увеличения объёма кода с незначителным увеличением времени. Освобождается два регистра, причём "верхних". Явно где-то поможет сократить код. Я бы постарался выделить регистровую пару Y под указатель на блок данных в DSEG, заменив все LDS/STS на LDD/STD. Ещё так на глаз минимум полсотни байт. Напоминаю — это всё не особо вникая в суть кода.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
Сообщений в этой теме
MaxiMuz "Оптимизация" в WinAVR и как с этим бороться Nov 16 2011, 18:07 Палыч Цитата(MaxiMuz @ Nov 16 2011, 22:07) хвал... Nov 16 2011, 18:45 MaxiMuz Цитата(Палыч @ Nov 16 2011, 21:45) А, вот... Nov 16 2011, 19:19  Палыч Цитата(MaxiMuz @ Nov 16 2011, 23:19) KeyM... Nov 16 2011, 20:10   MaxiMuz Цитата(Палыч @ Nov 16 2011, 23:10) Почему... Nov 16 2011, 21:06    aaarrr Цитата(MaxiMuz @ Nov 17 2011, 01:06) or ... Nov 16 2011, 21:19     MaxiMuz Цитата(aaarrr @ Nov 17 2011, 00:19) Это о... Nov 17 2011, 15:19      Палыч Цитата(MaxiMuz @ Nov 17 2011, 19:19) ... ... Nov 17 2011, 17:42      AHTOXA Цитата(MaxiMuz @ Nov 17 2011, 21:19) А ес... Nov 17 2011, 17:47      _Pasha Цитата(MaxiMuz @ Nov 17 2011, 19:19) Код ... Nov 18 2011, 06:25   _Pasha Цитата(Палыч @ Nov 18 2011, 13:59) Имхо, ... Nov 18 2011, 14:36    neiver Цитата(_Pasha @ Nov 18 2011, 18:36) и не ... Nov 18 2011, 14:45    ReAl Цитата(_Pasha @ Nov 18 2011, 16:36) ГЦЦ н... Nov 18 2011, 16:17     demiurg_spb Паша верно перечислил основные недочёты avr-gcc, с... Nov 18 2011, 17:13     neiver Цитата(ReAl @ Nov 18 2011, 20:17) Вот еще... Nov 18 2011, 17:23      MaxiMuz Цитата(neiver @ Nov 18 2011, 20:23) К сож... Nov 20 2011, 11:58       ReAl Цитата(MaxiMuz @ Nov 20 2011, 12:55) Хоте... Nov 20 2011, 12:23        MaxiMuz Цитата(ReAl @ Nov 20 2011, 15:23) .......... Nov 23 2011, 11:30         demiurg_spb Цитата(MaxiMuz @ Nov 23 2011, 15:30) где ... Nov 23 2011, 13:39          ReAl Тьху, ну конечно, -ffixed-reg
Что-то меня на = пот... Nov 23 2011, 21:19         AHTOXA КодCFLAGS += -ffixed-r16
CFLAGS += -ffixed-r18 Nov 23 2011, 14:40  Сергей Борщ QUOTE (MaxiMuz @ Nov 18 2011, 12:00) Это ... Nov 18 2011, 11:54 ReAl Цитата(MaxiMuz @ Nov 16 2011, 20:07) Код#... Nov 16 2011, 21:53 Genadi Zawidowski Код#define KeyMask (1<<Btn1)|... Nov 17 2011, 01:30 neiver Мда, можно вытащить ассемблерщика из ассемблера, н... Nov 17 2011, 08:19 Палыч Цитата(neiver @ Nov 17 2011, 12:19) integ... Nov 17 2011, 09:27 neiver Я к чему, тут про целочисленное расширение намекаю... Nov 18 2011, 05:25 MaxiMuz neiver , _Pasha да действительно, можно и так напи... Nov 18 2011, 08:38 neiver Цитата(MaxiMuz @ Nov 18 2011, 12:38) neiv... Nov 18 2011, 08:44 neiver GCC прекрасно может сгенерировать одну команду sbi... Nov 18 2011, 11:07 Палыч Цитата(neiver @ Nov 18 2011, 15:07) GCC п... Nov 18 2011, 11:17 ReAl Жаль. Nov 18 2011, 19:58 MaxiMuz Спасибо за ответы !
Опять я возвращаюсь к св... Nov 25 2011, 08:40 Сергей Борщ QUOTE (MaxiMuz @ Nov 25 2011, 11:40) Хоте... Nov 25 2011, 09:27  MaxiMuz Цитата(Сергей Борщ @ Nov 25 2011, 12:27) ... Nov 25 2011, 12:07   AHTOXA Цитата(MaxiMuz @ Nov 25 2011, 18:07) Вопр... Nov 25 2011, 14:16    ReAl Цитата(AHTOXA @ Nov 25 2011, 16:16) Какой... Nov 25 2011, 14:35     AHTOXA По-моему, на этот вопрос тоже уже ответили, и не р... Nov 25 2011, 19:17 ReAl Провёл маленький эксперимент.
Убрал все эти regist... Nov 25 2011, 20:32 MaxiMuz AHTOXA с вами не поспоришь
ReAl По сути , кусок... Nov 28 2011, 10:59 ReAl Цитата(MaxiMuz @ Nov 28 2011, 12:59) подо... Nov 28 2011, 14:16 sigmaN перед main воткните __attribute__ ((noreturn));
h... Nov 28 2011, 19:40 MaxiMuz Цитата(sigmaN @ Nov 28 2011, 22:40) перед... Jan 23 2012, 09:15 ReAl Для этого в AVR-GCC уже давно есть OS_main и OS_ta... Nov 28 2011, 20:17 sigmaN ну или так, да.
а ещё я из исходников библиотеки ... Nov 28 2011, 22:10 ILYAUL Цитата(sigmaN @ Nov 29 2011, 02:10) ну ил... Nov 29 2011, 04:15  ARV Цитата(ILYAUL @ Nov 29 2011, 08:15) ИМХО ... Jan 23 2012, 09:53 MaxiMuz При использовании int OS_main (void) компилятор вы... Jan 23 2012, 14:50 sigmaN warning это не error и по идее не должен приводить... Jan 24 2012, 02:07 MaxiMuz Цитата(sigmaN @ Jan 24 2012, 05:07) warni... Feb 2 2012, 11:49 _Pasha Таварисч не панимаит.
Кодint main(void) __... Feb 2 2012, 12:16 MaxiMuz Цитата(_Pasha @ Feb 2 2012, 15:16) Тавари... Feb 3 2012, 10:42  Сергей Борщ QUOTE (MaxiMuz @ Feb 3 2012, 12:42) Да... Feb 3 2012, 11:08 MaxiMuz Доброго времяни суток!
Не стал создавать отдел... Oct 16 2012, 18:35 Палыч Цитата(MaxiMuz @ Oct 16 2012, 22:35) здес... Oct 17 2012, 06:15  MaxiMuz Цитата(Палыч @ Oct 17 2012, 09:15) Это - ... Oct 17 2012, 12:11   Сергей Борщ В этом стандарте операция "&" выполн... Oct 17 2012, 12:59   Палыч Цитата(MaxiMuz @ Oct 17 2012, 16:11) стан... Oct 17 2012, 13:04 Genadi Zawidowski Используйте компилятор поновее (avr-gcc 4.7.2, avr... Oct 16 2012, 19:26
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|