реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Странное поведение компилятора AVRGCC в простой ситуации
Олег.
сообщение Mar 28 2009, 13:54
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 29-12-04
Пользователь №: 1 738



Добрый всем вечер.

Столкнулся со странным поведением компилятора в простой ситуации. Имеется простой код:

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 битное. То есть какая то зависимость от значения.
Вопрос . Кто нибудь сталкивался с подобным? Может это ошибка в компиляторе хотя она не очень значительная, ведь с точки зрения
кода всё правильно, только имеют место ненужные команды. В слуае критичности по размеру кода и количеству таких ситуаций несколько увеличивается размер кода.
Спасибо.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Mar 28 2009, 14:14
Сообщение #2


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Какая версия компилятора?
Какой уровень оптимизации?

А а если так:
volatile unsigned char data;
if ( !(data&3U) ) {...}
или
if ( !(data&(unsigned char)3) ) {...}
или
if ( !(unsigned char)(data&(unsigned char)3) ) {...}


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Олег.
сообщение Mar 28 2009, 14:34
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 19
Регистрация: 29-12-04
Пользователь №: 1 738



Цитата(demiurg_spb @ Mar 28 2009, 17:14) *
Какая версия компилятора?
Какой уровень оптимизации?

А а если так:
volatile unsigned char data;
if ( !(data&3U) ) {...}
или
if ( !(data&(unsigned char)3) ) {...}
или
if ( !(unsigned char)(data&(unsigned char)3) ) {...}


Версия компилятор 20081205, оптимизация Os . К сожалению приведение типа не помогает, пробовал по разному. От версии компилятора помоему это не зависит
Go to the top of the page
 
+Quote Post
ARV
сообщение Mar 28 2009, 14:49
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



и в версии 20090313 аналогично smile.gif


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 28 2009, 15:16
Сообщение #5


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Гнусненько... явная драка между integral promotion и оптимизацией.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 28 2009, 16:10
Сообщение #6


Нечётный пользователь.
******

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



Цитата(Олег. @ Mar 28 2009, 15:54) *
Столкнулся со странным поведением компилятора в простой ситуации.
Увы, есть такая беда.
Радикально помогает только введение промежуточной переменной.
Код
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 */


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 28 2009, 16:54
Сообщение #7


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(ReAl @ Mar 28 2009, 20:10) *
Увы, есть такая беда.


Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то  и вычисление логических выражений не оптимизируется. В данном случае тип результата логического выражения будет int, а надо бы int8_fast_t sad.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Mar 28 2009, 18:49
Сообщение #8


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Pasha @ Mar 28 2009, 19:54) *
Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то  и вычисление логических...
Мысль глубокая. И похожа на правду. Но ведь всегда ожидаешь лучшего. Будем учитывать сей факт.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 28 2009, 20:46
Сообщение #9


Нечётный пользователь.
******

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



Цитата(_Pasha @ Mar 28 2009, 18:54) *
Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то  и вычисление логических выражений не оптимизируется. В данном случае тип результата логического выражения будет int, а надо бы int8_fast_t sad.gif
В данном случае 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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 29 2009, 00:55
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(ReAl @ Mar 28 2009, 18:10) *
Увы, есть такая беда.
И "они" о ней знают:Known AVR GCC bug


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
injen-d
сообщение Mar 29 2009, 11:07
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 91
Регистрация: 10-10-07
Из: Воронежа
Пользователь №: 31 250



Недавно тоже столкнулся с этим. Пробовал разными версиями компиляторов - результат один и тот же. Так же методом проб и ошибок выяснил, что наличие этих "лишних движений" может зависить от значений констант, иногда от порядка проведения операций над переменными наличия скобок. Введение промежуточных переменных чаще всего помогало, но не всегда. В общем решил проблему с помощью инлайн-ассемблера, конечно это заморочно, но зато добился таки полного отсутствия мусора в критических секциях.

Кстати, наблюдал еще одну фишку - бессмысленное перекладывание переменных из регистра в регистр и обратно, метод устранения тот же, что и для вышеописанного бага - введение временных переменых и разбиение сложных выражений на простые операции. Четкой закономерности найти не удалось. Да, и еще этот феномен как правило сопровождается сохранением в стеке регистров, без которых можно было-бы обойтись, что может здорово увеличить размер кода и время выполнения небольших функций.
В данных случаях volatile-переменные нигде не использовал.


--------------------
- Бендер, ты же робот, зачем тебе пить пиво?
- Незачем! Я могу бросить в любой момент!
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 15:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01467 секунд с 7
ELECTRONIX ©2004-2016