vs2010 c++尾调用优化

发布于 2024-10-20 17:23:58 字数 622 浏览 3 评论 0原文

考虑以下代码:

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

Strange替换就够了,但是尾调用优化消失了。据我所知,VS2008中没有这种奇怪的编译器行为。有什么想法为什么会发生这些事情以及如何确保完成尾部调用优化吗?

;函数编译标志:/Ogtp

尝试了 /O2 和 /Ox 优化标志。还有其他重要的编译器选项吗?

编辑:VS2012设法做了优化

Consider the following code:

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

According to generated asm file everything is ok, tail call is optimized.

Try to replace

int x = fac( 50 );

with

int x = fac_aux( 50, 1 );

Strange enough, but tail call optimization is disappeared. As far as I remember there was no such a strange compiler behaviour in VS2008. Any ideas why these things happen and how to be sure of tail call optimization is done?

; Function compile flags: /Ogtp

Tried both /O2 and /Ox optimization flags. Are there any other compiler options that matter?

Edit: VS2012 manages to do the optimization

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

小梨窩很甜 2024-10-27 17:23:58

编译原始版本时,调用站点处的程序集具有 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

when the original is compiled, the assembly at the callsite has partial inlining of fac_aux, specifically the x - 1 part, which is required for the tail recursion, but using fac_aux prevents the partial inlining and thus the tail recursion optimization:

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
jJeQQOZ5 2024-10-27 17:23:58

我尝试了以下代码

#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不支持尾递归。

I tried the following code

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

and used the full optimization /Ox but I did not get the tail recursion. So it seems that MS VC++ 2010 does not support the tail recursion.

新一帅帅 2024-10-27 17:23:58

尝试使函数显式内联 - 此外,您使用什么优化级别?

Try making the functions explicitly inline – furthermore, what optimization level are you using?

椵侞 2024-10-27 17:23:58

我不知道它是否有效,但尝试用单个 return 语句替换 if ... else :

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

I don't know if it will work, but try to replace if ... else with single return statement:

return (x == 1) ? res : fac_aux( x - 1, res * x );
晚雾 2024-10-27 17:23:58

看起来很奇怪,你在做某种增量编译吗?
除此之外,编译器可能会感到困惑
多个参数,在工作版本中有效
只有一个参数,不知何故优化不再合格。

你可以尝试将 res 参数设置为全局参数,我知道它很混乱
不好的做法,但它可能会起作用。

听起来像是编译器错误/功能。

/托尼

Looks weird, are you doing some kind of incremental compile.
Other than that, it might be the fact that compiler gets confused by
the multiple parameters, in the working version there's effectively
only one parameter, somehow the optimization doesn't qualify anymore.

You could try making the res parameter a global, I its know messy
bad practice, but it might work.

Sounds like a compiler bug/feature.

/Tony

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文