2010-06-30 47 views
6

我目前有內聯函數調用另一個內聯函數(簡單的4行大getAbs()函數)。但是,通過查看彙編代碼,我發現「大」內聯函數內聯,但編譯器使用bl跳轉來調用getAbs()函數。內嵌另一個內聯函數中的函數C

是不是可以在另一個內聯函數中內聯一個函數?順便說一下,這是嵌入式代碼,我們不使用標準庫。

編輯:編譯器是WindRiver,並且我已經檢查到內聯會是有益的(4條指令而不是+ -40)。

+0

你使用什麼編譯器?通常有強制內聯的方法。我認爲你已經對你的代碼進行了描述,並且非常有把握地認爲內聯會有好處。在GCC中,這可以通過__attribute __((always_inline))完成。 – stinky472 2010-06-30 08:30:03

+0

請問爲什麼你關心編譯器做出的決定?你是否分析了代碼,並發現該跳轉指令的開銷會導致性能下降? – JeremyP 2010-06-30 08:44:21

回答

8

根據您使用的編譯器,您可能會鼓勵編譯器不太願意內聯,例如,用gcc你可以用__attribute__ ((always_inline)),用英特爾ICC你可以用icc -inline-level=1 -inline-forceinline,用蘋果的gcc就可以用gcc -obey-inline

7

inline關鍵字是一個建議到編譯器,僅此而已。在船上採取這一建議是完全免費的,完全忽略它,甚至對你撒謊,並說它是在做,而實際上並非如此。

強制代碼內聯的唯一方法就是將它內聯編寫。但是,即使如此,編譯器可能會認爲它知道得更好,並決定將它轉移到另一個函數。它爲您的特定源生成可執行代碼有很大的餘地,前提是它不會改變它的語義。

現代編譯器比大多數開發人員在組裝時能夠產生更好的代碼。我認爲inline關鍵字應與register關鍵字走的路徑相同。

如果你已經看到gcc的輸出在它的瘋狂的優化級別,你會明白爲什麼。它製作了我不可能想到的代碼,這讓我花了很長時間才明白。

另外,請檢查this瞭解gcc實際上有哪些優化,包括很多包含「inline」或「inlining」文本的優化。

+0

我想冒險一個猜測,並說當關於確定函數是否可以內聯的任務對於編譯器來說有點太大(無論是功能方面的還是時間方面的)的時候,都會添加關鍵字,但是今天的編譯器可能即使inline關鍵字不存在,也能夠自己找出這個問題。只是一個猜測。 – 2010-06-30 08:08:12

+0

我想說這是一個非常安全的猜測。查看我的更新。 – paxdiablo 2010-06-30 08:09:24

+0

gcc是否支持基於配置文件的優化?當不使用這些內容時,提示內聯可能有幫助的gcc是非常有意義的。這是基於對該函數是否被稱爲* lot *的知識,這是最聰明的編譯器仍然無法說明的。 – Peaker 2010-06-30 09:47:37

1

@gramm:在很多情況下,內聯不一定對您有好處。大多數編譯器使用一些非常先進的啓發式方法來確定何時內聯。在討論內聯時,最簡單的想法是,相信你的編譯器生成最快的代碼。

-1

我建議如果你的getAbs()函數(聽起來像絕對值,但你真的應該向我們顯示代碼的問題......)是4行,那麼你有更多的優化擔心比代碼內聯或不內聯。

+0

要麼你說任何調用函數的開銷對於短函數來說都不那麼重要,要麼你說短的函數通常是不好的,無論哪種方式你都會得到-1 – 2010-06-30 08:30:54

+0

不,我說的是如果編譯器不能內聯,那麼'abs()'的執行效率就會大得多。 (事實上​​,編譯器可能會通過不內聯來做正確的事情。) – 2010-06-30 09:46:25

+0

與Pete相同。擁有50條指令而不是5條是一個巨大的開銷,並且在循環中使用時通常會變得很明顯。我不確定你是否習慣於使用微控制器。 – gramm 2010-06-30 09:47:36

0

我最近有一個非常類似的問題,閱讀這篇文章給了我一個怪誕的想法。爲什麼不能有一個簡單的預編譯(一個簡單的註冊前應該做的工作)代碼解析器,解析出函數調用實際上將源代碼內聯。使用標籤,如/ 內嵌 // end_of_inline /以便您可以使用正常的ide功能(如果您正在使用或可能使用ide) 將此包含在您的構建過程中,這樣您也具有可讀性優勢因爲消除了編譯器的假設,即你只有像開發人員一樣優秀,並且不知道何時聯機。

儘管如此,在嘗試此操作之前,您應該先閱讀編譯器命令行選項。