Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1451,11 +1451,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';
});
Expand Down
19 changes: 17 additions & 2 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are making an assumption that the triple is homogenous (modulo libcall differences) across all the bitcode files. Ideally this would be the case, but build systems being build systems there could be some differences, I'm thinking about normalised triples where -march might differ.

Looking at getLibFuncSymbols it seems like most if not all the variation in libcall availability is in the environment and I wouldn't expect that to vary across the build system.

I don't think we need to change anything here, but could be worth stating our assumptions in a comment.

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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the test for sym == nullptr be combined with the find?

if (Symbol *sym = ctx.symtab->find(libFunc))
  if (isa<BitcodeFile>(sym->file))
        bitcodeLibFuncs.push_back(libFunc);

if (!sym)
continue;
if (isa<BitcodeFile>(sym->file))
bitcodeLibFuncs.push_back(libFunc);
}
}

ltoObjectFiles = lto->compile();
ltoObjectFiles = lto->compile(bitcodeLibFuncs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the callsite alone this could be interpreted as just compiling the bitcodeLibFuncs.

Suggestions:

  • Does the ltoObj->setBitcodeLibFuncs(bitcodeLibFuncs); need to be done in compile? Perhaps add a lto->setBitcodeLibFuncs(bitcodeLibFuncs) as it looks like ltoObj is private.
  • Rename to compileObjectsAndLibFuncs(bitcodeLibFuncs).

for (auto &file : ltoObjectFiles) {
auto *obj = cast<ObjFile<ELFT>>(file.get());
obj->parse(/*ignoreComdats=*/true);
Expand Down
5 changes: 4 additions & 1 deletion lld/ELF/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,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);
Expand Down
3 changes: 2 additions & 1 deletion lld/ELF/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
41 changes: 41 additions & 0 deletions lld/test/ELF/lto/libcall-archive-bitcode.test
Original file line number Diff line number Diff line change
@@ -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)

24 changes: 21 additions & 3 deletions llvm/include/llvm/LTO/LTO.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,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
Expand All @@ -279,10 +280,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); }
Expand Down Expand Up @@ -400,6 +402,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.
Expand All @@ -420,6 +428,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;

Expand Down Expand Up @@ -591,6 +607,8 @@ class LTO {

// Diagnostic optimization remarks file
LLVMRemarkFileHandle DiagnosticOutputFile;

SmallVector<StringRef> BitcodeLibFuncs;
};

/// The resolution for a symbol. The linker must provide a SymbolResolution for
Expand Down
7 changes: 5 additions & 2 deletions llvm/include/llvm/LTO/LTOBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>());

Expand Down
62 changes: 44 additions & 18 deletions llvm/lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,10 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
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) {
Expand Down Expand Up @@ -1385,9 +1389,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;
}

Expand All @@ -1407,6 +1411,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 {
Expand Down Expand Up @@ -1484,18 +1503,20 @@ class CGThinBackend : public ThinBackendProc {
class InProcessThinBackend : public CGThinBackend {
protected:
FileCache Cache;
const SmallVector<StringRef> &BitcodeLibFuncs;

public:
InProcessThinBackend(
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
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,
Expand All @@ -1516,7 +1537,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()))
Expand Down Expand Up @@ -1601,13 +1622,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(
Expand All @@ -1630,7 +1652,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
Expand Down Expand Up @@ -1697,14 +1719,15 @@ 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,
ModuleToDefinedGVSummaries, std::move(AddStream),
std::move(Cache),
/*OnWrite=*/nullptr,
/*ShouldEmitIndexFiles=*/false,
/*ShouldEmitImportsFiles=*/false),
/*ShouldEmitImportsFiles=*/false, BitcodeLibFuncs),
IRFiles(std::move(IRFiles)), CombinedCGDataHash(CombinedCGDataHash) {}

Error runThinLTOBackendThread(
Expand All @@ -1725,7 +1748,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),
Expand Down Expand Up @@ -1764,11 +1787,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);
}
Expand Down Expand Up @@ -1885,7 +1909,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,
Expand Down Expand Up @@ -2103,7 +2128,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());
}

Expand All @@ -2126,7 +2151,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;

Expand All @@ -2142,7 +2167,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());
}

Expand Down Expand Up @@ -2620,7 +2645,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,
Expand Down
Loading