Edited at

「2016年、C言語はどう書くべきか」をちょっと分析してみる (building編)

More than 3 years have passed since last update.


Overview

原典は、https://matt.sh/howto-c (日本語訳を作ってくださっている方のページは http://postd.cc/how-to-c-in-2016-1/ )を、分析してみるシリーズです。

前回は、「2016年、C言語はどう書くべきか」をちょっと分析してみる (warning編)は、warning編でしたが、今回は、building編です。


Link Time Optimization

gcc, clang共に、-fltoでサポートされるLink Time Optimizationについて、見てみます。

が、公式のドキュメントです。

link時点で、使われないことがわかった不要なコードを排除するような最適化をしようというのが、LTOということのようです。

LLVMのサイトには、

The LLVM Link Time Optimizer provides complete transparency, while doing intermodular optimization, in the compiler tool chain. Its main goal is to let the developer take advantage of intermodular optimizations without making any significant changes to the developer’s makefiles or build system. This is achieved through tight integration with the linker. In this model, the linker treates LLVM bitcode files like native object files and allows mixing and matching among them. The linker uses libLTO, a shared object, to handle LLVM bitcode files. This tight integration between the linker and LLVM optimizer helps to do optimizations that are not possible in other models. The linker input allows the optimizer to avoid relying on conservative escape analysis.

抄訳は、LLVM Link Time Optimizeは、compiler tool chainとして、モジュール間の最適化を行うときに、完全に透過性を提供します。メインゴールは、開発者に、makefileやbuild systemに、どんな大きな変更もなしに、module間最適化の恩恵を受けられるようにすることです。これは、linkerと密結合されることで実現します。このモデルにおいてlinkerは、LLVM bit codeファイルをnative object fileのように扱い、それらの間でmatchingやmixingを許します。liknerは、LLVM bit codeのファイルを扱うために、shared objectであるlibLTOを使います。このlinkerとLLVM optimizerの密結合によって、他のモデルでは実現できない最適化を実現します。そのlinkerの入力が、optimizerに、保守的で逃げ的な分析に頼ることを避けるようにします。

実際には、

http://llvm.org/docs/GoldPlugin.html

のとおり、

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

のように、compilerに-fltoをoptionとして渡しておくことと、

http://llvm.org/docs/GoldPlugin.html#lto-how-to-build

のとおり、

$ /usr/bin/ld -v

@(#)PROGRAM:ld PROJECT:ld64-253.9
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
LTO support using: Apple LLVM 7.0.2 (clang-700.1.81)

LTO supportと、Macだと出るようなので、大丈夫かな?

$  clang -flto

clang: error: no input files

のように認識もしてくれていますので。

なお、

LTO still needs some babysitting though. Sometimes, if your program has code not used directly but used by additional libraries, LTO can evict functions or code because it detects, globally when linking, some code is unused/unreachable and doesn't need to be included in the final linked result.

とも書かれており、link時に最適化された結果、不要と判断された実装などがなくなるので、それはそれで気をつけないといけなそうです。まだまだbaby sittingとも書かれていますので^^;

つづく