aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorMatthew Voss <matthew.voss@sony.com>2023-07-18 16:13:58 -0700
committerMatthew Voss <matthew.voss@sony.com>2023-07-18 16:13:58 -0700
commitab9b3c84a588f86e7f66eeb577bea7155817ff06 (patch)
treef67e268ab3d8295e5e84a6354bd43037d562802a /lld
parent1e62587a48a33b3bf5939e1eef2fd4e41b7e75f6 (diff)
downloadllvm-ab9b3c84a588f86e7f66eeb577bea7155817ff06.zip
llvm-ab9b3c84a588f86e7f66eeb577bea7155817ff06.tar.gz
llvm-ab9b3c84a588f86e7f66eeb577bea7155817ff06.tar.bz2
[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
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Config.h6
-rw-r--r--lld/ELF/Driver.cpp13
-rw-r--r--lld/ELF/LTO.cpp9
-rw-r--r--lld/ELF/Options.td3
-rw-r--r--lld/test/ELF/lto/unified-lto.ll35
5 files changed, 64 insertions, 2 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 797b772..bbf2d201 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -96,6 +96,9 @@ enum class SeparateSegmentKind { None, Code, Loadable };
// For -z *stack
enum class GnuStackKind { None, Exec, NoExec };
+// For --lto=
+enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default};
+
struct SymbolVersion {
llvm::StringRef name;
bool isExternCpp;
@@ -415,6 +418,9 @@ struct Config {
// not supported on Android 11 & 12.
bool androidMemtagStack;
+ // When using a unified pre-link LTO pipeline, specify the backend LTO mode.
+ LtoKind ltoKind = LtoKind::Default;
+
unsigned threadCount;
// If an input file equals a key, remap it to the value.
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 26283e1..4e3ab2c 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1489,6 +1489,19 @@ static void readConfigs(opt::InputArgList &args) {
config->mllvmOpts.emplace_back(arg->getValue());
}
+ config->ltoKind = LtoKind::Default;
+ if (auto *arg = args.getLastArg(OPT_lto)) {
+ StringRef s = arg->getValue();
+ if (s == "thin")
+ config->ltoKind = LtoKind::UnifiedThin;
+ else if (s == "full")
+ config->ltoKind = LtoKind::UnifiedRegular;
+ else if (s == "default")
+ config->ltoKind = LtoKind::Default;
+ else
+ error("unknown LTO mode: " + s);
+ }
+
// --threads= takes a positive integer and provides the default value for
// --thinlto-jobs=. If unspecified, cap the number of threads since
// overhead outweighs optimization for used parallel algorithms for the
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 9d927b0..e8bfa90 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -206,8 +206,13 @@ BitcodeCompiler::BitcodeCompiler() {
config->thinLTOEmitImportsFiles);
}
- ltoObj = std::make_unique<lto::LTO>(createConfig(), backend,
- config->ltoPartitions);
+ constexpr llvm::lto::LTO::LTOKind ltoModes[3] =
+ {llvm::lto::LTO::LTOKind::LTOK_UnifiedThin,
+ llvm::lto::LTO::LTOKind::LTOK_UnifiedRegular,
+ llvm::lto::LTO::LTOKind::LTOK_Default};
+ ltoObj = std::make_unique<lto::LTO>(
+ createConfig(), backend, config->ltoPartitions,
+ ltoModes[config->ltoKind]);
// Initialize usedStartStop.
if (ctx.bitcodeFiles.empty())
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 5de93f0..0d5c6c3 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -577,6 +577,9 @@ def: JoinedOrSeparate<["-"], "u">, Alias<undefined>, HelpText<"Alias for --undef
def: Flag<["-"], "V">, Alias<v>, HelpText<"Alias for -v">;
// LTO-related options.
+
+def lto: JJ<"lto=">, HelpText<"Set LTO backend">,
+ MetaVarName<"[full,thin]">;
def lto_aa_pipeline: JJ<"lto-aa-pipeline=">,
HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
def lto_debug_pass_manager: FF<"lto-debug-pass-manager">,
diff --git a/lld/test/ELF/lto/unified-lto.ll b/lld/test/ELF/lto/unified-lto.ll
new file mode 100644
index 0000000..50d9606
--- /dev/null
+++ b/lld/test/ELF/lto/unified-lto.ll
@@ -0,0 +1,35 @@
+; REQUIRES: x86
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %s -o %t0.o
+; RUN: opt -thinlto-bc -thinlto-split-lto-unit %s -o %t1.o
+; RUN: ld.lld --lto=full %t0.o -o %t0
+; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=FULL
+; RUN: ld.lld --lto=thin %t0.o -o %t0
+; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
+; RUN: ld.lld --lto=default %t0.o -o %t0
+; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
+; RUN: ld.lld --lto=default %t1.o -o %t1
+; RUN: llvm-readelf -s %t1 | FileCheck %s --check-prefix=THIN
+; RUN: ld.lld %t0.o -o %t0 2>&1 | count 0
+; RUN: llvm-readelf -s %t0 | FileCheck %s --check-prefix=THIN
+; RUN: not ld.lld --lto=unknown %t1.o -o /dev/null 2>&1 | \
+; RUN: FileCheck --implicit-check-not=error: --check-prefix=ERR %s
+; ERR: error: unknown LTO mode: unknown
+
+; FULL: Symbol table '.symtab' contains 3 entries:
+; FULL-NEXT: Num: Value Size Type Bind Vis Ndx Name
+; FULL-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+; FULL-NEXT: 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS ld-temp.o
+; FULL-NEXT: 2: 0000000000201120 1 FUNC GLOBAL DEFAULT 1 _start
+
+; THIN: Symbol table '.symtab' contains 3 entries:
+; THIN-NEXT: Num: Value Size Type Bind Vis Ndx Name
+; THIN-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+; THIN-NEXT: 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS unified-lto.ll
+; THIN-NEXT: 2: 0000000000201120 1 FUNC GLOBAL DEFAULT 1 _start
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @_start() {
+ ret void
+}