2011-03-08 13 views
10

llamada de cola Considere el siguiente código:VS2010 C++ optimización

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; 
} 

Según genera el archivo asm todo está bien, está optimizado llamada de cola.

tratar de sustituir

int x = fac(50); 

con

int x = fac_aux(50, 1); 

lo suficientemente extraño, pero la optimización de llamada de cola se desaparecieron. 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?

; Indicadores de compilación de funciones:/Ogtp

Indicadores de optimización de ambos/O2 y/Ox. ¿Hay alguna otra opción de compilación que importe?

Editar: VS2012 se las arregla para hacer la optimización

+0

al modificar su código, ¿eliminó la función 'fac'? – SirDarius

+0

no, todavía estaba allí – Voivoid

+0

por lo que la función que no se optimiza en realidad nunca se llama? ¿o estás hablando de la llamada final en la función puño? – Euqil

Respuesta

1

cuando se compila el original, el montaje en la callsite tiene inlining parcial de fac_aux, específicamente la parte x - 1, que se requiere para la recursión de cola, pero usando fac_aux impide que el inlining parcial y por lo tanto la optimización de la cola de recursión:

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 
0

intentar hacer las funciones de forma explícita inline - por otra parte, ¿qué nivel de optimización se utiliza?

+0

lamentablemente en línea no ayuda. Intentó ambas banderas/O2 y/Ox – Voivoid

0

No sé si funcionará, pero trata de reemplazar si ... más con instrucción de retorno individual:

return (x == 1) ? res : fac_aux(x - 1, res * x); 
+0

no, no funciona – Voivoid

0

ve raro, estás haciendo una especie de compilación incrementales. Aparte de eso, podría ser el hecho de que el compilador se confunde con los parámetros múltiples , en la versión de trabajo efectivamente hay solo un parámetro, de alguna manera la optimización ya no califica.

Podría intentar que el parámetro res sea global, ya sé que es una mala práctica , pero podría funcionar.

Suena como un error/función del compilador.

/a Tony

1

He probado 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 utilizó la optimización completa/buey, pero no he tenido la recursión de cola. Parece que MS VC++ 2010 no admite la recursividad de cola.