#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/ParallelCG.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Linker/IRMover.h"
#include "llvm/Support/StringSaver.h"
using namespace lld::elf;
// This is for use when debugging LTO.
-static void saveLtoObjectFile(StringRef Buffer) {
+static void saveLtoObjectFile(StringRef Buffer, unsigned I, bool Many) {
+ SmallString<128> Filename = Config->OutputFile;
+ if (Many)
+ Filename += utostr(I);
+ Filename += ".lto.o";
std::error_code EC;
- raw_fd_ostream OS(Config->OutputFile.str() + ".lto.o", EC,
- sys::fs::OpenFlags::F_None);
+ raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
check(EC);
OS << Buffer;
}
GV.setLinkage(GlobalValue::InternalLinkage);
}
+std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::runSplitCodegen() {
+ unsigned NumThreads = Config->LtoJobs;
+ OwningData.resize(NumThreads);
+
+ std::list<raw_svector_ostream> OSs;
+ std::vector<raw_pwrite_stream *> OSPtrs;
+ for (SmallString<0> &Obj : OwningData) {
+ OSs.emplace_back(Obj);
+ OSPtrs.push_back(&OSs.back());
+ }
+
+ splitCodeGen(std::move(Combined), OSPtrs, {},
+ [this]() { return getTargetMachine(); });
+
+ std::vector<std::unique_ptr<InputFile>> ObjFiles;
+ for (SmallString<0> &Obj : OwningData)
+ ObjFiles.push_back(createObjectFile(
+ MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object")));
+
+ if (Config->SaveTemps)
+ for (unsigned I = 0; I < NumThreads; ++I)
+ saveLtoObjectFile(OwningData[I], I, NumThreads > 1);
+
+ return ObjFiles;
+}
+
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile.
-std::unique_ptr<InputFile> BitcodeCompiler::compile() {
+std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::compile() {
+ TheTriple = Combined->getTargetTriple();
for (const auto &Name : InternalizedSyms) {
GlobalValue *GV = Combined->getNamedValue(Name.first());
assert(GV);
std::unique_ptr<TargetMachine> TM(getTargetMachine());
runLTOPasses(*Combined, *TM);
- raw_svector_ostream OS(OwningData);
- legacy::PassManager CodeGenPasses;
- if (TM->addPassesToEmitFile(CodeGenPasses, OS,
- TargetMachine::CGFT_ObjectFile))
- fatal("failed to setup codegen");
- CodeGenPasses.run(*Combined);
- MB = MemoryBuffer::getMemBuffer(OwningData,
- "LLD-INTERNAL-combined-lto-object", false);
- if (Config->SaveTemps)
- saveLtoObjectFile(MB->getBuffer());
- return createObjectFile(*MB);
+ return runSplitCodegen();
}
-TargetMachine *BitcodeCompiler::getTargetMachine() {
- StringRef TripleStr = Combined->getTargetTriple();
+std::unique_ptr<TargetMachine> BitcodeCompiler::getTargetMachine() {
std::string Msg;
- const Target *T = TargetRegistry::lookupTarget(TripleStr, Msg);
+ const Target *T = TargetRegistry::lookupTarget(TheTriple, Msg);
if (!T)
fatal("target not found: " + Msg);
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
Reloc::Model R = Config->Pic ? Reloc::PIC_ : Reloc::Static;
- return T->createTargetMachine(TripleStr, "", "", Options, R);
+ return std::unique_ptr<TargetMachine>(
+ T->createTargetMachine(TheTriple, "", "", Options, R));
}
class BitcodeCompiler {
public:
void add(BitcodeFile &F);
- std::unique_ptr<InputFile> compile();
+ std::vector<std::unique_ptr<InputFile>> compile();
BitcodeCompiler()
: Combined(new llvm::Module("ld-temp.o", Context)), Mover(*Combined) {}
private:
- llvm::TargetMachine *getTargetMachine();
+ std::vector<std::unique_ptr<InputFile>> runSplitCodegen();
+ std::unique_ptr<llvm::TargetMachine> getTargetMachine();
llvm::LLVMContext Context;
std::unique_ptr<llvm::Module> Combined;
llvm::IRMover Mover;
- SmallString<0> OwningData;
+ std::vector<SmallString<0>> OwningData;
std::unique_ptr<MemoryBuffer> MB;
llvm::StringSet<> InternalizedSyms;
+ std::string TheTriple;
};
}
}
Lto.reset(new BitcodeCompiler);
for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
Lto->add(*F);
- std::unique_ptr<InputFile> IF = Lto->compile();
- ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
+ std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();
// Replace bitcode symbols.
- llvm::DenseSet<StringRef> DummyGroups;
- Obj->parse(DummyGroups);
- for (SymbolBody *Body : Obj->getNonLocalSymbols()) {
- Symbol *Sym = insert(Body);
- Sym->Body->setUsedInRegularObj();
- if (Sym->Body->isShared())
- Sym->Body->MustBeInDynSym = true;
- if (Sym->Body->MustBeInDynSym)
- Body->MustBeInDynSym = true;
- if (!Sym->Body->isUndefined() && Body->isUndefined())
- continue;
- Sym->Body = Body;
+ for (auto &IF : IFs) {
+ ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
+
+ llvm::DenseSet<StringRef> DummyGroups;
+ Obj->parse(DummyGroups);
+ for (SymbolBody *Body : Obj->getNonLocalSymbols()) {
+ Symbol *Sym = insert(Body);
+ Sym->Body->setUsedInRegularObj();
+ if (Sym->Body->isShared())
+ Sym->Body->MustBeInDynSym = true;
+ if (Sym->Body->MustBeInDynSym)
+ Body->MustBeInDynSym = true;
+ if (!Sym->Body->isUndefined() && Body->isUndefined())
+ continue;
+ Sym->Body = Body;
+ }
+ ObjectFiles.emplace_back(Obj);
}
- ObjectFiles.emplace_back(Obj);
}
// Add an undefined symbol.