Index: lld/ELF/Config.h =================================================================== --- lld/ELF/Config.h +++ lld/ELF/Config.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/LTO/LTO.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" @@ -412,6 +413,8 @@ // this means to map the primary and thread stacks as PROT_MTE. Note: This is // not supported on Android 11 & 12. bool androidMemtagStack; + // When using a unified pre-link LTO pipeline, specify the backend LTO mode. + llvm::lto::LTO::LTOKind forceLTOMode = llvm::lto::LTO::LTOK_Default; unsigned threadCount; Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -1481,6 +1481,19 @@ config->mllvmOpts.emplace_back(arg->getValue()); } + config->forceLTOMode = llvm::lto::LTO::LTOK_Default; + if (auto *arg = args.getLastArg(OPT_lto_type_eq)) { + StringRef s = arg->getValue(); + if (s == "thin") + config->forceLTOMode = llvm::lto::LTO::LTOK_UnifiedThin; + else if (s == "full") + config->forceLTOMode = llvm::lto::LTO::LTOK_UnifiedRegular; + else if (s == "default") + config->forceLTOMode = llvm::lto::LTO::LTOK_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 Index: lld/ELF/LTO.cpp =================================================================== --- lld/ELF/LTO.cpp +++ lld/ELF/LTO.cpp @@ -206,8 +206,8 @@ config->thinLTOEmitImportsFiles); } - ltoObj = std::make_unique(createConfig(), backend, - config->ltoPartitions); + ltoObj = std::make_unique( + createConfig(), backend, config->ltoPartitions, config->forceLTOMode); // Initialize usedStartStop. if (ctx.bitcodeFiles.empty()) Index: lld/ELF/Options.td =================================================================== --- lld/ELF/Options.td +++ lld/ELF/Options.td @@ -577,6 +577,9 @@ def: Flag<["-"], "V">, Alias, HelpText<"Alias for -v">; // LTO-related options. + +def lto_type_eq: J<"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">, Index: lld/test/ELF/lto/unified-lto.ll =================================================================== --- /dev/null +++ lld/test/ELF/lto/unified-lto.ll @@ -0,0 +1,32 @@ +; 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 %t2 +; RUN: llvm-readobj --symbols %t2 | FileCheck %s +; RUN: ld.lld --lto=thin %t0.o -o %t2 +; RUN: llvm-readobj --symbols %t2 | FileCheck %s +; RUN: ld.lld --lto=default %t0.o -o %t2 +; RUN: llvm-readobj --symbols %t2 | FileCheck %s +; RUN: ld.lld --lto=default %t1.o -o %t2 +; RUN: llvm-readobj --symbols %t2 | FileCheck %s +; RUN: ld.lld %t0.o -o %t2 +; RUN: llvm-readobj --symbols %t2 | FileCheck %s + +; CHECK: Format: elf64-x86-64 +; CHECK-NEXT: Arch: x86_64 +; CHECK-NEXT: AddressSize: 64bit + +; CHECK: Name: _start +; CHECK-NEXT: Value: +; CHECK-NEXT: Size: 1 +; CHECK-NEXT: Binding: Global +; CHECK-NEXT: Type: Function +; CHECK-NEXT: Other: +; CHECK-NEXT: Section: .text + +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 +}