Así que he estado viendo algo de la magia que es O3
en GCC (bueno, en realidad estoy compilando usando Clang, pero es lo mismo con GCC y supongo que una gran parte del optimizador fue retirado de GCC a Clang).¿Cómo un compilador optimiza tan bien esta función factorial?
consideran este programa en C:
int foo(int n) {
if (n == 0) return 1;
return n * foo(n-1);
}
int main() {
return foo(10);
}
La primera cosa que era bastante WOW-ed al (que también era WOW-ed en en esta pregunta - https://stackoverflow.com/a/414774/1068248) era cómo int foo(int)
(una función básica factorial) compila en un círculo cerrado. Este es el conjunto ARM para él:
.globl _foo
.align 2
.code 16
.thumb_func _foo
_foo:
mov r1, r0
movs r0, #1
cbz r1, LBB0_2
LBB0_1:
muls r0, r1, r0
subs r1, #1
bne LBB0_1
LBB0_2:
bx lr
Blimey, pensé. ¡Eso es bastante interesante! Bucle completamente cerrado para hacer el factorial. GUAU. No es una optimización de la cola de llamadas ya que, bueno, no es una llamada de cola. Pero parece haber hecho una optimización muy similar.
Ahora mira main
:
.globl _main
.align 2
.code 16
.thumb_func _main
_main:
movw r0, #24320
movt r0, #55
bx lr
que acaba de soplar mi mente para ser honesto. Está pasando por alto totalmente foo
y devolviendo 3628800
que es 10!
.
Esto me hace comprender realmente cómo su compilador a menudo puede hacer un trabajo mucho mejor de lo que puede en la optimización de su código. Pero plantea la pregunta, ¿cómo se las arregla para hacer un buen trabajo? Así que, ¿alguien puede explicar (posiblemente mediante la vinculación con el código correspondiente) cómo funcionan las siguientes optimizaciones:
La optimización inicial
foo
para ser un bucle estrecho.La optimización donde
main
simplemente va y devuelve el resultado directamente en lugar de ejecutarfoo
.
Otro efecto secundario interesante de esta pregunta sería mostrar algunas optimizaciones más interesantes que GCC/Clang puede hacer.
¡Excelente respuesta! Y sí, la optimización 'principal 'de hecho puede ser simplemente reemplazada con constantes multiplicadas juntas para que una sea fácil. Me gusta su paseo por la optimización 'foo' :-). – mattjgalloway