【问题标题】:vs2010 c++ tail call optimizationvs2010 c++尾调用优化
【发布时间】:2011-07-11 01:11:45
【问题描述】:

考虑以下代码:

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 设法进行优化

【问题讨论】:

  • 修改代码时,是否删除了fac函数?
  • 所以实际上从未调用过未优化的函数?还是您在谈论第一个函数中的尾调用?
  • @Voivoid:该函数实际上是在程序集中调用吗? (可能,但我想我会问)
  • 仅供参考,there's no reason to use the /Ox optimization switch in preference to /O2/Ox 的“完全优化”这个名字有点欺骗性(至少在当代版本中);实际上,与/O2 相比,您至少获得了相同级别的优化,甚至更多。

标签: c++ visual-studio-2010 visual-c++ tail-call-optimization


【解决方案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 VC++ 2010 不支持尾递归。

    【讨论】:

      【解决方案3】:

      尝试明确地创建函数inline——此外,您使用的是什么优化级别?

      【讨论】:

      • 不幸的是内联没有帮助。尝试了 /O2 和 /Ox 标志
      【解决方案4】:

      我不知道它是否会起作用,但尝试将 if ... else 替换为单个 return 语句:

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

      【讨论】:

        【解决方案5】:

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

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

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

        /托尼

        【讨论】:

          猜你喜欢
          • 2011-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-23
          相关资源
          最近更新 更多