Skip to content

Commit ab9b3c8

Browse files
committed
[lld] A Unified LTO Bitcode Frontend
The unified LTO pipeline creates a single LTO bitcode structure that can be used by Thin or Full LTO. This means that the LTO mode can be chosen at link time and that all LTO bitcode produced by the pipeline is compatible, from an optimization perspective. This makes the behavior of LTO a bit more predictable by normalizing the set of LTO features supported by each LTO bitcode file. Example usage: clang -flto -funified-lto -fuse-ld=lld foo.c clang -flto=thin -funified-lto -fuse-ld=lld foo.c clang -c -flto -funified-lto foo.c # -flto={full,thin} are identical in terms of compilation actions clang -flto=thin -fuse-ld=lld foo.o # pass --lto=thin to ld.lld clang -c -flto -funified-lto foo.c clang -flto -fuse-ld=lld foo.o The RFC discussing the details and rational for this change is here: https://discourse.llvm.org/t/rfc-a-unified-lto-bitcode-frontend/61774 Differential Revision: https://reviews.llvm.org/D123805
1 parent 1e62587 commit ab9b3c8

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

lld/ELF/Config.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ enum class SeparateSegmentKind { None, Code, Loadable };
9696
// For -z *stack
9797
enum class GnuStackKind { None, Exec, NoExec };
9898

99+
// For --lto=
100+
enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default};
101+
99102
struct SymbolVersion {
100103
llvm::StringRef name;
101104
bool isExternCpp;
@@ -415,6 +418,9 @@ struct Config {
415418
// not supported on Android 11 & 12.
416419
bool androidMemtagStack;
417420

421+
// When using a unified pre-link LTO pipeline, specify the backend LTO mode.
422+
LtoKind ltoKind = LtoKind::Default;
423+
418424
unsigned threadCount;
419425

420426
// If an input file equals a key, remap it to the value.

lld/ELF/Driver.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,19 @@ static void readConfigs(opt::InputArgList &args) {
14891489
config->mllvmOpts.emplace_back(arg->getValue());
14901490
}
14911491

1492+
config->ltoKind = LtoKind::Default;
1493+
if (auto *arg = args.getLastArg(OPT_lto)) {
1494+
StringRef s = arg->getValue();
1495+
if (s == "thin")
1496+
config->ltoKind = LtoKind::UnifiedThin;
1497+
else if (s == "full")
1498+
config->ltoKind = LtoKind::UnifiedRegular;
1499+
else if (s == "default")
1500+
config->ltoKind = LtoKind::Default;
1501+
else
1502+
error("unknown LTO mode: " + s);
1503+
}
1504+
14921505
// --threads= takes a positive integer and provides the default value for
14931506
// --thinlto-jobs=. If unspecified, cap the number of threads since
14941507
// overhead outweighs optimization for used parallel algorithms for the

lld/ELF/LTO.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,13 @@ BitcodeCompiler::BitcodeCompiler() {
206206
config->thinLTOEmitImportsFiles);
207207
}
208208

209-
ltoObj = std::make_unique<lto::LTO>(createConfig(), backend,
210-
config->ltoPartitions);
209+
constexpr llvm::lto::LTO::LTOKind ltoModes[3] =
210+
{llvm::lto::LTO::LTOKind::LTOK_UnifiedThin,
211+
llvm::lto::LTO::LTOKind::LTOK_UnifiedRegular,
212+
llvm::lto::LTO::LTOKind::LTOK_Default};
213+
ltoObj = std::make_unique<lto::LTO>(
214+
createConfig(), backend, config->ltoPartitions,
215+
ltoModes[config->ltoKind]);
211216

212217
// Initialize usedStartStop.
213218
if (ctx.bitcodeFiles.empty())

lld/ELF/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ def: JoinedOrSeparate<["-"], "u">, Alias<undefined>, HelpText<"Alias for --undef
577577
def: Flag<["-"], "V">, Alias<v>, HelpText<"Alias for -v">;
578578

579579
// LTO-related options.
580+
581+
def lto: JJ<"lto=">, HelpText<"Set LTO backend">,
582+
MetaVarName<"[full,thin]">;
580583
def lto_aa_pipeline: JJ<"lto-aa-pipeline=">,
581584
HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
582585
def lto_debug_pass_manager: FF<"lto-debug-pass-manager">,

lld/test/ELF/lto/unified-lto.ll

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; REQUIRES: x86
2+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %s -o %t0.o
3+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit %s -o %t1.o
4+
; RUN: ld.lld --lto=full %t0.o -o %t0
5+
; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=FULL
6+
; RUN: ld.lld --lto=thin %t0.o -o %t0
7+
; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
8+
; RUN: ld.lld --lto=default %t0.o -o %t0
9+
; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
10+
; RUN: ld.lld --lto=default %t1.o -o %t1
11+
; RUN: llvm-readelf -s %t1 | FileCheck %s --check-prefix=THIN
12+
; RUN: ld.lld %t0.o -o %t0 2>&1 | count 0
13+
; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
14+
; RUN: not ld.lld --lto=unknown %t1.o -o /dev/null 2>&1 | \
15+
; RUN: FileCheck --implicit-check-not=error: --check-prefix=ERR %s
16+
; ERR: error: unknown LTO mode: unknown
17+
18+
; FULL: Symbol table '.symtab' contains 3 entries:
19+
; FULL-NEXT: Num: Value Size Type Bind Vis Ndx Name
20+
; FULL-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
21+
; FULL-NEXT: 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS ld-temp.o
22+
; FULL-NEXT: 2: 0000000000201120 1 FUNC GLOBAL DEFAULT 1 _start
23+
24+
; THIN: Symbol table '.symtab' contains 3 entries:
25+
; THIN-NEXT: Num: Value Size Type Bind Vis Ndx Name
26+
; THIN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
27+
; THIN-NEXT: 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS unified-lto.ll
28+
; THIN-NEXT: 2: 0000000000201120 1 FUNC GLOBAL DEFAULT 1 _start
29+
30+
target triple = "x86_64-unknown-linux-gnu"
31+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
32+
33+
define void @_start() {
34+
ret void
35+
}

0 commit comments

Comments
 (0)