[lld] r266484 - [LTO] Implement parallel Codegen for LTO using splitCodeGen.
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 15 16:46:44 PDT 2016
On Fri, Apr 15, 2016 at 3:51 PM, Rui Ueyama <ruiu at google.com> wrote:
> On Fri, Apr 15, 2016 at 3:38 PM, Davide Italiano via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>>
>> Author: davide
>> Date: Fri Apr 15 17:38:10 2016
>> New Revision: 266484
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=266484&view=rev
>> Log:
>> [LTO] Implement parallel Codegen for LTO using splitCodeGen.
>>
>> Parallelism level can be chosen using the new --lto-jobs=K option
>> where K is the number of threads used for CodeGen. It currently
>> defaults to 1.
>>
>> Added:
>> lld/trunk/test/ELF/lto/parallel.ll
>> Modified:
>> lld/trunk/ELF/Config.h
>> lld/trunk/ELF/Driver.cpp
>> lld/trunk/ELF/LTO.cpp
>> lld/trunk/ELF/LTO.h
>> lld/trunk/ELF/Options.td
>> lld/trunk/ELF/SymbolTable.cpp
>> lld/trunk/test/ELF/basic.s
>>
>> Modified: lld/trunk/ELF/Config.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Config.h (original)
>> +++ lld/trunk/ELF/Config.h Fri Apr 15 17:38:10 2016
>> @@ -94,6 +94,7 @@ struct Configuration {
>> ELFKind EKind = ELFNoneKind;
>> uint16_t EMachine = llvm::ELF::EM_NONE;
>> uint64_t EntryAddr = -1;
>> + unsigned LtoJobs;
>> unsigned LtoO;
>> unsigned Optimize;
>> };
>>
>> Modified: lld/trunk/ELF/Driver.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Driver.cpp (original)
>> +++ lld/trunk/ELF/Driver.cpp Fri Apr 15 17:38:10 2016
>> @@ -321,6 +321,9 @@ void LinkerDriver::readConfigs(opt::Inpu
>> Config->LtoO = getInteger(Args, OPT_lto_O, 2);
>> if (Config->LtoO > 3)
>> error("invalid optimization level for LTO: " + getString(Args,
>> OPT_lto_O));
>> + Config->LtoJobs = getInteger(Args, OPT_lto_jobs, 1);
>> + if (Config->LtoJobs == 0)
>> + error("number of threads must be > 0");
>>
>> Config->ZExecStack = hasZOption(Args, "execstack");
>> Config->ZNodelete = hasZOption(Args, "nodelete");
>>
>> Modified: lld/trunk/ELF/LTO.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/LTO.cpp (original)
>> +++ lld/trunk/ELF/LTO.cpp Fri Apr 15 17:38:10 2016
>> @@ -16,6 +16,7 @@
>> #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"
>> @@ -33,10 +34,13 @@ using namespace lld;
>> 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;
>> }
>> @@ -136,9 +140,36 @@ static void internalize(GlobalValue &GV)
>> 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;
>
>
> Is there any reason you used std::list instead of std::vector? I think
> std::vector is generally preferred unless you really want to have a linked
> list.
>
I just blatantly modeled this after the gold plugin does.
If we want to change it, we might want to change it everywhere.
>>
>> + 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);
>> @@ -151,26 +182,16 @@ std::unique_ptr<InputFile> BitcodeCompil
>> 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));
>> }
>>
>> Modified: lld/trunk/ELF/LTO.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.h?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/LTO.h (original)
>> +++ lld/trunk/ELF/LTO.h Fri Apr 15 17:38:10 2016
>> @@ -37,20 +37,22 @@ class InputFile;
>> 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;
>> };
>> }
>> }
>>
>> Modified: lld/trunk/ELF/Options.td
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Options.td (original)
>> +++ lld/trunk/ELF/Options.td Fri Apr 15 17:38:10 2016
>> @@ -237,7 +237,9 @@ def G : Separate<["-"], "G">;
>> // Aliases for ignored options
>> def alias_version_script_version_script : Joined<["--"],
>> "version-script=">, Alias<version_script>;
>>
>> -// Debugging/developer options
>> +// LTO-related options.
>> +def lto_jobs : Joined<["--"], "lto-jobs=">,
>> + HelpText<"Number of threads to run codegen">;
>> def disable_verify : Flag<["-"], "disable-verify">;
>> def mllvm : Separate<["-"], "mllvm">;
>> def save_temps : Flag<["-"], "save-temps">;
>>
>> Modified: lld/trunk/ELF/SymbolTable.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/SymbolTable.cpp (original)
>> +++ lld/trunk/ELF/SymbolTable.cpp Fri Apr 15 17:38:10 2016
>> @@ -122,24 +122,27 @@ template <class ELFT> void SymbolTable<E
>> 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.
>>
>> Modified: lld/trunk/test/ELF/basic.s
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/basic.s?rev=266484&r1=266483&r2=266484&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/test/ELF/basic.s (original)
>> +++ lld/trunk/test/ELF/basic.s Fri Apr 15 17:38:10 2016
>> @@ -214,3 +214,6 @@ _start:
>>
>> # RUN: not ld.lld %t -o %t -m wrong_emul 2>&1 | FileCheck
>> --check-prefix=UNKNOWN_EMUL %s
>> # UNKNOWN_EMUL: unknown emulation: wrong_emul
>> +
>> +# RUN: not ld.lld %t --lto-jobs=0 2>&1 | FileCheck
>> --check-prefix=NOTHREADS %s
>> +# NOTHREADS: number of threads must be > 0
>>
>> Added: lld/trunk/test/ELF/lto/parallel.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/parallel.ll?rev=266484&view=auto
>>
>> ==============================================================================
>> --- lld/trunk/test/ELF/lto/parallel.ll (added)
>> +++ lld/trunk/test/ELF/lto/parallel.ll Fri Apr 15 17:38:10 2016
>> @@ -0,0 +1,22 @@
>> +; RUN: llvm-as -o %t.bc %s
>> +; RUN: ld.lld -m elf_x86_64 --lto-jobs=2 -save-temps -o %t %t.bc -shared
>> +; RUN: llvm-nm %t0.lto.o | FileCheck --check-prefix=CHECK0 %s
>> +; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
>> +
>> +target triple = "x86_64-unknown-linux-gnu"
>> +
>> +; CHECK0-NOT: bar
>> +; CHECK0: T foo
>> +; CHECK0-NOT: bar
>> +define void @foo() {
>> + call void @bar()
>> + ret void
>> +}
>> +
>> +; CHECK1-NOT: foo
>> +; CHECK1: T bar
>> +; CHECK1-NOT: foo
>> +define void @bar() {
>> + call void @foo()
>> + ret void
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
--
Davide
"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare
More information about the llvm-commits
mailing list