| # FatLTO | |
| ## Introduction | |
| FatLTO objects are a special type of [fat object file](https://en.wikipedia.org/wiki/Fat_binary) that contain LTO compatible IR in | |
| addition to generated object code, instead of containing object code for | |
| multiple target architectures. This allows users to defer the choice of whether | |
| to use LTO or not to link-time, and has been a feature available in other | |
| compilers, like [GCC](https://gcc.gnu.org/onlinedocs/gccint/LTO-Overview.html), for some time. | |
| Under FatLTO the compiler can emit standard object files which contain both the | |
| machine code in the `.text` section and LLVM bitcode in the `.llvm.lto` | |
| section. | |
| ## Overview | |
| Within LLVM, FatLTO is supported by choosing the `FatLTODefaultPipeline`. | |
| This pipeline will: | |
| 1. Run the pre-link (Thin)LTO pipeline on the current module. | |
| 2. Embed the pre-link bitcode in a special `.llvm.lto` section. | |
| 3. Finish optimizing the module using the ModuleOptimization pipeline. | |
| 4. Emit the object file, including the new `.llvm.lto` section. | |
| % NOTE | |
| % | |
| % Previously, we conservatively ran independent pipelines on separate copies | |
| % of the LLVM module to generate the bitcode section and the object code, | |
| % which happened to be identical to those used outside of FatLTO. While that | |
| % resulted in compiled artifacts that were identical to those produced by the | |
| % default and (Thin)LTO pipelines, module cloning led to some cases of | |
| % miscompilation, and we have moved away from trying to keep bitcode | |
| % generation and optimization completely disjoint. | |
| % | |
| % Bit-for-bit compatibility is not (and never was) a guarantee, and we reserve | |
| % the right to change this at any time. Explicitly, users should not rely on | |
| % the produced bitcode or object code to match their non-LTO counterparts | |
| % precisely. They will exhibit similar performance characteristics, but may | |
| % not be bit-for-bit the same. | |
| Internally, the `.llvm.lto` section is created by running the | |
| `EmbedBitcodePass` after the `ThinLTOPreLinkDefaultPipeline`. This pass is | |
| responsible for emitting the `.llvm.lto` section. Afterwards, the | |
| `ThinLTODefaultPipeline` runs and the compiler can emit the fat object file. | |
| ## Limitations | |
| ### Linkers | |
| Currently, using LTO with LLVM fat lto objects is supported by LLD and by the | |
| GNU linkers via {doc}`GoldPlugin`. This may change in the future, but | |
| extending support to other linkers isn't planned for now. | |
| % NOTE | |
| % For standard linking the fat object files should be usable by any | |
| % linker capable of using ELF objects, since the ``.llvm.lto`` section is | |
| % marked ``SHF_EXCLUDE``. | |
| ### Supported File Formats | |
| The current implementation only supports ELF files. At time of writing, it is | |
| unclear if it will be useful to support other object file formats like `COFF` | |
| or `Mach-O`. | |
| ## Usage | |
| Clang users can specify `-ffat-lto-objects` with `-flto` or `-flto=thin`. | |
| Without the `-flto` option, `-ffat-lto-objects` has no effect. | |
| Compile an object file using FatLTO: | |
| ```console | |
| $ clang -flto -ffat-lto-objects example.c -c -o example.o | |
| ``` | |
| Link using the object code from the fat object without LTO. This turns | |
| `-ffat-lto-objects` into a no-op, when `-fno-lto` is specified: | |
| ```console | |
| $ clang -fno-lto -ffat-lto-objects -fuse-ld=lld example.o | |
| ``` | |
| Alternatively, you can omit any references to LTO with fat objects and retain standard linker behavior: | |
| ```console | |
| $ clang -fuse-ld=lld example.o | |
| ``` | |
| Link using the LLVM bitcode from the fat object with Full LTO: | |
| ```console | |
| $ clang -flto -ffat-lto-objects -fuse-ld=lld example.o # clang will pass --lto=full --fat-lto-objects to ld.lld | |
| ``` | |
| Link using the LLVM bitcode from the fat object with Thin LTO: | |
| ```console | |
| $ clang -flto=thin -ffat-lto-objects -fuse-ld=lld example.o # clang will pass --lto=thin --fat-lto-objects to ld.lld | |
| ``` |