FatLTO

简介

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

在 FatLTO 下,编译器可以生成标准目标文件,其中包含 .text 节中的机器代码和 .llvm.lto 节中的 LLVM bitcode。

概述

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

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

  2. 将预链接 bitcode 嵌入到特殊的 .llvm.lto 节中。

  3. 使用 ModuleOptimization pipeline 完成模块的优化。

  4. 生成目标文件,包括新的 .llvm.lto 节。

在内部,.llvm.lto 节是通过在 ThinLTOPreLinkDefaultPipeline 之后运行 EmbedBitcodePass 创建的。 此 pass 负责生成 .llvm.lto 节。 之后,ThinLTODefaultPipeline 运行,编译器可以生成胖目标文件。

局限性

链接器

目前,LLD 和 GNU 链接器通过 LLVM gold 插件 支持将 LTO 与 LLVM fat lto 对象一起使用。 未来这可能会改变,但目前尚无计划将支持扩展到其他链接器。

支持的文件格式

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

用法

Clang 用户可以使用 -flto-flto=thin 指定 -ffat-lto-objects。 如果没有 -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 bitcode 和 Full LTO

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

链接时使用来自胖对象的 LLVM bitcode 和 Thin LTO

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