Олег. 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Добрый всем вечер. Столкнулся со странным поведением компилятора в простой ситуации. Имеется простой код: volatile char data; int main(void){ if((data & 3) == 0) data++; return(0); } после компиляции имеем листинг: volatile char data; int main(void){ if((data & 3) == 0) 5e: 80 91 60 00 lds r24, 0x0060 62: 90 e0 ldi r25, 0x00 ; 0 64: 83 70 andi r24, 0x03 ; 3 66: 90 70 andi r25, 0x00 ; 0 68: 89 2b or r24, r25 6a: 29 f4 brne .+10 ; 0x76 <main+0x18> data++; 6c: 80 91 60 00 lds r24, 0x0060 70: 8f 5f subi r24, 0xFF ; 255 72: 80 93 60 00 sts 0x0060, r24 return(0); } 76: 80 e0 ldi r24, 0x00 ; 0 78: 90 e0 ldi r25, 0x00 ; 0 7a: 08 95 ret видно, что в данном случае константу компилятор интерпретирует как 16 битную и никакие приведения типа не помогают. Однако если изменить константу на значение 9, то всё нормально, вот листинг : volatile char data; int main(void){ if((data & 9) == 0) 5e: 80 91 60 00 lds r24, 0x0060 62: 89 70 andi r24, 0x09 ; 9 64: 29 f4 brne .+10 ; 0x70 <main+0x12> data++; 66: 80 91 60 00 lds r24, 0x0060 6a: 8f 5f subi r24, 0xFF ; 255 6c: 80 93 60 00 sts 0x0060, r24 return(0); } 70: 80 e0 ldi r24, 0x00 ; 0 72: 90 e0 ldi r25, 0x00 ; 0 74: 08 95 ret при константе равной 15 опять воспринимает как 16 битное. Путём подбора констант заметил, что до 8 включительно воспринимает как 16 битное, затем с 9 как 8 битное. То есть какая то зависимость от значения. Вопрос . Кто нибудь сталкивался с подобным? Может это ошибка в компиляторе хотя она не очень значительная, ведь с точки зрения кода всё правильно, только имеют место ненужные команды. В слуае критичности по размеру кода и количеству таких ситуаций несколько увеличивается размер кода. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Какая версия компилятора? Какой уровень оптимизации? А а если так: volatile unsigned char data; if ( !(data&3U) ) {...} или if ( !(data&(unsigned char)3) ) {...} или if ( !(unsigned char)(data&(unsigned char)3) ) {...} Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Олег. 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Какая версия компилятора? Какой уровень оптимизации? А а если так: volatile unsigned char data; if ( !(data&3U) ) {...} или if ( !(data&(unsigned char)3) ) {...} или if ( !(unsigned char)(data&(unsigned char)3) ) {...} Версия компилятор 20081205, оптимизация Os . К сожалению приведение типа не помогает, пробовал по разному. От версии компилятора помоему это не зависит Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба и в версии 20090313 аналогично :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Гнусненько... явная драка между integral promotion и оптимизацией. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Столкнулся со странным поведением компилятора в простой ситуации.Увы, есть такая беда. Радикально помогает только введение промежуточной переменной. volatile char data; void foo(void){ char tmp = data & 3; if(tmp == 0) data++; } И уж она-то будет соптимизиована (т.е. лишнее место занимать не будет, а операции станут 8-битными) .global foo .type foo, @function foo: /* prologue: frame size=0 */ /* prologue end (size=0) */ lds r24,data andi r24,lo8(3) brne .L4 lds r24,data subi r24,lo8(-(1)) sts data,r24 .L4: ret /* epilogue: frame size=0 */ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Увы, есть такая беда. Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то и вычисление логических выражений не оптимизируется. В данном случае тип результата логического выражения будет int, а надо бы int8_fast_t :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то и вычисление логических...Мысль глубокая. И похожа на правду. Но ведь всегда ожидаешь лучшего. Будем учитывать сей факт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 28 марта, 2009 Опубликовано 28 марта, 2009 · Жалоба Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то и вычисление логических выражений не оптимизируется. В данном случае тип результата логического выражения будет int, а надо бы int8_fast_t :(В данном случае volatile ни при чём, без него тот же эффект, только в профиль. char data; void foo(void) { char tmp = data & 3; if(tmp == 0) data++; } void moo(void){ if( (data & 3) == 0) data++; } foo: lds r25,data mov r24,r25 andi r24,lo8(3) brne .L4 subi r25,lo8(-(1)) sts data,r25 .L4: ret moo: lds r18,data mov r24,r18 clr r25 sbrc r24,7 com r25 andi r24,lo8(3) andi r25,hi8(3) or r24,r25 brne .L13 subi r18,lo8(-(1)) sts data,r18 .L13: ret Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 122 29 марта, 2009 Опубликовано 29 марта, 2009 · Жалоба Увы, есть такая беда.И "они" о ней знают:Known AVR GCC bug Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 29 марта, 2009 Опубликовано 29 марта, 2009 · Жалоба Недавно тоже столкнулся с этим. Пробовал разными версиями компиляторов - результат один и тот же. Так же методом проб и ошибок выяснил, что наличие этих "лишних движений" может зависить от значений констант, иногда от порядка проведения операций над переменными наличия скобок. Введение промежуточных переменных чаще всего помогало, но не всегда. В общем решил проблему с помощью инлайн-ассемблера, конечно это заморочно, но зато добился таки полного отсутствия мусора в критических секциях. Кстати, наблюдал еще одну фишку - бессмысленное перекладывание переменных из регистра в регистр и обратно, метод устранения тот же, что и для вышеописанного бага - введение временных переменых и разбиение сложных выражений на простые операции. Четкой закономерности найти не удалось. Да, и еще этот феномен как правило сопровождается сохранением в стеке регистров, без которых можно было-бы обойтись, что может здорово увеличить размер кода и время выполнения небольших функций. В данных случаях volatile-переменные нигде не использовал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться