[lld] r266484 - [LTO] Implement parallel Codegen for LTO using splitCodeGen.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 15 15:51:49 PDT 2016


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.


> +  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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160415/28e07cd9/attachment.html>


More information about the llvm-commits mailing list