[clang] [lld] [llvm] [LTO][LLD] Prevent invalid LTO libfunc transforms (PR #164916)
Daniel Thornburgh via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 15 15:52:00 PST 2026
https://github.com/mysterymath updated https://github.com/llvm/llvm-project/pull/164916
>From 935b972840238daf88a41954f63e6a8b6918d764 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 7 Aug 2025 16:05:09 -0700
Subject: [PATCH 1/9] [LTO][LLD] Prevent invalid LTO libfunc transforms
This patch ensures that:
1) New bitcode is not extracted for libfuncs after LTO occurs, and
2) Extracted bitcode for libfuncs is considered external, since new
calls to it may be emitted.
---
clang/lib/CodeGen/BackendUtil.cpp | 10 +--
lld/ELF/Driver.cpp | 19 +++++-
lld/ELF/LTO.cpp | 5 +-
lld/ELF/LTO.h | 3 +-
lld/test/ELF/lto/libcall-archive-bitcode.test | 41 ++++++++++++
llvm/include/llvm/LTO/LTO.h | 24 ++++++-
llvm/include/llvm/LTO/LTOBackend.h | 7 ++-
llvm/lib/LTO/LTO.cpp | 62 +++++++++++++------
llvm/lib/LTO/LTOBackend.cpp | 43 ++++++++++---
llvm/lib/LTO/LTOCodeGenerator.cpp | 4 +-
llvm/lib/Object/CMakeLists.txt | 1 +
llvm/lib/Object/IRSymtab.cpp | 8 ++-
.../X86/libcall-external-bitcode.ll | 20 ++++++
.../X86/libcall-external-not-bitcode.ll | 20 ++++++
llvm/test/LTO/Resolution/X86/libcall-in-tu.ll | 34 ++++++++++
llvm/tools/llvm-lto2/llvm-lto2.cpp | 7 +++
16 files changed, 266 insertions(+), 42 deletions(-)
create mode 100644 lld/test/ELF/lto/libcall-archive-bitcode.test
create mode 100644 llvm/test/LTO/Resolution/X86/libcall-external-bitcode.ll
create mode 100644 llvm/test/LTO/Resolution/X86/libcall-external-not-bitcode.ll
create mode 100644 llvm/test/LTO/Resolution/X86/libcall-in-tu.ll
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 26794a9cbc11d..862075db2dc5f 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1408,11 +1408,11 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
// FIXME: Both ExecuteAction and thinBackend set up optimization remarks for
// the same context.
finalizeLLVMOptimizationRemarks(M->getContext());
- if (Error E =
- thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
- ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
- /*ModuleMap=*/nullptr, Conf.CodeGenOnly,
- /*IRAddStream=*/nullptr, CGOpts.CmdArgs)) {
+ if (Error E = thinBackend(
+ Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
+ ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
+ /*ModuleMap=*/nullptr, Conf.CodeGenOnly, /*BitcodeLibFuncs=*/{},
+ /*IRAddStream=*/nullptr, CGOpts.CmdArgs)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
});
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 8647752be31fe..b0834e6c26b7a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2701,15 +2701,30 @@ static void markBuffersAsDontNeed(Ctx &ctx, bool skipLinkedOutput) {
template <class ELFT>
void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
llvm::TimeTraceScope timeScope("LTO");
+ // Capture the triple before moving the bitcode into the bitcode compiler.
+ std::optional<llvm::Triple> tt;
+ if (!ctx.bitcodeFiles.empty())
+ tt = llvm::Triple(ctx.bitcodeFiles.front()->obj->getTargetTriple());
// Compile bitcode files and replace bitcode symbols.
lto.reset(new BitcodeCompiler(ctx));
for (BitcodeFile *file : ctx.bitcodeFiles)
lto->add(*file);
- if (!ctx.bitcodeFiles.empty())
+ llvm::BumpPtrAllocator alloc;
+ llvm::StringSaver saver(alloc);
+ SmallVector<StringRef> bitcodeLibFuncs;
+ if (!ctx.bitcodeFiles.empty()) {
markBuffersAsDontNeed(ctx, skipLinkedOutput);
+ for (StringRef libFunc : lto::LTO::getLibFuncSymbols(*tt, saver)) {
+ Symbol *sym = ctx.symtab->find(libFunc);
+ if (!sym)
+ continue;
+ if (isa<BitcodeFile>(sym->file))
+ bitcodeLibFuncs.push_back(libFunc);
+ }
+ }
- ltoObjectFiles = lto->compile();
+ ltoObjectFiles = lto->compile(bitcodeLibFuncs);
for (auto &file : ltoObjectFiles) {
auto *obj = cast<ObjFile<ELFT>>(file.get());
obj->parse(/*ignoreComdats=*/true);
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 44a679498ed1d..49f6d15b346ae 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -316,7 +316,10 @@ static void thinLTOCreateEmptyIndexFiles(Ctx &ctx) {
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile(s).
-SmallVector<std::unique_ptr<InputFile>, 0> BitcodeCompiler::compile() {
+SmallVector<std::unique_ptr<InputFile>, 0>
+BitcodeCompiler::compile(const SmallVector<StringRef> &bitcodeLibFuncs) {
+ ltoObj->setBitcodeLibFuncs(bitcodeLibFuncs);
+
unsigned maxTasks = ltoObj->getMaxTasks();
buf.resize(maxTasks);
files.resize(maxTasks);
diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h
index acf3bcff7f2f1..8207e91460785 100644
--- a/lld/ELF/LTO.h
+++ b/lld/ELF/LTO.h
@@ -42,7 +42,8 @@ class BitcodeCompiler {
~BitcodeCompiler();
void add(BitcodeFile &f);
- SmallVector<std::unique_ptr<InputFile>, 0> compile();
+ SmallVector<std::unique_ptr<InputFile>, 0>
+ compile(const SmallVector<StringRef> &bitcodeLibFuncs);
private:
Ctx &ctx;
diff --git a/lld/test/ELF/lto/libcall-archive-bitcode.test b/lld/test/ELF/lto/libcall-archive-bitcode.test
new file mode 100644
index 0000000000000..20735b5c89c99
--- /dev/null
+++ b/lld/test/ELF/lto/libcall-archive-bitcode.test
@@ -0,0 +1,41 @@
+; REQUIRES: x86
+
+; RUN: rm -rf %t && split-file %s %t && cd %t
+; RUN: llvm-as main.ll -o main.o
+; RUN: llvm-as bcmp.ll -o bcmp.o
+; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnu memcmp.s -o memcmp.o
+; RUN: llvm-ar rc libc.a bcmp.o memcmp.o
+
+;; Ensure that no memcmp->bcmp translation occurs during LTO because bcmp is in
+;; bitcode, but was not brought into the link. This would fail the link by
+;; extracting bitcode after LTO.
+; RUN: ld.lld -o out main.o -L. -lc
+; RUN: llvm-nm out | FileCheck %s
+
+;--- bcmp.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @bcmp(ptr %0, ptr %1, i64 %2) {
+ ret i32 0
+}
+
+;--- memcmp.s
+.globl memcmp
+memcmp:
+ ret
+
+;--- main.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i1 @_start(ptr %0, ptr %1, i64 %2) {
+ %cmp = call i32 @memcmp(ptr %0, ptr %1, i64 %2)
+ %eq = icmp eq i32 %cmp, 0
+ ret i1 %eq
+}
+
+; CHECK-NOT: bcmp
+; CHECK: memcmp
+declare i32 @memcmp(ptr, ptr, i64)
+
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 819be1909ec12..66a3a80d7d61e 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -287,7 +287,8 @@ class ThinBackendProc {
using ThinBackendFunction = std::function<std::unique_ptr<ThinBackendProc>(
const Config &C, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, FileCache Cache)>;
+ AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs)>;
/// This type defines the behavior following the thin-link phase during ThinLTO.
/// It encapsulates a backend function and a strategy for thread pool
@@ -302,10 +303,11 @@ struct ThinBackend {
std::unique_ptr<ThinBackendProc> operator()(
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, FileCache Cache) {
+ AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
assert(isValid() && "Invalid backend function");
return Func(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
- std::move(AddStream), std::move(Cache));
+ std::move(AddStream), std::move(Cache), BitcodeLibFuncs);
}
ThreadPoolStrategy getParallelism() const { return Parallelism; }
bool isValid() const { return static_cast<bool>(Func); }
@@ -423,6 +425,12 @@ class LTO {
LLVM_ABI Error add(std::unique_ptr<InputFile> Obj,
ArrayRef<SymbolResolution> Res);
+ /// Set the list of functions implemented in bitcode across the link, whether
+ /// extracted or not. Such functions may not be referenced if they were not
+ /// extracted by the time LTO occurs.
+ LLVM_ABI void
+ setBitcodeLibFuncs(const SmallVector<StringRef> &BitcodeLibFuncs);
+
/// Returns an upper bound on the number of tasks that the client may expect.
/// This may only be called after all IR object files have been added. For a
/// full description of tasks see LTOBackend.h.
@@ -443,6 +451,14 @@ class LTO {
LLVM_ABI static SmallVector<const char *>
getRuntimeLibcallSymbols(const Triple &TT);
+ /// Static method that returns a list of library function symbols that can be
+ /// generated by LTO but might not be visible from bitcode symbol table.
+ /// Unlike the runtime libcalls, the linker can report to the code generator
+ /// which of these are actually available in the link, and the code generator
+ /// can then only reference that set of symbols.
+ LLVM_ABI static SmallVector<StringRef>
+ getLibFuncSymbols(const Triple &TT, llvm::StringSaver &Saver);
+
private:
Config Conf;
@@ -615,6 +631,8 @@ class LTO {
// Diagnostic optimization remarks file
LLVMRemarkFileHandle DiagnosticOutputFile;
+ SmallVector<StringRef> BitcodeLibFuncs;
+
public:
virtual Expected<std::shared_ptr<lto::InputFile>>
addInput(std::unique_ptr<lto::InputFile> InputPtr) {
diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h
index 48ad5aa64f61f..6a7d7e0d87ac9 100644
--- a/llvm/include/llvm/LTO/LTOBackend.h
+++ b/llvm/include/llvm/LTO/LTOBackend.h
@@ -39,13 +39,15 @@ LLVM_ABI bool opt(const Config &Conf, TargetMachine *TM, unsigned Task,
Module &Mod, bool IsThinLTO,
ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary,
- const std::vector<uint8_t> &CmdArgs);
+ const std::vector<uint8_t> &CmdArgs,
+ const SmallVector<StringRef> &BitcodeLibFuncs);
/// Runs a regular LTO backend. The regular LTO backend can also act as the
/// regular LTO phase of ThinLTO, which may need to access the combined index.
LLVM_ABI Error backend(const Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel, Module &M,
- ModuleSummaryIndex &CombinedIndex);
+ ModuleSummaryIndex &CombinedIndex,
+ const SmallVector<StringRef> &BitcodeLibFuncs);
/// Runs a ThinLTO backend.
/// If \p ModuleMap is not nullptr, all the module files to be imported have
@@ -62,6 +64,7 @@ thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
const FunctionImporter::ImportMapTy &ImportList,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> *ModuleMap, bool CodeGenOnly,
+ const SmallVector<StringRef> &BitcodeLibFuncs,
AddStreamFn IRAddStream = nullptr,
const std::vector<uint8_t> &CmdArgs = std::vector<uint8_t>());
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index ff6762ebb59be..ee8db650cf20e 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -771,6 +771,10 @@ Error LTO::add(std::unique_ptr<InputFile> InputPtr,
return Error::success();
}
+void LTO::setBitcodeLibFuncs(const SmallVector<StringRef> &BitcodeLibFuncs) {
+ this->BitcodeLibFuncs = BitcodeLibFuncs;
+}
+
Expected<ArrayRef<SymbolResolution>>
LTO::addModule(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
unsigned ModI, ArrayRef<SymbolResolution> Res) {
@@ -1400,9 +1404,9 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
}
if (!RegularLTO.EmptyCombinedModule || Conf.AlwaysEmitRegularLTOObj) {
- if (Error Err =
- backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
- *RegularLTO.CombinedModule, ThinLTO.CombinedIndex))
+ if (Error Err = backend(
+ Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
+ *RegularLTO.CombinedModule, ThinLTO.CombinedIndex, BitcodeLibFuncs))
return Err;
}
@@ -1422,6 +1426,21 @@ SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
return LibcallSymbols;
}
+SmallVector<StringRef> LTO::getLibFuncSymbols(const Triple &TT,
+ StringSaver &Saver) {
+ auto TLII = std::make_unique<TargetLibraryInfoImpl>(TT);
+ TargetLibraryInfo TLI(*TLII);
+ SmallVector<StringRef> LibFuncSymbols;
+ LibFuncSymbols.reserve(LibFunc::NumLibFuncs);
+ for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); I != E;
+ ++I) {
+ LibFunc F = static_cast<LibFunc>(I);
+ if (TLI.has(F))
+ LibFuncSymbols.push_back(Saver.save(TLI.getName(F)).data());
+ }
+ return LibFuncSymbols;
+}
+
Error ThinBackendProc::emitFiles(
const FunctionImporter::ImportMapTy &ImportList, llvm::StringRef ModulePath,
const std::string &NewModulePath) const {
@@ -1499,6 +1518,7 @@ class CGThinBackend : public ThinBackendProc {
class InProcessThinBackend : public CGThinBackend {
protected:
FileCache Cache;
+ const SmallVector<StringRef> &BitcodeLibFuncs;
public:
InProcessThinBackend(
@@ -1506,11 +1526,12 @@ class InProcessThinBackend : public CGThinBackend {
ThreadPoolStrategy ThinLTOParallelism,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache, lto::IndexWriteCallback OnWrite,
- bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles)
+ bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles,
+ const SmallVector<StringRef> &BitcodeLibFuncs)
: CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
AddStream, OnWrite, ShouldEmitIndexFiles,
ShouldEmitImportsFiles, ThinLTOParallelism),
- Cache(std::move(Cache)) {}
+ Cache(std::move(Cache)), BitcodeLibFuncs(BitcodeLibFuncs) {}
virtual Error runThinLTOBackendThread(
AddStreamFn AddStream, FileCache Cache, unsigned Task, BitcodeModule BM,
@@ -1531,7 +1552,7 @@ class InProcessThinBackend : public CGThinBackend {
return thinBackend(Conf, Task, AddStream, **MOrErr, CombinedIndex,
ImportList, DefinedGlobals, &ModuleMap,
- Conf.CodeGenOnly);
+ Conf.CodeGenOnly, BitcodeLibFuncs);
};
if (ShouldEmitIndexFiles) {
if (auto E = emitFiles(ImportList, ModuleID, ModuleID.str()))
@@ -1616,13 +1637,14 @@ class FirstRoundThinBackend : public InProcessThinBackend {
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
ThreadPoolStrategy ThinLTOParallelism,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn CGAddStream, FileCache CGCache, AddStreamFn IRAddStream,
+ AddStreamFn CGAddStream, FileCache CGCache,
+ const SmallVector<StringRef> &BitcodeLibFuncs, AddStreamFn IRAddStream,
FileCache IRCache)
: InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
ModuleToDefinedGVSummaries, std::move(CGAddStream),
std::move(CGCache), /*OnWrite=*/nullptr,
/*ShouldEmitIndexFiles=*/false,
- /*ShouldEmitImportsFiles=*/false),
+ /*ShouldEmitImportsFiles=*/false, BitcodeLibFuncs),
IRAddStream(std::move(IRAddStream)), IRCache(std::move(IRCache)) {}
Error runThinLTOBackendThread(
@@ -1645,7 +1667,7 @@ class FirstRoundThinBackend : public InProcessThinBackend {
return thinBackend(Conf, Task, CGAddStream, **MOrErr, CombinedIndex,
ImportList, DefinedGlobals, &ModuleMap,
- Conf.CodeGenOnly, IRAddStream);
+ Conf.CodeGenOnly, BitcodeLibFuncs, IRAddStream);
};
// Like InProcessThinBackend, we produce index files as needed for
// FirstRoundThinBackend. However, these files are not generated for
@@ -1712,6 +1734,7 @@ class SecondRoundThinBackend : public InProcessThinBackend {
ThreadPoolStrategy ThinLTOParallelism,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs,
std::unique_ptr<SmallVector<StringRef>> IRFiles,
stable_hash CombinedCGDataHash)
: InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
@@ -1719,7 +1742,7 @@ class SecondRoundThinBackend : public InProcessThinBackend {
std::move(Cache),
/*OnWrite=*/nullptr,
/*ShouldEmitIndexFiles=*/false,
- /*ShouldEmitImportsFiles=*/false),
+ /*ShouldEmitImportsFiles=*/false, BitcodeLibFuncs),
IRFiles(std::move(IRFiles)), CombinedCGDataHash(CombinedCGDataHash) {}
Error runThinLTOBackendThread(
@@ -1740,7 +1763,7 @@ class SecondRoundThinBackend : public InProcessThinBackend {
return thinBackend(Conf, Task, AddStream, *LoadedModule, CombinedIndex,
ImportList, DefinedGlobals, &ModuleMap,
- /*CodeGenOnly=*/true);
+ /*CodeGenOnly=*/true, BitcodeLibFuncs);
};
if (!Cache.isValid() || !CombinedIndex.modulePaths().count(ModuleID) ||
all_of(CombinedIndex.getModuleHash(ModuleID),
@@ -1779,11 +1802,12 @@ ThinBackend lto::createInProcessThinBackend(ThreadPoolStrategy Parallelism,
auto Func =
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, FileCache Cache) {
+ AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
return std::make_unique<InProcessThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
- ShouldEmitImportsFiles);
+ ShouldEmitImportsFiles, BitcodeLibFuncs);
};
return ThinBackend(Func, Parallelism);
}
@@ -1900,7 +1924,8 @@ ThinBackend lto::createWriteIndexesThinBackend(
auto Func =
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, FileCache Cache) {
+ AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
return std::make_unique<WriteIndexesThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
@@ -2118,7 +2143,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
if (!CodeGenDataThinLTOTwoRounds) {
std::unique_ptr<ThinBackendProc> BackendProc =
ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
- AddStream, Cache);
+ AddStream, Cache, BitcodeLibFuncs);
return RunBackends(BackendProc.get());
}
@@ -2141,7 +2166,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
LLVM_DEBUG(dbgs() << "[TwoRounds] Running the first round of codegen\n");
auto FirstRoundLTO = std::make_unique<FirstRoundThinBackend>(
Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
- CG.AddStream, CG.Cache, IR.AddStream, IR.Cache);
+ CG.AddStream, CG.Cache, BitcodeLibFuncs, IR.AddStream, IR.Cache);
if (Error E = RunBackends(FirstRoundLTO.get()))
return E;
@@ -2157,7 +2182,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
LLVM_DEBUG(dbgs() << "[TwoRounds] Running the second round of codegen\n");
auto SecondRoundLTO = std::make_unique<SecondRoundThinBackend>(
Conf, ThinLTO.CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
- AddStream, Cache, IR.getResult(), CombinedHash);
+ AddStream, Cache, BitcodeLibFuncs, IR.getResult(), CombinedHash);
return RunBackends(SecondRoundLTO.get());
}
@@ -2664,7 +2689,8 @@ ThinBackend lto::createOutOfProcessThinBackend(
auto Func =
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
- AddStreamFn AddStream, FileCache Cache) {
+ AddStreamFn AddStream, FileCache Cache,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
return std::make_unique<OutOfProcessThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index e998ac961e24a..b7ff4bddaf9e2 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -240,7 +240,8 @@ createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) {
static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
unsigned OptLevel, bool IsThinLTO,
ModuleSummaryIndex *ExportSummary,
- const ModuleSummaryIndex *ImportSummary) {
+ const ModuleSummaryIndex *ImportSummary,
+ const DenseSet<StringRef> &BitcodeLibFuncs) {
std::optional<PGOOptions> PGOOpt;
if (!Conf.SampleProfile.empty())
PGOOpt = PGOOptions(Conf.SampleProfile, "", Conf.ProfileRemapping,
@@ -282,6 +283,28 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
new TargetLibraryInfoImpl(TM->getTargetTriple(), TM->Options.VecLib));
if (Conf.Freestanding)
TLII->disableAllFunctions();
+
+ TargetLibraryInfo TLI(*TLII);
+ for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); I != E;
+ ++I) {
+ LibFunc F = static_cast<LibFunc>(I);
+ StringRef Name = TLI.getName(F);
+ GlobalValue *Val = Mod.getNamedValue(Name);
+
+ // LibFuncs present in the current TU can always be referenced.
+ if (Val && !Val->isDeclaration())
+ continue;
+
+ // LibFuncs not implemented in bitcode can always be referenced.
+ if (!BitcodeLibFuncs.contains(Name))
+ continue;
+
+ // FIXME: Functions that are somewhere in a ThinLTO link (just not imported
+ // in this module) should not be disabled, as they have already been
+ // extracted.
+ TLII->setUnavailable(F);
+ }
+
FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
// Parse a custom AA pipeline if asked to.
@@ -365,7 +388,8 @@ static bool isEmptyModule(const Module &Mod) {
bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary,
- const std::vector<uint8_t> &CmdArgs) {
+ const std::vector<uint8_t> &CmdArgs,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
llvm::TimeTraceScope timeScope("opt");
if (EmbedBitcode == LTOBitcodeEmbedding::EmbedPostMergePreOptimized) {
// FIXME: the motivation for capturing post-merge bitcode and command line
@@ -390,9 +414,11 @@ bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
// analysis in the case of a ThinLTO build where this might be an empty
// regular LTO combined module, with a large combined index from ThinLTO.
if (!isEmptyModule(Mod)) {
+ DenseSet<StringRef> BitcodeLibFuncsSet(BitcodeLibFuncs.begin(),
+ BitcodeLibFuncs.end());
// FIXME: Plumb the combined index into the new pass manager.
runNewPMPasses(Conf, Mod, TM, Conf.OptLevel, IsThinLTO, ExportSummary,
- ImportSummary);
+ ImportSummary, BitcodeLibFuncsSet);
}
return !Conf.PostOptModuleHook || Conf.PostOptModuleHook(Task, Mod);
}
@@ -558,7 +584,8 @@ Error lto::finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile) {
Error lto::backend(const Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel, Module &Mod,
- ModuleSummaryIndex &CombinedIndex) {
+ ModuleSummaryIndex &CombinedIndex,
+ const SmallVector<StringRef> &BitcodeLibFuncs) {
llvm::TimeTraceScope timeScope("LTO backend");
Expected<const Target *> TOrErr = initAndLookupTarget(C, Mod);
if (!TOrErr)
@@ -570,7 +597,7 @@ Error lto::backend(const Config &C, AddStreamFn AddStream,
if (!C.CodeGenOnly) {
if (!opt(C, TM.get(), 0, Mod, /*IsThinLTO=*/false,
/*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr,
- /*CmdArgs*/ std::vector<uint8_t>()))
+ /*CmdArgs*/ std::vector<uint8_t>(), BitcodeLibFuncs))
return Error::success();
}
@@ -610,7 +637,9 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
const FunctionImporter::ImportMapTy &ImportList,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> *ModuleMap,
- bool CodeGenOnly, AddStreamFn IRAddStream,
+ bool CodeGenOnly,
+ const SmallVector<StringRef> &BitcodeLibFuncs,
+ AddStreamFn IRAddStream,
const std::vector<uint8_t> &CmdArgs) {
llvm::TimeTraceScope timeScope("Thin backend", Mod.getModuleIdentifier());
Expected<const Target *> TOrErr = initAndLookupTarget(Conf, Mod);
@@ -649,7 +678,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
// Perform optimization and code generation for ThinLTO.
if (!opt(Conf, TM, Task, Mod, /*IsThinLTO=*/true,
/*ExportSummary=*/nullptr, /*ImportSummary=*/&CombinedIndex,
- CmdArgs))
+ CmdArgs, BitcodeLibFuncs))
return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
// Save the current module before the first codegen round.
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
index 8aa404da15286..599c5c2eb5f84 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -614,7 +614,7 @@ bool LTOCodeGenerator::optimize() {
TargetMach = createTargetMachine();
if (!opt(Config, TargetMach.get(), 0, *MergedModule, /*IsThinLTO=*/false,
/*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr,
- /*CmdArgs*/ std::vector<uint8_t>())) {
+ /*CmdArgs*/ std::vector<uint8_t>(), {})) {
emitError("LTO middle-end optimizations failed");
return false;
}
@@ -639,7 +639,7 @@ bool LTOCodeGenerator::compileOptimized(AddStreamFn AddStream,
Config.CodeGenOnly = true;
Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
- CombinedIndex);
+ CombinedIndex, {});
assert(!Err && "unexpected code-generation failure");
(void)Err;
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 0f6d2f7c59a5c..c48d251249488 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -51,6 +51,7 @@ add_llvm_component_library(LLVMObject
BinaryFormat
MCParser
Support
+ Target
TargetParser
TextAPI
)
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index a45b34eb2e706..92ed072a80267 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Comdat.h"
@@ -75,12 +76,14 @@ struct Builder {
Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
BumpPtrAllocator &Alloc, const Triple &TT)
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
- Libcalls(TT) {}
+ TLII(TT), TLI(TLII), Libcalls(TT) {}
DenseMap<const Comdat *, int> ComdatMap;
Mangler Mang;
const Triple &TT;
+ TargetLibraryInfoImpl TLII;
+ TargetLibraryInfo TLI;
// FIXME: This shouldn't be here.
RTLIB::RuntimeLibcallsInfo Libcalls;
@@ -95,6 +98,9 @@ struct Builder {
std::vector<storage::Str> DependentLibraries;
bool isPreservedName(StringRef Name) {
+ LibFunc F;
+ if (TLI.getLibFunc(Name, F) && TLI.has(F))
+ return true;
return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
}
diff --git a/llvm/test/LTO/Resolution/X86/libcall-external-bitcode.ll b/llvm/test/LTO/Resolution/X86/libcall-external-bitcode.ll
new file mode 100644
index 0000000000000..95a599fe75e8b
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/libcall-external-bitcode.ll
@@ -0,0 +1,20 @@
+; RUN: opt %s -o %t -module-summary -mtriple x86_64-unknown-linux-musl
+; RUN: llvm-lto2 run -o %t2 \
+; RUN: -r %t,foo,plx \
+; RUN: -r %t,memcmp,x \
+; RUN: -r %t,bcmp,pl --bitcode-libfuncs=bcmp %t -save-temps
+; RUN: llvm-dis %t2.1.4.opt.bc -o - | FileCheck %s
+
+define i1 @foo(ptr %0, ptr %1, i64 %2) {
+ ; CHECK-LABEL: define{{.*}}i1 @foo
+ ; CHECK-NEXT: %cmp = {{.*}}call i32 @memcmp
+ ; CHECK-NEXT: %eq = icmp eq i32 %cmp, 0
+ ; CHECK-NEXT: ret i1 %eq
+
+ %cmp = call i32 @memcmp(ptr %0, ptr %1, i64 %2)
+ %eq = icmp eq i32 %cmp, 0
+ ret i1 %eq
+}
+
+declare i32 @memcmp(ptr, ptr, i64)
+declare i32 @bcmp(ptr, ptr, i64)
diff --git a/llvm/test/LTO/Resolution/X86/libcall-external-not-bitcode.ll b/llvm/test/LTO/Resolution/X86/libcall-external-not-bitcode.ll
new file mode 100644
index 0000000000000..2e6cc798d22cd
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/libcall-external-not-bitcode.ll
@@ -0,0 +1,20 @@
+; RUN: opt %s -o %t -module-summary -mtriple x86_64-unknown-linux-musl
+; RUN: llvm-lto2 run -o %t2 \
+; RUN: -r %t,foo,plx \
+; RUN: -r %t,memcmp,x \
+; RUN: -r %t,bcmp,pl %t -save-temps
+; RUN: llvm-dis %t2.1.4.opt.bc -o - | FileCheck %s
+
+define i1 @foo(ptr %0, ptr %1, i64 %2) {
+ ; CHECK-LABEL: define{{.*}}i1 @foo
+ ; CHECK-NEXT: %bcmp = {{.*}}call i32 @bcmp
+ ; CHECK-NEXT: %eq = icmp eq i32 %bcmp, 0
+ ; CHECK-NEXT: ret i1 %eq
+
+ %cmp = call i32 @memcmp(ptr %0, ptr %1, i64 %2)
+ %eq = icmp eq i32 %cmp, 0
+ ret i1 %eq
+}
+
+declare i32 @memcmp(ptr, ptr, i64)
+declare i32 @bcmp(ptr, ptr, i64)
diff --git a/llvm/test/LTO/Resolution/X86/libcall-in-tu.ll b/llvm/test/LTO/Resolution/X86/libcall-in-tu.ll
new file mode 100644
index 0000000000000..948f21a6536ca
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/libcall-in-tu.ll
@@ -0,0 +1,34 @@
+;; This test comes from a real world scenario in LTO, where the definition of
+;; bcmp was deleted because it has no uses, but later instcombine re-introduced
+;; a call to bcmp() as part of SimplifyLibCalls. Such deletions must not be
+;; allowed.
+
+; RUN: opt %s -o %t -module-summary -mtriple x86_64-unknown-linux-musl
+; RUN: llvm-lto2 run -o %t2 \
+; RUN: -r %t,foo,plx \
+; RUN: -r %t,memcmp,x \
+; RUN: -r %t,bcmp,pl \
+; RUN: -r %t,bcmp_impl,x %t -save-temps
+; RUN: llvm-dis %t2.1.4.opt.bc -o - | FileCheck %s
+
+define i1 @foo(ptr %0, ptr %1, i64 %2) {
+ ; CHECK-LABEL: define{{.*}}i1 @foo
+ ; CHECK-NEXT: %bcmp = {{.*}}call i32 @bcmp
+ ; CHECK-NEXT: %eq = icmp eq i32 %bcmp, 0
+ ; CHECK-NEXT: ret i1 %eq
+
+ %cmp = call i32 @memcmp(ptr %0, ptr %1, i64 %2)
+ %eq = icmp eq i32 %cmp, 0
+ ret i1 %eq
+}
+
+declare i32 @memcmp(ptr, ptr, i64)
+declare i32 @bcmp_impl(ptr, ptr, i64)
+
+;; Ensure bcmp is not removed from module because it is external.
+; CHECK: define dso_local i32 @bcmp
+define i32 @bcmp(ptr %0, ptr %1, i64 %2) noinline {
+ %r = call i32 @bcmp_impl(ptr %0, ptr %1, i64 %2)
+ ret i32 %r
+}
+
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 955c1130e9f4c..9be00a4495b36 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -234,6 +234,10 @@ static cl::opt<bool>
AllVtablesHaveTypeInfos("all-vtables-have-type-infos", cl::Hidden,
cl::desc("All vtables have type infos"));
+static cl::list<std::string>
+ BitcodeLibFuncs("bitcode-libfuncs", cl::Hidden,
+ cl::desc("set of libfuncs implemented in bitcode"));
+
static cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace"));
static cl::opt<unsigned> TimeTraceGranularity(
@@ -496,6 +500,9 @@ static int run(int argc, char **argv) {
if (HasErrors)
return 1;
+ Lto.setBitcodeLibFuncs(
+ SmallVector<StringRef>(BitcodeLibFuncs.begin(), BitcodeLibFuncs.end()));
+
auto AddStream =
[&](size_t Task,
const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
>From ab00fa7692a5da8bc9127892e674b248880f3ea3 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 11 Dec 2025 15:33:23 -0800
Subject: [PATCH 2/9] Move bitcodeLibFuncs from compile() to setter
---
lld/ELF/LTO.cpp | 10 ++++++----
lld/ELF/LTO.h | 4 ++--
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 49f6d15b346ae..f704ed2ee362b 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -316,10 +316,7 @@ static void thinLTOCreateEmptyIndexFiles(Ctx &ctx) {
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile(s).
-SmallVector<std::unique_ptr<InputFile>, 0>
-BitcodeCompiler::compile(const SmallVector<StringRef> &bitcodeLibFuncs) {
- ltoObj->setBitcodeLibFuncs(bitcodeLibFuncs);
-
+SmallVector<std::unique_ptr<InputFile>, 0> BitcodeCompiler::compile() {
unsigned maxTasks = ltoObj->getMaxTasks();
buf.resize(maxTasks);
files.resize(maxTasks);
@@ -430,3 +427,8 @@ BitcodeCompiler::compile(const SmallVector<StringRef> &bitcodeLibFuncs) {
}
return ret;
}
+
+void BitcodeCompiler::setBitcodeLibFuncs(
+ const SmallVector<StringRef> &bitcodeLibFuncs) {
+ ltoObj->setBitcodeLibFuncs(bitcodeLibFuncs);
+}
diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h
index 8207e91460785..b9547202901fd 100644
--- a/lld/ELF/LTO.h
+++ b/lld/ELF/LTO.h
@@ -42,8 +42,8 @@ class BitcodeCompiler {
~BitcodeCompiler();
void add(BitcodeFile &f);
- SmallVector<std::unique_ptr<InputFile>, 0>
- compile(const SmallVector<StringRef> &bitcodeLibFuncs);
+ SmallVector<std::unique_ptr<InputFile>, 0> compile();
+ void setBitcodeLibFuncs(const SmallVector<StringRef> &bitcodeLibFuncs);
private:
Ctx &ctx;
>From 4b5f55c4a24c74cb6c967f6ee741ad002b203fa0 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 11 Dec 2025 15:35:22 -0800
Subject: [PATCH 3/9] Densify bitcode file finding
---
lld/ELF/Driver.cpp | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index b0834e6c26b7a..3a0028c92d060 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2712,19 +2712,18 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
llvm::BumpPtrAllocator alloc;
llvm::StringSaver saver(alloc);
- SmallVector<StringRef> bitcodeLibFuncs;
if (!ctx.bitcodeFiles.empty()) {
markBuffersAsDontNeed(ctx, skipLinkedOutput);
- for (StringRef libFunc : lto::LTO::getLibFuncSymbols(*tt, saver)) {
- Symbol *sym = ctx.symtab->find(libFunc);
- if (!sym)
- continue;
- if (isa<BitcodeFile>(sym->file))
+
+ SmallVector<StringRef> bitcodeLibFuncs;
+ for (StringRef libFunc : lto::LTO::getLibFuncSymbols(*tt, saver))
+ if (Symbol *sym = ctx.symtab->find(libFunc);
+ sym && isa<BitcodeFile>(sym->file))
bitcodeLibFuncs.push_back(libFunc);
- }
+ lto->setBitcodeLibFuncs(bitcodeLibFuncs);
}
- ltoObjectFiles = lto->compile(bitcodeLibFuncs);
+ ltoObjectFiles = lto->compile();
for (auto &file : ltoObjectFiles) {
auto *obj = cast<ObjFile<ELFT>>(file.get());
obj->parse(/*ignoreComdats=*/true);
>From 9a8faead110f7c662761c70b910f3925d452530f Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 11 Dec 2025 15:39:54 -0800
Subject: [PATCH 4/9] Add comment about triple assumption
---
lld/ELF/Driver.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 3a0028c92d060..b7a6aa89efb96 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2702,6 +2702,8 @@ template <class ELFT>
void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
llvm::TimeTraceScope timeScope("LTO");
// Capture the triple before moving the bitcode into the bitcode compiler.
+ // Note that this assumes that the set of possible libfuncs is roughly
+ // equivalent for all bitcode translation units.
std::optional<llvm::Triple> tt;
if (!ctx.bitcodeFiles.empty())
tt = llvm::Triple(ctx.bitcodeFiles.front()->obj->getTargetTriple());
>From 5758497738692098fd9f153cd8c701ac1009538b Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 13 Jan 2026 16:26:00 -0800
Subject: [PATCH 5/9] Remove optional from triple in LLD Driver.cpp
---
lld/ELF/Driver.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index b7a6aa89efb96..5c83b5295939f 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2704,7 +2704,7 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
// Capture the triple before moving the bitcode into the bitcode compiler.
// Note that this assumes that the set of possible libfuncs is roughly
// equivalent for all bitcode translation units.
- std::optional<llvm::Triple> tt;
+ llvm::Triple tt;
if (!ctx.bitcodeFiles.empty())
tt = llvm::Triple(ctx.bitcodeFiles.front()->obj->getTargetTriple());
// Compile bitcode files and replace bitcode symbols.
@@ -2718,7 +2718,7 @@ void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
markBuffersAsDontNeed(ctx, skipLinkedOutput);
SmallVector<StringRef> bitcodeLibFuncs;
- for (StringRef libFunc : lto::LTO::getLibFuncSymbols(*tt, saver))
+ for (StringRef libFunc : lto::LTO::getLibFuncSymbols(tt, saver))
if (Symbol *sym = ctx.symtab->find(libFunc);
sym && isa<BitcodeFile>(sym->file))
bitcodeLibFuncs.push_back(libFunc);
>From eca8a7e1958c8c2bf3d4763aa27e33cb9b21dfa9 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 13 Jan 2026 16:33:46 -0800
Subject: [PATCH 6/9] Replace SmallVector& with ArrayRef
---
lld/ELF/LTO.cpp | 3 +--
lld/ELF/LTO.h | 2 +-
llvm/include/llvm/LTO/LTO.h | 7 +++----
llvm/include/llvm/LTO/LTOBackend.h | 21 ++++++++++-----------
llvm/lib/LTO/LTO.cpp | 19 ++++++++++---------
llvm/lib/LTO/LTOBackend.cpp | 7 +++----
6 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index f704ed2ee362b..e795ca572f12a 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -428,7 +428,6 @@ SmallVector<std::unique_ptr<InputFile>, 0> BitcodeCompiler::compile() {
return ret;
}
-void BitcodeCompiler::setBitcodeLibFuncs(
- const SmallVector<StringRef> &bitcodeLibFuncs) {
+void BitcodeCompiler::setBitcodeLibFuncs(ArrayRef<StringRef> bitcodeLibFuncs) {
ltoObj->setBitcodeLibFuncs(bitcodeLibFuncs);
}
diff --git a/lld/ELF/LTO.h b/lld/ELF/LTO.h
index b9547202901fd..c8cb2156d90ca 100644
--- a/lld/ELF/LTO.h
+++ b/lld/ELF/LTO.h
@@ -43,7 +43,7 @@ class BitcodeCompiler {
void add(BitcodeFile &f);
SmallVector<std::unique_ptr<InputFile>, 0> compile();
- void setBitcodeLibFuncs(const SmallVector<StringRef> &bitcodeLibFuncs);
+ void setBitcodeLibFuncs(ArrayRef<StringRef> bitcodeLibFuncs);
private:
Ctx &ctx;
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 66a3a80d7d61e..45cd90ed4734c 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -288,7 +288,7 @@ using ThinBackendFunction = std::function<std::unique_ptr<ThinBackendProc>(
const Config &C, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs)>;
+ ArrayRef<StringRef> BitcodeLibFuncs)>;
/// This type defines the behavior following the thin-link phase during ThinLTO.
/// It encapsulates a backend function and a strategy for thread pool
@@ -304,7 +304,7 @@ struct ThinBackend {
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
assert(isValid() && "Invalid backend function");
return Func(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
std::move(AddStream), std::move(Cache), BitcodeLibFuncs);
@@ -428,8 +428,7 @@ class LTO {
/// Set the list of functions implemented in bitcode across the link, whether
/// extracted or not. Such functions may not be referenced if they were not
/// extracted by the time LTO occurs.
- LLVM_ABI void
- setBitcodeLibFuncs(const SmallVector<StringRef> &BitcodeLibFuncs);
+ LLVM_ABI void setBitcodeLibFuncs(ArrayRef<StringRef> BitcodeLibFuncs);
/// Returns an upper bound on the number of tasks that the client may expect.
/// This may only be called after all IR object files have been added. For a
diff --git a/llvm/include/llvm/LTO/LTOBackend.h b/llvm/include/llvm/LTO/LTOBackend.h
index 6a7d7e0d87ac9..4bb38529ec754 100644
--- a/llvm/include/llvm/LTO/LTOBackend.h
+++ b/llvm/include/llvm/LTO/LTOBackend.h
@@ -40,14 +40,14 @@ LLVM_ABI bool opt(const Config &Conf, TargetMachine *TM, unsigned Task,
ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary,
const std::vector<uint8_t> &CmdArgs,
- const SmallVector<StringRef> &BitcodeLibFuncs);
+ ArrayRef<StringRef> BitcodeLibFuncs);
/// Runs a regular LTO backend. The regular LTO backend can also act as the
/// regular LTO phase of ThinLTO, which may need to access the combined index.
LLVM_ABI Error backend(const Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel, Module &M,
ModuleSummaryIndex &CombinedIndex,
- const SmallVector<StringRef> &BitcodeLibFuncs);
+ ArrayRef<StringRef> BitcodeLibFuncs);
/// Runs a ThinLTO backend.
/// If \p ModuleMap is not nullptr, all the module files to be imported have
@@ -58,15 +58,14 @@ LLVM_ABI Error backend(const Config &C, AddStreamFn AddStream,
/// the backend will skip optimization and only perform code generation. If
/// \p IRAddStream is not nullptr, it will be called just before code generation
/// to serialize the optimized IR.
-LLVM_ABI Error
-thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
- const ModuleSummaryIndex &CombinedIndex,
- const FunctionImporter::ImportMapTy &ImportList,
- const GVSummaryMapTy &DefinedGlobals,
- MapVector<StringRef, BitcodeModule> *ModuleMap, bool CodeGenOnly,
- const SmallVector<StringRef> &BitcodeLibFuncs,
- AddStreamFn IRAddStream = nullptr,
- const std::vector<uint8_t> &CmdArgs = std::vector<uint8_t>());
+LLVM_ABI Error thinBackend(
+ const Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
+ const ModuleSummaryIndex &CombinedIndex,
+ const FunctionImporter::ImportMapTy &ImportList,
+ const GVSummaryMapTy &DefinedGlobals,
+ MapVector<StringRef, BitcodeModule> *ModuleMap, bool CodeGenOnly,
+ ArrayRef<StringRef> BitcodeLibFuncs, AddStreamFn IRAddStream = nullptr,
+ const std::vector<uint8_t> &CmdArgs = std::vector<uint8_t>());
LLVM_ABI Error finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile);
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index ee8db650cf20e..d8186c27536dc 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -771,8 +771,9 @@ Error LTO::add(std::unique_ptr<InputFile> InputPtr,
return Error::success();
}
-void LTO::setBitcodeLibFuncs(const SmallVector<StringRef> &BitcodeLibFuncs) {
- this->BitcodeLibFuncs = BitcodeLibFuncs;
+void LTO::setBitcodeLibFuncs(ArrayRef<StringRef> BitcodeLibFuncs) {
+ this->BitcodeLibFuncs.clear();
+ this->BitcodeLibFuncs.append(BitcodeLibFuncs.begin(), BitcodeLibFuncs.end());
}
Expected<ArrayRef<SymbolResolution>>
@@ -1518,7 +1519,7 @@ class CGThinBackend : public ThinBackendProc {
class InProcessThinBackend : public CGThinBackend {
protected:
FileCache Cache;
- const SmallVector<StringRef> &BitcodeLibFuncs;
+ ArrayRef<StringRef> BitcodeLibFuncs;
public:
InProcessThinBackend(
@@ -1527,7 +1528,7 @@ class InProcessThinBackend : public CGThinBackend {
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache, lto::IndexWriteCallback OnWrite,
bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles,
- const SmallVector<StringRef> &BitcodeLibFuncs)
+ ArrayRef<StringRef> BitcodeLibFuncs)
: CGThinBackend(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
AddStream, OnWrite, ShouldEmitIndexFiles,
ShouldEmitImportsFiles, ThinLTOParallelism),
@@ -1638,7 +1639,7 @@ class FirstRoundThinBackend : public InProcessThinBackend {
ThreadPoolStrategy ThinLTOParallelism,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn CGAddStream, FileCache CGCache,
- const SmallVector<StringRef> &BitcodeLibFuncs, AddStreamFn IRAddStream,
+ ArrayRef<StringRef> BitcodeLibFuncs, AddStreamFn IRAddStream,
FileCache IRCache)
: InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
ModuleToDefinedGVSummaries, std::move(CGAddStream),
@@ -1734,7 +1735,7 @@ class SecondRoundThinBackend : public InProcessThinBackend {
ThreadPoolStrategy ThinLTOParallelism,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs,
+ ArrayRef<StringRef> BitcodeLibFuncs,
std::unique_ptr<SmallVector<StringRef>> IRFiles,
stable_hash CombinedCGDataHash)
: InProcessThinBackend(Conf, CombinedIndex, ThinLTOParallelism,
@@ -1803,7 +1804,7 @@ ThinBackend lto::createInProcessThinBackend(ThreadPoolStrategy Parallelism,
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
return std::make_unique<InProcessThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
@@ -1925,7 +1926,7 @@ ThinBackend lto::createWriteIndexesThinBackend(
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
return std::make_unique<WriteIndexesThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
@@ -2690,7 +2691,7 @@ ThinBackend lto::createOutOfProcessThinBackend(
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
AddStreamFn AddStream, FileCache Cache,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
return std::make_unique<OutOfProcessThinBackend>(
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index b7ff4bddaf9e2..fc004ec409d94 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -389,7 +389,7 @@ bool lto::opt(const Config &Conf, TargetMachine *TM, unsigned Task, Module &Mod,
bool IsThinLTO, ModuleSummaryIndex *ExportSummary,
const ModuleSummaryIndex *ImportSummary,
const std::vector<uint8_t> &CmdArgs,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
llvm::TimeTraceScope timeScope("opt");
if (EmbedBitcode == LTOBitcodeEmbedding::EmbedPostMergePreOptimized) {
// FIXME: the motivation for capturing post-merge bitcode and command line
@@ -585,7 +585,7 @@ Error lto::finalizeOptimizationRemarks(LLVMRemarkFileHandle DiagOutputFile) {
Error lto::backend(const Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel, Module &Mod,
ModuleSummaryIndex &CombinedIndex,
- const SmallVector<StringRef> &BitcodeLibFuncs) {
+ ArrayRef<StringRef> BitcodeLibFuncs) {
llvm::TimeTraceScope timeScope("LTO backend");
Expected<const Target *> TOrErr = initAndLookupTarget(C, Mod);
if (!TOrErr)
@@ -637,8 +637,7 @@ Error lto::thinBackend(const Config &Conf, unsigned Task, AddStreamFn AddStream,
const FunctionImporter::ImportMapTy &ImportList,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> *ModuleMap,
- bool CodeGenOnly,
- const SmallVector<StringRef> &BitcodeLibFuncs,
+ bool CodeGenOnly, ArrayRef<StringRef> BitcodeLibFuncs,
AddStreamFn IRAddStream,
const std::vector<uint8_t> &CmdArgs) {
llvm::TimeTraceScope timeScope("Thin backend", Mod.getModuleIdentifier());
>From 4e7384d45aa944ab478dae7096601277f07cd7b7 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 15 Jan 2026 11:07:13 -0800
Subject: [PATCH 7/9] Add FIXMEs for TLI usage and Target dep
---
llvm/lib/Object/CMakeLists.txt | 2 ++
llvm/lib/Object/IRSymtab.cpp | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index c48d251249488..8b08f18b935cf 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -51,6 +51,8 @@ add_llvm_component_library(LLVMObject
BinaryFormat
MCParser
Support
+ # FIXME: Target dep should be removed once TLI and RuntimeLibcalls are fused
+ # and moved out of Target.
Target
TargetParser
TextAPI
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index 92ed072a80267..43c2292baeb3f 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -82,9 +82,9 @@ struct Builder {
Mangler Mang;
const Triple &TT;
+ // FIXME: These shouldn't be here.
TargetLibraryInfoImpl TLII;
TargetLibraryInfo TLI;
- // FIXME: This shouldn't be here.
RTLIB::RuntimeLibcallsInfo Libcalls;
std::vector<storage::Comdat> Comdats;
>From a7db97f97c514e2894e6e61e137bd69ac6c1b926 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 15 Jan 2026 11:17:28 -0800
Subject: [PATCH 8/9] More idiomatic LibFunc iteration
---
llvm/lib/LTO/LTO.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index d8186c27536dc..085d0d4a587f4 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1433,8 +1433,7 @@ SmallVector<StringRef> LTO::getLibFuncSymbols(const Triple &TT,
TargetLibraryInfo TLI(*TLII);
SmallVector<StringRef> LibFuncSymbols;
LibFuncSymbols.reserve(LibFunc::NumLibFuncs);
- for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs); I != E;
- ++I) {
+ for (unsigned I = LibFunc::Begin_LibFunc; I != LibFunc::End_LibFunc; ++I) {
LibFunc F = static_cast<LibFunc>(I);
if (TLI.has(F))
LibFuncSymbols.push_back(Saver.save(TLI.getName(F)).data());
>From 5df49059dc2c1f777f64e5148a60f972ad3ad80e Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Thu, 15 Jan 2026 14:10:25 -0800
Subject: [PATCH 9/9] Move isPreservedName out of IRSymtab into LTO's Symbol
---
llvm/include/llvm/LTO/LTO.h | 6 +++++-
llvm/lib/LTO/LTO.cpp | 22 +++++++++++++++++++---
llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 10 +++++++---
llvm/lib/Object/CMakeLists.txt | 3 ---
llvm/lib/Object/IRSymtab.cpp | 18 ++----------------
5 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 45cd90ed4734c..3fab39b1eb90d 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -16,6 +16,7 @@
#define LLVM_LTO_LTO_H
#include "llvm/IR/LLVMRemarkStreamer.h"
+#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/Support/Compiler.h"
#include <memory>
@@ -167,6 +168,9 @@ class InputFile {
using irsymtab::Symbol::getSectionName;
using irsymtab::Symbol::isExecutable;
using irsymtab::Symbol::isUsed;
+
+ bool isPreserved(const TargetLibraryInfo &TLI,
+ const RTLIB::RuntimeLibcallsInfo &Libcalls) const;
};
/// A range over the symbols in this InputFile.
@@ -589,7 +593,7 @@ class LTO {
void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res, unsigned Partition,
- bool InSummary);
+ bool InSummary, const Triple &TT);
// These functions take a range of symbol resolutions and consume the
// resolutions used by a single input module. Functions return ranges refering
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 085d0d4a587f4..2c314a40899ea 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -597,6 +597,15 @@ Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
return std::move(File);
}
+bool InputFile::Symbol::isPreserved(
+ const TargetLibraryInfo &TLI,
+ const RTLIB::RuntimeLibcallsInfo &Libcalls) const {
+ LibFunc F;
+ if (TLI.getLibFunc(IRName, F) && TLI.has(F))
+ return true;
+ return Libcalls.getSupportedLibcallImpl(IRName) != RTLIB::Unsupported;
+}
+
StringRef InputFile::getName() const {
return Mods[0].getModuleIdentifier();
}
@@ -640,11 +649,15 @@ LTO::~LTO() = default;
// their partitions.
void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
ArrayRef<SymbolResolution> Res,
- unsigned Partition, bool InSummary) {
+ unsigned Partition, bool InSummary,
+ const Triple &TT) {
llvm::TimeTraceScope timeScope("LTO add module to global resolution");
auto *ResI = Res.begin();
auto *ResE = Res.end();
(void)ResE;
+ RTLIB::RuntimeLibcallsInfo Libcalls(TT);
+ TargetLibraryInfoImpl TLII(TT);
+ TargetLibraryInfo TLI(TLII);
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
@@ -687,11 +700,14 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
GlobalRes.VisibleOutsideSummary = true;
}
+ bool IsPreserved = Sym.isPreserved(TLI, Libcalls);
+
// Set the partition to external if we know it is re-defined by the linker
// with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
// regular object, is referenced from llvm.compiler.used/llvm.used, or was
// already recorded as being referenced from a different partition.
if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
+ IsPreserved ||
(GlobalRes.Partition != GlobalResolution::Unknown &&
GlobalRes.Partition != Partition)) {
GlobalRes.Partition = GlobalResolution::External;
@@ -702,7 +718,7 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
// Flag as visible outside of summary if visible from a regular object or
// from a module that does not have a summary.
GlobalRes.VisibleOutsideSummary |=
- (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary);
+ (Res.VisibleToRegularObj || Sym.isUsed() || IsPreserved || !InSummary);
GlobalRes.ExportDynamic |= Res.ExportDynamic;
}
@@ -814,7 +830,7 @@ LTO::addModule(InputFile &Input, ArrayRef<SymbolResolution> InputRes,
auto ModSyms = Input.module_symbols(ModI);
addModuleToGlobalRes(ModSyms, Res,
IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
- LTOInfo->HasSummary);
+ LTOInfo->HasSummary, Triple(Input.getTargetTriple()));
if (IsThinLTO)
return addThinLTO(BM, ModSyms, Res);
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 961dd0ee43370..05eb2cf01830e 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -58,6 +58,7 @@
#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
+#include "llvm/WindowsDriver/MSVCPaths.h"
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
@@ -290,11 +291,14 @@ static void optimizeModule(Module &TheModule, TargetMachine &TM,
static void
addUsedSymbolToPreservedGUID(const lto::InputFile &File,
DenseSet<GlobalValue::GUID> &PreservedGUID) {
- for (const auto &Sym : File.symbols()) {
- if (Sym.isUsed())
+ Triple TT(File.getTargetTriple());
+ RTLIB::RuntimeLibcallsInfo Libcalls(TT);
+ TargetLibraryInfoImpl TLII(TT);
+ TargetLibraryInfo TLI(TLII);
+ for (const auto &Sym : File.symbols())
+ if (Sym.isUsed() || Sym.isPreserved(TLI, Libcalls))
PreservedGUID.insert(
GlobalValue::getGUIDAssumingExternalLinkage(Sym.getIRName()));
- }
}
// Convert the PreservedSymbols map from "Name" based to "GUID" based.
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index 8b08f18b935cf..0f6d2f7c59a5c 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -51,9 +51,6 @@ add_llvm_component_library(LLVMObject
BinaryFormat
MCParser
Support
- # FIXME: Target dep should be removed once TLI and RuntimeLibcalls are fused
- # and moved out of Target.
- Target
TargetParser
TextAPI
)
diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index 43c2292baeb3f..be8e88738eab9 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -23,7 +23,6 @@
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
-#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ModuleSymbolTable.h"
#include "llvm/Object/SymbolicFile.h"
@@ -75,18 +74,12 @@ struct Builder {
// so this provides somewhere to store any strings that we create.
Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
BumpPtrAllocator &Alloc, const Triple &TT)
- : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
- TLII(TT), TLI(TLII), Libcalls(TT) {}
+ : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT) {}
DenseMap<const Comdat *, int> ComdatMap;
Mangler Mang;
const Triple &TT;
- // FIXME: These shouldn't be here.
- TargetLibraryInfoImpl TLII;
- TargetLibraryInfo TLI;
- RTLIB::RuntimeLibcallsInfo Libcalls;
-
std::vector<storage::Comdat> Comdats;
std::vector<storage::Module> Mods;
std::vector<storage::Symbol> Syms;
@@ -97,13 +90,6 @@ struct Builder {
std::vector<storage::Str> DependentLibraries;
- bool isPreservedName(StringRef Name) {
- LibFunc F;
- if (TLI.getLibFunc(Name, F) && TLI.has(F))
- return true;
- return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
- }
-
void setStr(storage::Str &S, StringRef Value) {
S.Offset = StrtabBuilder.add(Value);
S.Size = Value.size();
@@ -275,7 +261,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
StringRef GVName = GV->getName();
setStr(Sym.IRName, GVName);
- if (Used.count(GV) || isPreservedName(GVName))
+ if (Used.count(GV))
Sym.Flags |= 1 << storage::Symbol::FB_used;
if (GV->isThreadLocal())
Sym.Flags |= 1 << storage::Symbol::FB_tls;
More information about the cfe-commits
mailing list