Jump to content

    
Sign in to follow this  
Arlleex

Keil: оптимизация -O3 + -Ot ломает логику программы

Recommended Posts

Приветствую!

 

Keil 5.28.0.0, оптимизация -O3 и установлен чекбокс оптимизации по скорости -Ot.

Есть функция

#define RBTYPE      u8
#define RB_BUF_SIZE (64 + 1)


typedef struct
{
  volatile s32 rp, wp;
  RBTYPE buf[RB_BUF_SIZE];
}sRingBuf;


s32 rb_Read(sRingBuf *rb, RBTYPE buf[], s32 len)
{
  s32 rlen = rb_GetBusy(rb);
  if(rlen > len) rlen = len;
  len = rlen; s32 rp = rb->rp;
  for(; len-- > 0; rp &= (rp - RB_BUF_SIZE) >> 31)
    *buf++ = rb->buf[rp++];
  rb->rp = rp; return rlen;
}

 

На неоптимизирующей сборке все отлично.

На -O3 + -Ot получаю следующий выхлоп:

0x08001634 B430      PUSH     {r4-r5}
0x08001636 4605      MOV      r5,r0
   114:   s32 t = rb->wp; 
0x08001638 6840      LDR      r0,[r0,#0x04]
   115:   if((t -= rb->rp) < 0) 
0x0800163A 682B      LDR      r3,[r5,#0x00]
   115:   if((t -= rb->rp) < 0) 
0x0800163C 1AC0      SUBS     r0,r0,r3
    44: { 
    45:   s32 rlen = rb_GetBusy(rb); 
0x0800163E D500      BPL      0x08001642
0x08001640 3041      ADDS     r0,r0,#0x41
    46:   if(rlen > len) rlen = len; 
0x08001642 4290      CMP      r0,r2
0x08001644 DC11      BGT      0x0800166A
    47:   len = rlen; s32 rp = rb->rp; 
    48: #if (pwroftwo(RB_BUF_SIZE)) 
    49:   for(; len-- > 0; rp &= RB_BUF_SIZE - 1) 
    50: #else 
0x08001646 682C      LDR      r4,[r5,#0x00]
    51:   for(; len-- > 0; rp &= (rp - RB_BUF_SIZE) >> 31) 
    52: #endif 
0x08001648 2800      CMP      r0,#0x00
0x0800164A DD0B      BLE      0x08001664
0x0800164C 4603      MOV      r3,r0
    53:     *buf++ = rb->buf[rp++]; 
0x0800164E 192A      ADDS     r2,r5,r4
0x08001650 7A12      LDRB     r2,[r2,#0x08]
0x08001652 700A      STRB     r2,[r1,#0x00]
0x08001654 4622      MOV      r2,r4
0x08001656 3A41      SUBS     r2,r2,#0x41
0x08001658 17D2      ASRS     r2,r2,#31
0x0800165A 4022      ANDS     r2,r2,r4
0x0800165C 1C54      ADDS     r4,r2,#1
0x0800165E 1C49      ADDS     r1,r1,#1
0x08001660 1E5B      SUBS     r3,r3,#1
0x08001662 D1F4      BNE      0x0800164E
    54:   rb->rp = rp; 
    55:   return rlen; 
0x08001664 602C      STR      r4,[r5,#0x00]
    56: } 
    57:  
    58: s32 rb_Write(sRingBuf *rb, RBTYPE buf[], s32 len) 
0x08001666 BC30      POP      {r4-r5}
0x08001668 4770      BX       lr

 

Интересует сам цикл:

Цитата

0x0800164E 192A      ADDS     r2,r5,r4
0x08001650 7A12      LDRB     r2,[r2,#0x08]
0x08001652 700A      STRB     r2,[r1,#0x00]
0x08001654 4622      MOV      r2,r4
0x08001656 3A41      SUBS     r2,r2,#0x41
0x08001658 17D2      ASRS     r2,r2,#31
0x0800165A 4022      ANDS     r2,r2,r4
0x0800165C 1C54      ADDS     r4,r2,#1
0x0800165E 1C49      ADDS     r1,r1,#1
0x08001660 1E5B      SUBS     r3,r3,#1
0x08001662 D1F4      BNE      0x0800164E

 

Как так??? С какого лешего сначала выполняется rp &= (rp - RB_BUF_SIZE) >> 31, а лишь потом постиндексация rp при записи в buf?

Ведь после выражения *buf++ = rb->buf[rp++]; (согласно стандарту) есть точка следования, и все побочные действия вычислений уже произошли.

Лишь потом должна выполниться операция очистки по маске (третий аргумент цикла)...

Из-за этого косяка у меня неправильно обрабатывается кольцо на максимальной оптимизации.

 

Если сделать тупо

for(; len-- > 0; rp &= (rp - RB_BUF_SIZE) >> 31)
{
  *buf++ = rb->buf[rp];
  ++rp;
}

то все работает как положено.

 

если сделать rp как volatile, то все будет тоже как положено.

 

Что это? Глюк оптимизации или я дурак?

Share this post


Link to post
Share on other sites
3 minutes ago, Arlleex said:

Компилятор armcc v5.06 update 6 (build 750).

Он уже несколько лет не обновлялся, числится как legacy. Поэтому всякое возможно ;)

Переходите на v6

Share this post


Link to post
Share on other sites
32 минуты назад, Forger сказал:

Он уже несколько лет не обновлялся, числится как legacy. Поэтому всякое возможно ;)

Переходите на v6

Эх... Долго я с ним (armcc) дружил:boredom:

На v6 все работает как положено, спасибо.

Share this post


Link to post
Share on other sites

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

По нажатию "Go to definition" внизу слева пишется No information available for the selected symbol. Галка "Browse information" в настройках стоит.

Может, знает кто, в чем проблема?

Share this post


Link to post
Share on other sites
8 минут назад, Arlleex сказал:

Что на -O1? Появляется надпись или нет? Или Вы про баг компайлера?

Так про оптимизацию же. Может, на -o3 нечего показывать по причине отсутствия. 

Share this post


Link to post
Share on other sites
2 минуты назад, ViKo сказал:

Так про оптимизацию же. Может, на -o3 нечего показывать по причине отсутствия. 

Да как банальный #define A 100 может выкидываться оптимизатором? И при чем тут он... К тому же я сейчас на -O0 вообще, поскольку отлаживаюсь.

То бишь не только переходы по функциям не работают, не работают вообще любый переходы по символам, будь то функции или defines, typedefs и т.д.

Share this post


Link to post
Share on other sites
21 minutes ago, ViKo said:

Keil рекомендует использовать -o1.

В дебаге использую -o1, для отлаживаемых модулей иногда временно включаю -o0 (через свойства файла), порой приходится, компилятор дюже умный, режет очень много даже на -o1

В релизе выбира "balanced".

 

ps В обеих сборках рекомендую везде ставить галку "One ELF section per function", сильно сокращает код, убирая неиспользуемые функции их объектных файлов.

Share this post


Link to post
Share on other sites
29 минут назад, ViKo сказал:

Keil рекомендует использовать -o1.
http://www.keil.com/appnotes/files/apnt_298.pdf

Вряд ли оно, но почитайте, вдруг поможет.

Дело в том, что оптимизация не влияет и влиять не может на навигацию по проекту, так как она, скорее всего, работает просто как file search.

А с этой красной надписью встречался и раньше, возможно именно поэтому забил на этот компилятор и работал с armcc...

 

10 минут назад, Forger сказал:

В дебаге использую -o1...

Я дебажу в -O0, релиз в -O3 + -Ot (либо просто -O3). Но в новом компиляторе появилась balanced, поэтому юзать буду ее.

 

12 минут назад, Forger сказал:

ps В обеих сборках рекомендую везде ставить галку "One ELF section per function", сильно сокращает код, убирая неиспользуемые функции их объектных файлов.

Всегда так и было, собственно:smile:

Share this post


Link to post
Share on other sites
4 minutes ago, Arlleex said:

Я дебажу в -O0, релиз в -O3 + -Ot (либо просто -O3). Но в новом компиляторе появилась balanced, поэтому юзать буду ее.:smile:

Если проект жирный, то -o0 для всех файлов делает его очень объемным, долго зашивается,

поэтому только для отлаживаемых файлов временно отключают оптимизацию (ставлю -o0)

Ксатати -o1, 02 и -o3 и др уже мало отличаются, честно говоря, особой разницы по производительности (загрузка задач в %) тоже не заметил, равно как и по объему кода и озу.

Однако, -o0 делает код сильно жирным и тормозным, разница заметна. Удобно для отладки. Если и с такой оптимизацией производительности хватает, то на остальных оптимизациях и подавно хвататит ))

Share this post


Link to post
Share on other sites
14 минут назад, Forger сказал:

Если и с такой оптимизацией производительности хватает, то на остальных оптимизациях и подавно хвататит ))

В 90% случаев я оптимизацию ставлю лишь для защиты от модернизации бинарника ПО третьими лицами, а не для скорости...

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

А любителям реверса и -O3 хватит, чтобы вдоволь наиграться и сесть в лужу. К тому же, как мне известно, прошивки попадают к несильно компетентным людям.

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

Поэтому сегодня они стырили бинарь и он работает на другой железке, а завтра мы обновляем ПО и клоны отвалились.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this