¿Por qué el sonido metálico produce asm ineficiente con -O0 (para esta simple suma de coma flotante)?
Desarmo este código en llvm clang Apple LLVM versión 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);
}
Compilé sin especificaciones -O, pero también intenté con -O0 (da lo mismo) y -O2 (en realidad calcula el valor y lo almacena precalculado)
El desmontaje resultante es el siguiente (eliminé las partes que no son relevantes)
-> 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)
...
Aparentemente está haciendo lo siguiente:
cargar los dos flotadores en los registros xmm0 y xmm1 ponlos en la pilaload un valor (no el que xmm0 tenía anteriormente) de la pila a xmm0 realizar la adición. almacenar el resultado nuevamente en la pila.Me parece ineficiente porque:
Todo se puede hacer en el registro. No estoy usando ayb más tarde, por lo que podría omitir cualquier operación que involucre la pila. incluso si quisiera usar la pila, podría ahorrar recargar xmm0 desde la pila si realizara la operación con un orden diferente.Dado que el compilador siempre tiene la razón, ¿por qué eligió esta estrategia?