Оптимизация хвостовых опций vs2010 С++

Рассмотрим следующий код:

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

Согласно сгенерированному asm файлу все в порядке, оптимизирован хвостовой вызов.

Попробуйте заменить

int x = fac( 50 );

с

int x = fac_aux( 50, 1 );

Странно, но оптимизация хвостового вызова исчезает. Насколько я помню, в VS2008 не было такого странного поведения компилятора. Любые идеи, почему это происходит, и как быть уверенным в оптимизации хвостового вызова?

; Флаги компиляции функции:/Ogtp

Пробовал флаги оптимизации /O 2 и/Ox. Существуют ли какие-либо другие параметры компилятора?

Изменить: VS2012 удается выполнить оптимизацию

Ответ 1

когда оригинал скомпилирован, сборка на вызывающей стороне имеет частичную вставку fac_aux, в частности часть x - 1, которая требуется для рекурсии хвоста, но с использованием fac_aux предотвращает частичную вставку и, следовательно, хвост оптимизация рекурсии:

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

Ответ 2

Я пробовал следующий код

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

и использовал полную оптимизацию /Ox, но я не получил хвостовую рекурсию. Похоже, что MS VС++ 2010 не поддерживает хвостовую рекурсию.

Ответ 3

Попробуйте сделать функции явно inline - кроме того, какой уровень оптимизации вы используете?

Ответ 4

Я не знаю, будет ли это работать, но попытайтесь заменить if... else одним оператором return:

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

Ответ 5

Выглядит странно, делаете ли вы какую-то инкрементальную компиляцию. Помимо этого, возможно, что компилятор запутался множество параметров, в рабочей версии там эффективно только один параметр, как-то оптимизация больше не подходит.

Вы можете попробовать сделать параметр res глобальным, я его знаю, грязный плохая практика, но это может сработать.

Звучит как ошибка/функция компилятора.

/Tony