2011-02-10 19 views
2

我們有一個共同的事業庫,是這樣的信號錯誤宏:什麼是規則編譯器用來決定是否內聯函數的實際集合?

#define OurMacro(condition) \ 
    if(condition) { \ 
    } else { \ 
     CallExternalFunctionThatWillThrowAnException(parametersListHere); \ 
    } \ 

我稱之爲parametersListHere是由編譯器在每個人口常量和宏以逗號分隔的列表宏觀擴張。

該函數調用總是會解析爲一個調用 - 函數實現不會暴露給編譯器。該函數有六個參數,在調試配置中,它們都具有有意義的值,而在發佈配置中,只有兩個具有有意義的值,而其他參數則傳遞相同的默認值。

通常這個條件會成立,所以我不關心這個調用的速度有多快,我只關心代碼膨脹。使用6個參數調用該函數需要7條x86指令(6個push es和一個call),並且如果函數簽名被更改爲僅有兩個參數,則可以避免使用那些push es中的4個 - 這可以通過引入中間「門「功能以這種方式實現,編譯器不可見。

我需要估計我是否應該堅持這種改變。到目前爲止,我期望的主要改進是,減少參數的數量將在每次調用時減少4條指令,這意味着圍繞宏擴展的代碼將變得更小,編譯器將更有可能地內聯代碼並進一步優化發出的代碼。

我如何估計,而不是實際嘗試和重新編譯我們所有的代碼,並仔細分析發出的代碼?每當我讀到inline時,都會有一個聲明,編譯器決定是否內聯該函數。

我可以看到一些關於函數內部函數如何影響編譯器決定內聯的準確規則嗎?

+0

任何原因你沒有2個不同的功能`#ifdef NDEBUG`開關? – 2011-02-10 10:37:09

+0

@Matthieu M .:原始函數可能已經從我不知道的一些代碼中調用。無論如何,使用新功能或通過改變現有功能簽名,我可以達到完全相同的結果,所以選擇哪種方式並不重要。 – sharptooth 2011-02-10 10:39:47

回答

3

海灣合作委員會有一個相當大的選項,公開他們的過程如何工作,記錄here。這當然不是確切的,因爲它會隨着時間的推移而被調整,並且取決於CPU。

第一條規則是「他們的身體小於預期的函數調用代碼」。 第二條規則是「靜態函數調用一次」。

還有一些參數影響打盹過程,例如, max-inline-insns-single。一個insn是GCC編譯器中的僞指令,在這裏用作度量函數複雜度。參數max-inline-insns-auto的文檔清楚地表明,手動聲明函數inline可能會導致它被認爲是內聯的,即使它對於自動內聯來說太大。

內聯不是一個全有或全無的過程,因爲有一個-fpartial-inlining標誌。

當然,你不能孤立地考慮內聯。通用子表達式消除(CSE)使代碼更簡單。這是一個優化過程,可以使函數足夠小以便內聯。內聯後,可能會發現新的常見子表達式,因此應該再次運行CSE通行證,這反過來可能會觸發進一步的內聯。而CSE不是唯一需要重新運行的優化。

1

關於哪些函數內聯以及在什麼條件下(例如,選定的優化級別)對每個編譯器都是特定的,所以我建議你檢查你的編譯器的文檔。然而,一個只轉發給另一個函數的函數(如你所建議的)應該是任何支持它的編譯器內聯的好候選者。

一些編譯器有一個機制,可以標記你確實想要內聯函數,例如, MSVC++有__forceinline。

1

如果您使用的是Visual C++,則可以使用__forceinline強制的編譯器內聯一個函數。

相關問題