FatLTO

简介

FatLTO 对象是一种特殊的 胖目标文件,除了生成的目标代码外,还包含与 LTO 兼容的 IR,而不是包含针对多个目标架构的目标代码。这允许用户将是否使用 LTO 的选择推迟到链接时,并且在其他编译器(如 GCC)中已经存在一段时间了。

在 FatLTO 下,编译器可以发出标准的目标文件,这些文件同时包含 .text 部分中的机器代码和 .llvm.lto 部分中的 LLVM 位代码。

概述

在 LLVM 中,通过选择 FatLTODefaultPipeline 来支持 FatLTO。此管道将

  1. 在当前模块上运行预链接(Thin)LTO 管道。

  2. 将预链接位代码嵌入到特殊的 .llvm.lto 部分中。

  3. 使用 ModuleOptimization 管道完成模块优化。

  4. 发出目标文件,包括新的 .llvm.lto 部分。

在内部,.llvm.lto 部分是通过在 ThinLTOPreLinkDefaultPipeline 之后运行 EmbedBitcodePass 创建的。此传递负责发出 .llvm.lto 部分。之后,ThinLTODefaultPipeline 运行,编译器可以发出胖目标文件。

限制

链接器

目前,LLD 和通过 LLVM gold 插件 的 GNU 链接器支持使用带有 LLVM 胖 lto 对象的 LTO。这在将来可能会发生变化,但目前不打算将支持扩展到其他链接器。

支持的文件格式

当前实现仅支持 ELF 文件。在撰写本文时,尚不清楚是否支持其他目标文件格式(如 COFFMach-O)是否有用。

用法

Clang 用户可以将 -ffat-lto-objects-flto-flto=thin 一起指定。如果没有 -flto 选项,则 -ffat-lto-objects 不会有任何作用。

使用 FatLTO 编译目标文件

$ clang -flto -ffat-lto-objects example.c -c -o example.o

使用胖目标文件中的目标代码进行链接,但不使用 LTO。当指定 -fno-lto 时,这会将 -ffat-lto-objects 变成一个无操作。

$ clang -fno-lto -ffat-lto-objects -fuse-ld=lld example.o

或者,您可以省略对胖对象中 LTO 的任何引用并保留标准链接器行为

$ clang -fuse-ld=lld example.o

使用胖目标文件中的 LLVM 位代码进行链接,使用完整 LTO

$ clang -flto -ffat-lto-objects -fuse-ld=lld example.o  # clang will pass --lto=full --fat-lto-objects to ld.lld

使用胖目标文件中的 LLVM 位代码进行链接,使用 Thin LTO

$ clang -flto=thin -ffat-lto-objects -fuse-ld=lld example.o  # clang will pass --lto=thin --fat-lto-objects to ld.lld