C/C++靜態庫中的函數在這個靜態庫被使用時還有被inline的可能嗎?

C/C++靜態庫中的函數在這個靜態庫被其他項目使用時還有被inline的可能嗎?

如果沒有,對於本該inline的小函數豈不是會影響速度? 比如很多getter和setter.

如果有,代碼都已經編譯成靜態庫里的彙編代碼了,編譯器難道要從彙編的角度去inline嗎?

//-------------------------------------------

首先感謝@RednaxelaFX的答案,在答案中提到了LTO,並且提到需要LTO需要一些"額外的信息"來輔助優化,那麼假如我的靜態庫本身就是彙編寫的,或者比如說使用minGW生成的C靜態庫給VC來用,恐怕這種情況下就不會有"額外的信息"了吧? 那麼在這種情況下豈不是就無法做優化了?

另外我本以為LTO只會對.obj文件之間做優化,靜態庫也有這種待遇嗎?


代碼都已經編譯成靜態庫里的彙編代碼了,編譯器難道要從彙編的角度去inline嗎?

Yes and no. 題主想要的功能其實就是LTO(Link-Time Optimization)。主流的C/C++編譯器都支持此類優化,Clang也不例外。

請跳傳送門:

The LLVM gold plugin

LLVM Link Time Optimization: Design and Implementation

Yes的部分:靜態庫在編譯出來之後,在與其它模塊鏈接時,可以通過LTO來跨越模塊邊界進行進一步優化,包括函數內聯在內。

No的部分:使用LTO時,編譯器通常在靜態庫里不只放「彙編」或者說尚未完全鏈接的機器碼,還會附帶上對應的編譯器IR,讓鏈接器(linker)在集齊要鏈接的靜態庫之後把它們傳給編譯器去把IR收集起來一起優化,最終由編譯器生成出最終鏈接+優化後的機器碼。

在使用LTO時,

  • MSVC生成的目標文件里包含的是CIL / CxxIL。這是MSVC的前端(C1 / C1XX)生成的中間代碼。
  • GCC生成的目標文件里包含的是GIMPLE的序列化形態。LTO Overview / LinkTimeOptimization
  • Clang生成的目標文件里包含的是LLVM IR(bitcode形態)
  • IBM XL生成的目標文件里包含的是WCode。這是前端到高層優化器、高層優化器到後端之間傳輸代碼用的IR。
  • HP aCC生成的目標文件里包含的應該是UCode-2(待確認)
  • Intel ICC在LTO用的IR是哪種我不太確定…


我想幫 @RednaxelaFX 大大再補充一點。答案R大已經說了,yes和no。

我猜題主想問的是如下這樣的情況:我們能不能內聯後綴名為.a或者.dylib/.dll/.so文件裡面的某個函數,雖然我們不知道它的實現是怎麼樣的?在這種情況下答案是no。事實上,當我們生成了機器碼/彙編碼(包括relocatable machine code,即obj文件)之後,內聯已經太遲了。

內聯的主要功能是去掉函數調用的開銷,另外內聯函數通常能夠暴露更多的其它的優化機會,而做這些優化是需要在編譯器的中間語言層面上進行的,所以內聯優化是在編譯時(compile time)進行的而不是在鏈接時(link time)進行的。Link time optimization事實上是把編譯時應該做的優化延後放到了鏈接時鏈接器裡面做,故而它不是真正意義上的鏈接時優化。

現有的編譯器都不能直接對機器碼或者relocatable machine code進行複雜優化,不單是因為非結構化的機器碼缺少程序分析,控制流和數據流的信息,而且機器碼緊湊和已固定成型的結構是非常不適合做優化的。

以在機器碼/彙編語言做inlining來舉例,當我們內聯某個函數的時候我們需要知道這個函數的執行邊界,這在機器碼里是做不到的。我們甚至還不能對庫文件做任何假設--萬一弄錯了呢?


讓鏈接器(linker)在集齊要鏈接的靜態庫之後把它們傳給編譯器去把IR收集起來一起優化,最終由編譯器生成出最終鏈接+優化後的機器碼。

-- @RednaxelaFX ,那麼請教,Java 9的模塊化系統,官方說到可以做whole program優化,也提供了linker工具,說Java的啟動性能,footprint都會改善。R大能解釋下這個whole program優化技術嗎?


靜態庫裡面肯定不是優化好的彙編代碼,而是某種格式「代碼」,使用的工程編鏈接裡面函數的時候當然可以優化,否則那叫動態庫。

其實這個問題,可以不去理睬具體的lib的格式,因為你就從業務的角度理解,靜態庫就某種形式的源碼,當然不知道出於什麼目的,人家不願意給源碼。所以靜態庫是很雞肋的東西,不像動態庫,不管庫本身多複雜,使用者只要知道介面信息就行了,一個h文件一個lib文件。而靜態庫的使用者必須有庫工程所有引用的庫。

話說靜態庫還要分編譯vs的版本,如果引用的工程使用了不同的版本,還有很大問題,不過幸好,它們不挑源碼的版本,要是不同版本的文本編輯器保存的源碼不通用,那才有意思呢。

能提供一份記事本編寫的源碼版本嗎?我們沒法用寫字板保存的源碼。


推薦閱讀:

為什麼現在有很多人甚至大學授課還在堅持VC6?

TAG:C編程語言 | CC | Clang | 編譯器優化 |