надстройку разрушает r0 поэтому мы теряем значение с и должны перезагрузить его
ldr r2, .L2+4 get address of .data location of *c from .text
...
ldr r2, [r2] ; r2 = pointer to c
...
ldr r0, [r2] ; r0 = c
...
add r0, ip, r0 ; this destroys r0 it no longer holds the value of c
...
ldr r2, [r2] ; need the value of c again to add to b
Интересные да, что различные версии GCC и/или различных оптимизаций выбрать различные сочетания регистров. Но такая же последовательность с дополнительной нагрузкой. Главное здесь почему это сделать:
add r0, ip, r0
str r0, [r3]
вместо
add ip, ip, r0
str ip, [r3]
, а затем не нужно повторно нагрузки С?
Нюанс оптимизатора глазок - это мое предположение. Другой связанный с этим вопрос заключается в том, зачем начинать возиться с ** b до того, как закончите с сохранением? Если бы он не сделал этого, у него был бы еще один бесплатный реестр. (Без сомнения, другая оптимизация)
Еще один интересный момент, по крайней мере один из моих GCC компиляторов производит это:
00001000 <_start>:
1000: eaffffff b 1004 <fun>
00001004 <fun>:
1004: e59f2034 ldr r2, [pc, #52] ; 1040 <fun+0x3c>
1008: e59f3034 ldr r3, [pc, #52] ; 1044 <fun+0x40>
100c: e5921000 ldr r1, [r2]
1010: e5932000 ldr r2, [r3]
1014: e591c000 ldr ip, [r1]
1018: e5920000 ldr r0, [r2]
101c: e59f3024 ldr r3, [pc, #36] ; 1048 <fun+0x44>
1020: e08c0000 add r0, ip, r0
1024: e5933000 ldr r3, [r3]
1028: e5810000 str r0, [r1]
102c: e5922000 ldr r2, [r2]
1030: e5931000 ldr r1, [r3]
1034: e0812002 add r2, r1, r2
1038: e5832000 str r2, [r3]
103c: e12fff1e bx lr
1040: 00009054 andeq r9, r0, r4, asr r0
1044: 00009050 andeq r9, r0, r0, asr r0
1048: 0000904c andeq r9, r0, ip, asr #32
Disassembly of section .bss:
0000904c <__bss_start>:
904c: 00000000 andeq r0, r0, r0
00009050 <c>:
9050: 00000000 andeq r0, r0, r0
00009054 <a>:
9054: 00000000 andeq r0, r0, r0
С или без обнаженный вы получите то же самое, почему НКУ так отчаянно использовать каждый одноразовый регистр и не использовать стек, например. Обратите внимание, что в вашей компиляции он добавляет, а затем сохраняет его в моей, он добавляет затем нагрузки * b, затем сохраняет. Он не только перемещал нагрузку ** b в последовательности, но также загружал * b вверх до завершения результата a.
так что голая вещь не помогла здесь, кроме как удалить bx lr в конце функции. то, что вы можете/должны попробовать, это -fdump-rtl-all в командной строке gcc (делает много файлов) и прокладывать путь через них, чтобы увидеть, где начался gcc и где он изменил ситуацию, и, возможно, это определит вывод или если а не в компиляторе, а затем в бэкэнде оптимизатор подглядывает переделанные вещи и не уверен, что командная строка должна сбросить.
Итог заключается в том, что в то время как в течение длительного времени (десятки тысяч, сотни тысяч, миллионы строк кода) компилятор/optmizer будет превосходить человека, но очень легко поймать изолированные части оптимизированного код, который можно настроить вручную, чтобы быть немного «лучше» в зависимости от вашего определения лучше. Обратите внимание, что меньшее количество инструкций не всегда лучше.
Вы должны попробовать более высокий уровень оптимизации, '-O2' или' -O3'. – Jester
Я пробовал, это тот же код = ( – Mike
Тогда это просто пропущенная оптимизация. Компиляторы не идеальны. Один на [gcc.godbolt.org] (http://gcc.godbolt.org) создает другой код. – Jester