vs2010 c++ optimización de la cola de cola
visual-studio-2010 visual-c++ (5)
Intente hacer explícitamente las funciones en inline
; además, ¿qué nivel de optimización está usando?
Considera el siguiente código:
int fac_aux( int x, int res ) {
if( x == 1 ) return res;
else return fac_aux( x - 1, res * x );
}
int fac( int x ) {
return fac_aux( x, 1 );
}
int main() {
int x = fac( 50 );
std::cout << x;
return 0;
}
De acuerdo con el archivo asm generado todo está bien, la cola de llamada está optimizada.
Intenta reemplazar
int x = fac( 50 );
con
int x = fac_aux( 50, 1 );
Es bastante extraño, pero la optimización de la cola de llamada ha desaparecido. Por lo que recuerdo, no había un comportamiento de compilación tan extraño en VS2008. ¿Alguna idea de por qué ocurren estas cosas y cómo asegurarse de que se haga una optimización de las llamadas finales?
; Banderas de compilación de funciones: / Ogtp
Intentó los indicadores de optimización de ambos / O2 y / Ox. ¿Hay alguna otra opción de compilación que importe?
Editar : VS2012 logra hacer la optimización
No sé si funcionará, pero intente reemplazar si ... else con declaración de devolución única:
return (x == 1) ? res : fac_aux( x - 1, res * x );
Parece extraño, ¿estás haciendo algún tipo de compilación incremental? Aparte de eso, podría ser el hecho de que el compilador se confunde por los múltiples parámetros, en la versión de trabajo hay efectivamente un solo parámetro, de alguna manera la optimización ya no califica.
Podrías tratar de hacer que el parámetro res sea global, es una mala práctica desordenada, pero podría funcionar.
Suena como una característica / error del compilador.
/ Tony
Probé el siguiente código
#include "stdafx.h"
int f( size_t i, int x )
{
return ( ( i < 2 ) ? x : f( i - 1, i * x ) );
}
int f( size_t i )
{
return ( f( i, 1 ) );
}
int _tmain(int argc, _TCHAR* argv[])
{
{
f( 0 );
}
return 0;
}
y usé la optimización completa / Ox pero no obtuve la recursividad de la cola. Parece que MS VC ++ 2010 no admite la recursividad de cola.
cuando se compila el original, el ensamblado en el callsite tiene una delimitación parcial de fac_aux
, específicamente la parte x - 1
, que se requiere para la recursión fac_aux
, pero el uso de fac_aux
evita la fac_aux
parcial y, por lo tanto, la optimización de recursión de cola:
TestThin.fac_aux 013B1000 CMP ECX,1
013B1003 JE SHORT TestThin.013B100E
013B1005 IMUL EAX,ECX
013B1008 DEC ECX
013B1009 CMP ECX,1
013B100C JNZ SHORT TestThin.013B1005
013B100E RETN
013B100F INT3
TestThin.main 013B1010 MOV EAX,32
013B1015 LEA ECX,DWORD PTR DS:[EAX-1] ;notice the partial inlining of x - 1
013B1018 CALL TestThin.fac_aux