Estoy experimentando con el ensamblado x86-64. Habiendo compilado esta función ficticia:
long myfunc(long a, long b, long c, long d,
long e, long f, long g, long h)
{
long xx = a * b * c * d * e * f * g * h;
long yy = a + b + c + d + e + f + g + h;
long zz = utilfunc(xx, yy, xx % yy);
return zz + 20;
}
Con gcc -O0 -g
Me sorprendió encontrar lo siguiente al comienzo del ensamblaje de la función:
0000000000400520 <myfunc>:
400520: 55 push rbp
400521: 48 89 e5 mov rbp,rsp
400524: 48 83 ec 50 sub rsp,0x50
400528: 48 89 7d d8 mov QWORD PTR [rbp-0x28],rdi
40052c: 48 89 75 d0 mov QWORD PTR [rbp-0x30],rsi
400530: 48 89 55 c8 mov QWORD PTR [rbp-0x38],rdx
400534: 48 89 4d c0 mov QWORD PTR [rbp-0x40],rcx
400538: 4c 89 45 b8 mov QWORD PTR [rbp-0x48],r8
40053c: 4c 89 4d b0 mov QWORD PTR [rbp-0x50],r9
400540: 48 8b 45 d8 mov rax,QWORD PTR [rbp-0x28]
400544: 48 0f af 45 d0 imul rax,QWORD PTR [rbp-0x30]
400549: 48 0f af 45 c8 imul rax,QWORD PTR [rbp-0x38]
40054e: 48 0f af 45 c0 imul rax,QWORD PTR [rbp-0x40]
400553: 48 0f af 45 b8 imul rax,QWORD PTR [rbp-0x48]
400558: 48 0f af 45 b0 imul rax,QWORD PTR [rbp-0x50]
40055d: 48 0f af 45 10 imul rax,QWORD PTR [rbp+0x10]
400562: 48 0f af 45 18 imul rax,QWORD PTR [rbp+0x18]
gcc
muy extrañamente derrama todos los registros de argumentos en la pila y luego los toma de la memoria para operaciones posteriores.
Esto solo sucede en -O0
(con -O1
no hay problemas), pero aún así, ¿por qué? Esto me parece una antioptimización: ¿por qué gcc
¿Haz eso?
Creo que podrías tenerlo al revés. Estoy bastante seguro de que lo anterior es cómo GCC siempre (inicialmente) genera el código, es solo que normalmente no lo verá, ya que está optimizado de manera trivial (pero, por supuesto, solo si las optimizaciones están habilitadas).
– usuario786653
26 de agosto de 2011 a las 8:14
Esto no es anti optimización, simplemente no es optimización.
-Gunther Piez
27 de agosto de 2011 a las 21:08
Acababa de ver este ejemplo en alguna parte: eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 🙂
– Ciro Santilli Путлер Капут 六四事
16 de julio de 2015 a las 9:15
@GuntherPiez: Yo lo llamaría antioptimización; hay suficientes registros para contener trivialmente todos los locales, y comenzaron en registros, por lo que solo es necesario derramarlos para admitir una depuración consistente. (Y para simplificar los algoritmos internos del compilador). Consulte también ¿Por qué clang produce asm ineficiente con -O0 (para esta simple suma de punto flotante)?
– Peter Cordes
4 de septiembre de 2020 a las 5:33
@user786653: GCC optimiza antes de generando asm, en una representación interna del programa como GIMPLE. Creo que una compilación optimizada se dará cuenta de que estas variables no necesitan direcciones y no les dará una en primer lugar, en lugar de darles una y luego optimizarla.
– Peter Cordes
4 de septiembre de 2020 a las 5:35