10

次のコードを検討してください。

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

/O2と/Oxの両方の最適化フラグを試しました。重要な他のコンパイラオプションはありますか?

編集:VS2012はなんとか最適化を行うことができます

4

5 に答える 5

1

次のコードを試しました

#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 VC++2010は末尾再帰をサポートしていないようです。

于 2012-07-31T15:30:30.127 に答える
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
于 2012-07-31T16:06:44.457 に答える
0

奇妙に見えます、あなたはある種のインクリメンタルコンパイルをしていますか?それ以外に、コンパイラーが複数のパラメーターによって混乱するという事実かもしれません。作業バージョンでは、事実上1つのパラメーターしかなく、どういうわけか最適化はもはや適格ではありません。

resパラメータをグローバルにしてみることができます。私は厄介な悪い習慣を知っていますが、うまくいくかもしれません。

コンパイラのバグ/機能のように聞こえます。

/トニー

于 2011-09-27T21:28:45.643 に答える
0

関数を明示的に作成してみてくださいinline。さらに、どの最適化レベルを使用していますか?

于 2011-03-08T11:31:24.080 に答える
0

それが機能するかどうかはわかりませんが、if...elseを単一のreturnステートメントに置き換えてみてください。

return (x == 1) ? res : fac_aux( x - 1, res * x );
于 2011-03-08T11:49:22.327 に答える