LLVM gold 插件¶
簡介¶
使用連結時優化需要系統連結器的配合。Linux 系統上的 LTO 支援可透過 gold 連結器 取得,該連結器透過插件支援 LTO。這與 GCC LTO 專案使用的機制相同。
LLVM gold 插件在 libLTO 之上實作了 gold 插件介面。相同的插件也可以被其他工具使用,例如 ar
和 nm
。請注意,binutils 2.21.51.0.2 及更高版本的 ld.bfd 也透過插件支援 LTO。但是,不建議且官方不支援將 LLVM gold 插件與 ld.bfd 搭配使用。
從 LLVM 15 開始,gold 插件將會忽略 ELF 物件檔案內 .llvmbc
區段中的位元碼。但是,仍然支援使用位元碼檔案的 LTO。
如何建構¶
您需要具有插件支援的 gold 並建構 LLVMgold 插件。gold 連結器安裝為 ld.gold。若要查看 gold 是否為系統上的預設值,請執行 /usr/bin/ld -v
。如果有的話,它會報告「GNU gold」,否則會報告「GNU ld」。如果 gold 已經安裝在 /usr/bin/ld.gold
,則其中一個選項是透過備份現有的 /usr/bin/ld
並使用 ln -s /usr/bin/ld.gold /usr/bin/ld
建立符號連結,將其設為預設值。或者,您可以使用 clang 的 -fuse-ld=gold
進行建構,或將 -fuse-ld=gold
新增至 LDFLAGS,這會導致 clang 驅動程式直接呼叫 /usr/bin/ld.gold
。
如果您已安裝 gold,請執行 /usr/bin/ld.gold -plugin
來檢查插件支援。如果它顯示「缺少參數」,則表示您擁有插件支援。如果沒有,並且您收到錯誤訊息,例如「未知選項」,則您需要建構 gold 或安裝具有插件支援的版本。
下載、設定並建構具有插件支援的 gold
$ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils $ mkdir build $ cd build $ ../binutils/configure --enable-gold --enable-plugins --disable-werror $ make all-gold
這應該會讓您擁有支援
-plugin
選項的build/gold/ld-new
。執行make
還會建構支援插件的build/binutils/ar
和nm-new
二進制檔案。當您準備好切換到使用 gold 時,請備份您現有的
/usr/bin/ld
,然後將其替換為ld-new
。或者,安裝在/usr/bin/ld.gold
並使用-fuse-ld=gold
,如前所述。(可選)將
--enable-gold=default
添加到上述 configure 呼叫,以便在使用make install
安裝時自動將新構建的 gold 安裝為預設連結器。建置 LLVMgold 外件。使用 CMake 並搭配
-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include
執行。正確的 include 路徑將包含檔案plugin-api.h
。
用法¶
您應該使用 -flto
選項從 clang
產生位元碼檔案。這個旗標也會導致 clang
在其前綴下的 lib
目錄中尋找 gold 外件,並將 -plugin
選項傳遞給 ld
。如果沒有 -fuse-ld=gold
,它不會尋找替代的連結器,這就是為什麼您需要將 gold 作為已安裝的系統連結器放在您的路徑中的原因。
ar
和 nm
也接受 -plugin
選項,並且可以將 LLVMgold.so
安裝到 /usr/lib/bfd-plugins
以實現無縫設定。如果您是自己建置 gold 的,請確保將您建置的 ar
和 nm-new
安裝到 /usr/bin
。
連結時最佳化的範例¶
以下範例顯示了一個 gold 外件混合 LLVM 位元碼和原生碼的實際範例。
--- a.c ---
#include <stdio.h>
extern void foo1(void);
extern void foo4(void);
void foo2(void) {
printf("Foo2\n");
}
void foo3(void) {
foo4();
}
int main(void) {
foo1();
}
--- b.c ---
#include <stdio.h>
extern void foo2(void);
void foo1(void) {
foo2();
}
void foo4(void) {
printf("Foo4");
}
--- command lines ---
$ clang -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file
$ ar q a.a a.o # <-- a.a is an archive with LLVM bitcode
$ clang b.c -c -o b.o # <-- b.o is native object file
$ clang -flto a.a b.o -o main # <-- link with LLVMgold plugin
Gold 通知外件 foo3 從未在 IR 之外被參考,導致 LLVM 刪除該函數。但是,與 libLTO 範例 不同,gold 目前不會消除 foo4。
使用自動工具專案進行 LTO 的快速入門¶
一旦您的系統 ld
、ar
和 nm
都支援 LLVM 位元碼,就可以輕鬆使用 LTO 建置自動工具專案
將新構建的 binutils 安裝到
$PREFIX
將
Release/lib/LLVMgold.so
複製到$PREFIX/lib/bfd-plugins/
設定環境變數(
$PREFIX
是您安裝 clang 和 binutils 的位置)export CC="$PREFIX/bin/clang -flto" export CXX="$PREFIX/bin/clang++ -flto" export AR="$PREFIX/bin/ar" export NM="$PREFIX/bin/nm" export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
或者,您可以設定您的路徑
export PATH="$PREFIX/bin:$PATH" export CC="clang -flto" export CXX="clang++ -flto" export RANLIB=/bin/true
照常設定和建置專案
% ./configure && make && make check
環境變數設定可能也適用於非 autotools 專案,但您可能也需要設定 LD
環境變數。
授權條款¶
Gold 採用 GPLv3 授權。LLVMgold 使用來自 gold 的介面檔案 plugin-api.h
,這表示產生的 LLVMgold.so
二進制檔案也採用 GPLv3 授權。這仍然可以用於連結非 GPLv3 程式,就像沒有插件的 gold 一樣。