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

При максимальной оптимизации - ошибка

IAR ARM 6.50.3.4757

сам код, упрощен до максимума

extern void foo(uint8_t b);

uint8_t glb;

void tst(void)
{
  static uint8_t sv;
  uint8_t tmp;

  if (sv != (glb & (1 << 6))) {
    sv = (glb & (1 << 6));
    tmp = (sv)? 0x00 : 0xFF;
    foo(tmp);
  }

}

int main()
{ 
  while(1) {
    
    tst();
    
  }
}

листинг для оптимизации High Balanced

     27          void tst(void)
     28          {
     29            static uint8_t sv;
     30            uint8_t tmp;
     31          
     32            if (sv != (glb & (1 << 6))) {
   \                     `tst`:
   \   00000000   0x....             LDR.N    R0,??DataTable3_1
   \   00000002   0x7801             LDRB     R1,[R0, #+0] // glb
   \   00000004   0x7842             LDRB     R2,[R0, #+1] // sv
   \   00000006   0xF001 0x0340      AND      R3,R1,#0x40 // R3 = glb & (1 << 6)
   \   0000000A   0x429A             CMP      R2,R3
   \   0000000C   0xD006             BEQ.N    ??tst_0
     33              sv = (glb & (1 << 6));
   \   0000000E   0x7041             STRB     R1,[R0, #+1] // sv = glb а не sv = glb & (1 << 6)
     34              tmp = (sv)? 0x00 : 0xFF;
   \   00000010   0x0648             LSLS     R0,R1,#+25
   \   00000012   0xBF4C             ITE      MI 
   \   00000014   0x2000             MOVMI    R0,#+0
   \   00000016   0x20FF             MOVPL    R0,#+255
     35              foo(tmp);
   \   00000018   0x.... 0x....      B.W      foo
     36            }
     37          
     38          }
   \                     ??tst_0:
   \   0000001C   0x4770             BX       LR               ;; return

листинг для оптимизации Medium

     27          void tst(void)
     28          {
     29            static uint8_t sv;
     30            uint8_t tmp;
     31          
     32            if (sv != (glb & (1 << 6))) {
   \                     `tst`:
   \   00000000   0x....             LDR.N    R0,??DataTable2_1
   \   00000002   0x7801             LDRB     R1,[R0, #+0] // glb
   \   00000004   0x7842             LDRB     R2,[R0, #+1] // sv
   \   00000006   0xF001 0x0340      AND      R3,R1,#0x40 // R3 = glb & (1 << 6)
   \   0000000A   0x429A             CMP      R2,R3
   \   0000000C   0xD008             BEQ.N    ??tst_0
     33              sv = (glb & (1 << 6));
   \   0000000E   0xF011 0x0140      ANDS     R1,R1,#0x40 // R1 = glb & (1 << 6)
   \   00000012   0x7041             STRB     R1,[R0, #+1] // sv = glb & (1 << 6) как надо
     34              tmp = (sv)? 0x00 : 0xFF;
   \   00000014   0xD001             BEQ.N    ??tst_1
   \   00000016   0x2000             MOVS     R0,#+0
   \   00000018   0xE000             B.N      ??tst_2
   \                     ??tst_1:
   \   0000001A   0x20FF             MOVS     R0,#+255
     35              foo(tmp);
   \                     ??tst_2:
   \   0000001C   0x.... 0x....      B.W      foo
     36            }
     37          
     38          }
   \                     ??tst_0:
   \   00000020   0x4770             BX       LR               ;; return

листинг для оптимизации High Balanced и дополнительной переменной

extern void foo(uint8_t b);

uint8_t glb;

void tst(void)
{
  static uint8_t sv;
  uint8_t tmp, tmp2;

  tmp2 = glb & (1 << 6);
  if (sv != tmp2) {
    sv = tmp2;
    tmp = (sv)? 0x00 : 0xFF;
    foo(tmp);
  }

}

int main()
{ 
  while(1) {
    
    tst();
    
  }
}



     27          void tst(void)
     28          {
     29            static uint8_t sv;
     30            uint8_t tmp, tmp2;
     31          
     32            tmp2 = glb & (1 << 6);
   \                     `tst`:
   \   00000000   0x....             LDR.N    R0,??DataTable3_1
   \   00000002   0x7801             LDRB     R1,[R0, #+0] // glb
     33            if (sv != tmp2) {
   \   00000004   0x7843             LDRB     R3,[R0, #+1] // sv
   \   00000006   0xF001 0x0140      AND      R1,R1,#0x40 // R1 = glb & (1 << 6)
   \   0000000A   0x428B             CMP      R3,R1
   \   0000000C   0xD006             BEQ.N    ??tst_0
     34              sv = tmp2;
   \   0000000E   0x7041             STRB     R1,[R0, #+1] // sv = glb & (1 << 6) как надо
     35              tmp = (sv)? 0x00 : 0xFF;
   \   00000010   0x2900             CMP      R1,#+0
   \   00000012   0xBF14             ITE      NE 
   \   00000014   0x2000             MOVNE    R0,#+0
   \   00000016   0x20FF             MOVEQ    R0,#+255
     36              foo(tmp);
   \   00000018   0x.... 0x....      B.W      foo
     37            }
     38          
     39          }
   \                     ??tst_0:
   \   0000001C   0x4770             BX       LR               ;; return

Почему так, где ошибка?

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


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

Вы уточните, где вы видите ошибку, просто так просматривать сотню строк листинга вряд ли кому-то интересно.

А, вижу комментарии. Ничего криминального компилятор не вычудил, ошибок нет.

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


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

4 minutes ago, Arlleex said:

Вы уточните, где вы видите ошибку, просто так просматривать сотню строк листинга вряд ли кому-то интересно.

отмечено коментариями в листингах. В одном случае в переменную sv записывается (glb & (1 << 6)) (как надо), в другом glb (не правильно).

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


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

1 минуту назад, const сказал:

отмечено коментариями в листингах. В одном случае в переменную sv записывается (glb & (1 << 6)) (как надо), в другом glb (не правильно).

С токи зрения наблюдаемого поведения Си-программы она полностью корректна. По сути будете получать один и тот же результат.

Подумайте: если бы при оптимизации компилятор все равно транслировал "в лоб" все написанное, на кой были бы нужны все эти хитрые уровни оптимизаций?

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


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

@Arlleex

Программа корректна, а результат компиляции нет.

Не изменяя программу, а только уровень оптимизации, получаем разный результат (алгоритм).

А добавляя промежуточную переменную в "нерабочую" оптимизацию, получаем корректный результат.

 

И еще.

IAR ARM 8.30.1.17148 - компилирует правильно

Изменено пользователем const

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


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

24 minutes ago, const said:

Программа корректна, а результат компиляции нет.

в "упрощённой" версии и glb и sv всегда равны 0, не понятно почему целиком всё не выкинул, а только присвоение "соптимизировал".

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


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

13 minutes ago, _pv said:

в "упрощённой" версии и glb и sv всегда равны 0, не понятно почему целиком всё не выкинул, а только присвоение "соптимизировал".

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

Что по вашему надо добавить, что бы код для компилятора был "правильный"?

Проект на 1000+ строк не вижу надобности выкладывать. Проблему изолировал.

вот что получается когда делаю переменную glb volatile (оптимизация High Balanced)

     27          void tst(void)
     28          {
     29            static uint8_t sv;
     30            uint8_t tmp;
     31          
     32            if (sv != (glb & (1 << 6))) {
   \                     `tst`:
   \   00000000   0x....             LDR.N    R0,??DataTable3_1
   \   00000002   0x7841             LDRB     R1,[R0, #+1]
   \   00000004   0x7802             LDRB     R2,[R0, #+0]
   \   00000006   0xF002 0x0240      AND      R2,R2,#0x40
   \   0000000A   0x4291             CMP      R1,R2
   \   0000000C   0xD007             BEQ.N    ??tst_0
     33              sv = (glb & (1 << 6));
   \   0000000E   0x7801             LDRB     R1,[R0, #+0] // операция "& (1 << 6)" игнорируется
   \   00000010   0x7041             STRB     R1,[R0, #+1]
     34              tmp = (sv)? 0x00 : 0xFF;
   \   00000012   0x0648             LSLS     R0,R1,#+25
   \   00000014   0xBF4C             ITE      MI 
   \   00000016   0x2000             MOVMI    R0,#+0
   \   00000018   0x20FF             MOVPL    R0,#+255
     35              foo(tmp);
   \   0000001A   0x.... 0x....      B.W      foo
     36            }
     37          
     38          }
   \                     ??tst_0:
   \   0000001E   0x4770             BX       LR               ;; return

 

Изменено пользователем const

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


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

1 час назад, const сказал:

IAR ARM 6.50.3.4757

Я бы не стал пользоваться IAR-ами до 7.80.4. Зачем вам такое старьё???

(да и с более новыми в некоторых случаях нужно быть осторожным; но по-крайней мере если не используется FPU и некоторые intrinsinc-и, то в 7.80.4 багов не замечал)

21 минуту назад, const сказал:

Проект на 1000+ строк не вижу надобности выкладывать. Проблему изолировал.

1 час назад, const сказал:

Почему так, где ошибка?

Как версия (что может быть):  где-то в этих 1000+ строках у вас объявлена или определена другая переменная с таким же именем (glb), но другого типа. Возможно.

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


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

@jcxz нет, переменная с таким именем одна. Ну а как же мой "изолированный" пример, разве такое поведение компилятора корректно?

З.Ы. Оно соответствует поведению в моем проекте.

Изменено пользователем const

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


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

3 минуты назад, const сказал:

@jcxz нет, переменная с таким иминем одна. Ну а как же мой "изолированный" пример, разве такое поведение компилятора корректно?

А кто вас заставляет пользоваться неисправным инструментом, вместо того, чтобы взять исправный?  :wacko2:

6 минут назад, const сказал:

нет, переменная с таким именем одна.

Может быть и не переменная, а например - макрос. Ну или любой объект с таким именем.

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


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

42 минуты назад, const сказал:

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

Разнятся исходные условия, разнится и результат компиляции. При этом наблюдаемое поведение программы не меняется, результат компиляции корректный во всех случаях.

42 минуты назад, const сказал:

Да и более свежий компилятор дает правильный код.

Этот компилятор тоже дает правильный код. Результатом работы (наблюдаемым поведением) является значения аргумента вызова функции foo(). Значения переменных sv, tmp не являются наблюдаемым поведением, поэтому их значение может быть любым (их может вообще не быть в исполняемом коде), пока в foo() передается правильное значение.

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


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

@jcxz не заставляют. После найденой ошибки буду переходить на более свежий IAR.

Имя неповторимое (оно не glb). Проблема же в неправильном присвоении значения переменной sv.

Вопрос задал так как решил, что что-то упускаю. Видемо и в самом деле компилятор глючит.

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


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

43 минуты назад, const сказал:

вот что получается когда делаю переменную glb volatile

Что просите, то и получаете.

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


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

@Сергей Борщ

При повторном вызове ф-ции tst при неизменной переменной glb, ф-ция foo вызываться не должна

2 minutes ago, Сергей Борщ said:

Что просите, то и получаете.

я прошу sv = glb & (1 << 6)

а получаю sv = glb

Изменено пользователем const

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


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

19 минут назад, Сергей Борщ сказал:

Разнятся исходные условия, разнится и результат компиляции. При этом наблюдаемое поведение программы не меняется, результат компиляции корректный во всех случаях.

Результат работы программы при "high balanced" оптимизации и при "medium" будет разный. А значит компилятор неправ. Как бы он ни оптимизировал код, результат выполнения меняться не должен.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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