Перейти к содержанию
    

Странное поведение компилятора AVRGCC в простой ситуации

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

 

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

 

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 битное. То есть какая то зависимость от значения.

Вопрос . Кто нибудь сталкивался с подобным? Может это ошибка в компиляторе хотя она не очень значительная, ведь с точки зрения

кода всё правильно, только имеют место ненужные команды. В слуае критичности по размеру кода и количеству таких ситуаций несколько увеличивается размер кода.

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какая версия компилятора?

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

 

А а если так:

volatile unsigned char data;

if ( !(data&3U) ) {...}

или

if ( !(data&(unsigned char)3) ) {...}

или

if ( !(unsigned char)(data&(unsigned char)3) ) {...}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какая версия компилятора?

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

 

А а если так:

volatile unsigned char data;

if ( !(data&3U) ) {...}

или

if ( !(data&(unsigned char)3) ) {...}

или

if ( !(unsigned char)(data&(unsigned char)3) ) {...}

 

Версия компилятор 20081205, оптимизация Os . К сожалению приведение типа не помогает, пробовал по разному. От версии компилятора помоему это не зависит

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Столкнулся со странным поведением компилятора в простой ситуации.
Увы, есть такая беда.

Радикально помогает только введение промежуточной переменной.

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 */

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Увы, есть такая беда.

 

Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то  и вычисление логических выражений не оптимизируется. В данном случае тип результата логического выражения будет int, а надо бы int8_fast_t :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я понял такую вещь, что это не беда никакая. Раз volatile не оптимизируется, то  и вычисление логических...
Мысль глубокая. И похожа на правду. Но ведь всегда ожидаешь лучшего. Будем учитывать сей факт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я понял такую вещь, что это не беда никакая. Раз 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Увы, есть такая беда.
И "они" о ней знают:Known AVR GCC bug

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

В данных случаях volatile-переменные нигде не использовал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...