LLVM gold プラグイン¶
はじめに¶
リンク時最適化を使用してビルドするには、システムリンカーとの連携が必要です。LinuxシステムでのLTOサポートは、プラグインを介してLTOをサポートするgoldリンカーを介して利用できます。これは、GCC LTOプロジェクトで使用されているのと同じメカニズムです。
LLVM goldプラグインは、libLTOの上にgoldプラグインインターフェースを実装します。同じプラグインは、ar
やnm
などの他のツールでも使用できます。binutilsバージョン2.21.51.0.2以降のld.bfdもプラグインを介してLTOをサポートすることに注意してください。ただし、ld.bfdでのLLVM goldプラグインの使用はテストされておらず、そのため公式にはサポートまたは推奨されていません。
LLVM 15以降、goldプラグインはELFオブジェクトファイル内の.llvmbc
セクションからのビットコードを無視します。ただし、ビットコードファイルを使用したLTOはまだサポートされています。
ビルド方法¶
プラグインをサポートするgoldを用意し、LLVM goldプラグインをビルドする必要があります。goldリンカーはld.goldとしてインストールされます。システムでgoldがデフォルトかどうかを確認するには、/usr/bin/ld -v
を実行します。「GNU gold」と表示されるか、そうでない場合は「GNU ld」と表示されます。/usr/bin/ld.gold
に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
を追加して、make install
を使用して新しくビルドされたgoldをデフォルトのリンカーとして自動的にインストールします。LLVM goldプラグインをビルドします。
-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include
を使用してCMakeを実行します。正しいインクルードパスにはplugin-api.h
ファイルが含まれます。
使用方法¶
clang
で-flto
オプションを使用してビットコードファイルを作成する必要があります。このフラグにより、clang
はプレフィックスの下のlib
ディレクトリでgoldプラグインを検索し、-plugin
オプションをld
に渡すようになります。-fuse-ld=gold
を使用しない限り、別のリンカーは検索されません。そのため、パスにインストールされているシステムリンカーとしてgoldが必要になります。
ar
とnm
も-plugin
オプションを受け入れ、LLVMgold.so
を/usr/lib/bfd-plugins
にインストールしてシームレスなセットアップを行うことができます。自分でgoldをビルドした場合は、ビルドしたar
とnm-new
を/usr/bin
にインストールしてください。
リンク時最適化の例¶
次の例は、LLVMビットコードとネイティブコードを混合したgoldプラグインの動作例を示しています。
--- 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を削除しません。
autotoolsプロジェクトでLTOを使用するためのクイックスタート¶
システムのld
、ar
、nm
がすべてLLVMビットコードをサポートするようになると、autotoolsプロジェクトの使いやすいLTOビルドの準備が整います。
LLVMgold.soのビルド方法の手順に従ってください。
新しくビルドした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になります。これは、プラグインなしのgoldと同様に、非GPLv3プログラムをリンクするために使用できます。