2011-03-08 81 views
10

考慮下面的代碼:VS2010 C++尾調用優化的

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_aux(50, 1); 

自嘆不如更換

int x = fac(50); 

,但尾調用優化的消失。據我記得在VS2008中沒有這種奇怪的編譯器行爲。任何想法爲什麼會發生這些事情,以及如何確保尾巴呼叫優化完成?

;函數編譯標誌:/ Ogtp

嘗試了/ O2和/ Ox優化標誌。有沒有其他編譯器選項很重要?

編輯:VS2012設法做了優化

+0

修改代碼時,你是否刪除了'fac'函數? – SirDarius 2011-03-08 12:52:42

+0

不,它仍然存在 – Voivoid 2011-03-08 13:11:47

+0

所以沒有得到優化的功能實際上從來沒有被調用過?或者你是否在談論第一拳功能中的尾巴呼叫? – Euqil 2011-07-29 11:14:58

回答

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 
0

嘗試使功能明確inline - 而且,你使用的是什麼優化級別?

+0

不幸的是,內聯並沒有幫助。試過/ O2和/ Ox標誌 – Voivoid 2011-03-08 11:35:36

0

我不知道這是否會工作,但嘗試更換,如果...否則單return語句:

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

不行,它不起作用 – Voivoid 2011-03-08 11:54:11

0

看起來奇怪,你在做某種類型的漸進式編譯的。 除此之外,編譯器可能會因爲多個參數而感到困惑,在工作版本中只有一個參數有效,不知何故優化不再有資格。

你可以嘗試使res參數成爲一個全球性的,我知道它很糟糕的做法 ,但它可能工作。

聽起來像一個編譯器錯誤/功能。

/託尼

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

和使用的全面優化/牛年,但我沒有得到的尾遞歸。所以看起來MS VC++ 2010不支持尾遞歸。