) превращает их в кучу переменных SSA, если это возможно. Так что, по крайней мере, в clang «антиоптимизация» не происходит, обычные оптимизации просто отключены.

бираю этот код на llvm clang Apple LLVM версии 8.0.0 (clang-800.0.42.1):

int main() {
    float a=0.151234;
    float b=0.2;
    float c=a+b;
    printf("%f", c);
}

Я скомпилировал без спецификаций -O, но я также попытался с -O0 (дает то же самое) и -O2 (фактически вычисляет значение и сохраняет его предварительно вычисленным)

В результате разборка выглядит следующим образом (я удалил части, которые не имеют отношения)

->  0x100000f30 <+0>:  pushq  %rbp
    0x100000f31 <+1>:  movq   %rsp, %rbp
    0x100000f34 <+4>:  subq   $0x10, %rsp
    0x100000f38 <+8>:  leaq   0x6d(%rip), %rdi       
    0x100000f3f <+15>: movss  0x5d(%rip), %xmm0           
    0x100000f47 <+23>: movss  0x59(%rip), %xmm1        
    0x100000f4f <+31>: movss  %xmm1, -0x4(%rbp)  
    0x100000f54 <+36>: movss  %xmm0, -0x8(%rbp)
    0x100000f59 <+41>: movss  -0x4(%rbp), %xmm0         
    0x100000f5e <+46>: addss  -0x8(%rbp), %xmm0
    0x100000f63 <+51>: movss  %xmm0, -0xc(%rbp)
    ...

Видимо, он делает следующее:

загрузка двух поплавков в регистры xmm0 и xmm1положить их в стекзагрузить одно значение (а не то, которое было раньше у xmm0) из стека в xmm0выполнить сложение.сохранить результат обратно в стек.

Я считаю это неэффективным, потому что:

Все можно сделать в реестре. Я не буду использовать a и b позже, поэтому он может просто пропустить любую операцию, связанную со стеком.даже если бы он хотел использовать стек, он мог бы сохранить перезагрузку xmm0 из стека, если бы он выполнял операцию в другом порядке.

Учитывая, что компилятор всегда прав, почему он выбрал эту стратегию?

Ответы на вопрос(1)

Ваш ответ на вопрос