編譯優化之 鏈結時優化 LTO 入門

2021-10-01 16:39:35 字數 3486 閱讀 5834

1. 關於 lto 、-flto 、thinlto

2. llvm或aocc中flto

llvm中lto work在ir(intermediate representation)上,我們常用的選項-flto其實代表-flto=full,指lto將分散的目標檔案的所有llvm ir組合到乙個大的llvm模組中,然後對其進行整體分析優化並生成machinecode,該選項僅並行執行前端的語義分析,優化和machinecode生成在單執行緒完成。-flto=thin則是把模組分開,根據需要才從其他模組匯入功能,並且除全域性分析外均採用並行的方式進行優化和machinecode的生成。因此使用-flto=thin-flto=full編譯鏈結的速度大大加快,而且對於spec cpu2017部分benchmark效能更好。

2.1 linkers

gold linker:使用前需要先安裝外掛程式,然後就可以使用-fuse-ld=gold。安裝請見(the llvm gold plugin)。

ld64:從xcode 8開始。

lld:來自於llvm專案,執行速度更快,特別是在眾核處理器上。預設支援lto,lld讀取llvm ir bitcode進行編譯優化並輸出檔案。詳細請見(the llvm linker — lld)。llvm中關於lld的詳細說明介紹請見知乎大佬的:llvm中的lld程式流程分析 這篇文章。

基本用法:

// 使用-flto=thin編譯鏈結

clang -flto=thin -o2 file1.c file2.c -c

clang -flto=thin -o2 file1.o file2.o -o a.out

// 使用lld-link時,只需將-flto選項新增到編譯步驟中

clang-cl -flto=thin -o2 -c file1.c file2.c

lld-link /out:a.exe file1.obj file2.obj

3. gcc和icc中flto

3.1 gcc中用法

gcc-4.6.0中開始支援lto框架,主要分為:partitioned lto和non-partitioned lto

分割槽的lto(partitioned lto)整體步驟為:

lgen:生成摘要資訊;生成轉換單元資訊

wpa(whole program analysis):讀取除函式體外的call graph資訊;每個函式的摘要資訊

ltrans:區域性轉換

處理順序為:

不分割槽的lto(non-partitioned lto)整體步驟為:

lgen:生成轉換單元資訊

ipa(interprocedural analysis) :讀取call graph和函式體內容;進行分析和轉換

處理順序為:

以上內容摘自於:是以gcc-4.7.2版本原始碼進行的分析說明。

gcc中使用-flto編譯**時,它將生成gimple中間表示,並將其寫到目標檔案的elf(部分的資料結構和列舉**在 lto-streamer.h中),將目標檔案鏈結在一起時,將從這些elf中讀取所有功能體,並將其實例化(鏈結期間,所有物件模組放在一起並呼叫lto1)。當前,大多數基於elf的系統以及darwincygwinmingw系統都啟用了lto支援。

從原始碼時使用-flto編譯,所有的passesall_lto_gen_passes中管理,它包含兩個ipa passes:

gcc中基本用法:

gcc -c -o test1.o -o2 -flto test1.c

gcc -o2 -flto test1.o test2.o ... -o test

// lto的另乙個功能是可以對用不同語言編寫的檔案進行過程間優化

gcc -c -flto foo.c

g++ -c -flto bar.cc

gfortran -c -flto baz.f90

g++ -o myprog -flto -o2 foo.o bar.o baz.o -lgfortran

gcc中如果你想知道你的**從前端開始的編譯過程中做了哪些pass,可使用fdump-tree-all-fdump-ipa-all或者-fdump-rtl-all列印出來,如下:

gcc -flto -o3 .....  -fdump-tree-all test.c    // 可使用任意選項,此處列印flto 和o3

由上圖可看出,原始碼經過前端處理之後在中端需要經過很多處理,你可以結合gdb看到每乙個處理過程的轉換資訊。

對於最簡單的 printf(「hello world」),在gcc中沒有-flto選項的情況下得到的彙編碼如下:

使用-flto之後的大致輸出資訊如下:

由此看出:lto輸出不包含目標**,而僅包含lto資訊。

關於flto優化的具體資訊可通過--verbose列印出來:

在以上標註的6個步驟中,-flto真正開始起作用是從第4步開始,lto1位置。

3.2 icc中用法

ifort -c -o test1.o -o2 -ipo test1.f90

ifort -o2 -ipo test1.o test2.o ... -o test

4. 注意點

references:

預處理,編譯, 優化, 彙編, 鏈結

編譯,編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言,並且按照作業系統對可執行檔案格式的要求鏈結生成可執行程式。c源程式標頭檔案 預編譯處理 cpp 編譯程式本身 優化程式 匯程式設計序 鏈結程式 可執行檔案 1.編譯預處理讀...

預處理,編譯, 優化, 彙編, 鏈結

編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言 目標檔案 並且按照作業系統對可執行檔案格式的要求鏈結生成可執行程式。c源程式標頭檔案 預編譯處理 cpp 編譯程式本身 優化程式 匯程式設計序 鏈結程式 可執行檔案 1.編譯預處...

預處理,編譯, 優化, 彙編, 鏈結

編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言 目標檔案 並且按照作業系統對可執行檔案格式的要求鏈結生成可執行程式。c源程式標頭檔案 預編譯處理 cpp 編譯程式本身 優化程式 匯程式設計序 鏈結程式 可執行檔案 1.編譯預處...