diff --git a/include/llvm/CodeGen/ParallelCG.h b/include/llvm/CodeGen/ParallelCG.h index 723ea6a9fe2..5932f23e2d9 100644 --- a/include/llvm/CodeGen/ParallelCG.h +++ b/include/llvm/CodeGen/ParallelCG.h @@ -43,6 +43,19 @@ splitCodeGen(std::unique_ptr M, ArrayRef OSs, TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile, bool PreserveLocals = false); +/// Split M into OSs.size() partitions, and generate code for each. +/// It is a variant that takes a factory function for the TargetMachine +/// TMFactory. TMFactory needs to be thread safe on the client side. +/// See the other splitCodeGen() for a more detailed description. +/// +/// \returns M if OSs.size() == 1, otherwise returns std::unique_ptr(). +std::unique_ptr +splitCodeGen(std::unique_ptr M, ArrayRef OSs, + ArrayRef BCOSs, + const std::function()> &TMFactory, + TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile, + bool PreserveLocals = false); + } // namespace llvm #endif diff --git a/lib/CodeGen/ParallelCG.cpp b/lib/CodeGen/ParallelCG.cpp index 1486af14d4b..7085cb562df 100644 --- a/lib/CodeGen/ParallelCG.cpp +++ b/lib/CodeGen/ParallelCG.cpp @@ -25,39 +25,47 @@ using namespace llvm; -static void codegen(Module *M, llvm::raw_pwrite_stream &OS, - const Target *TheTarget, StringRef CPU, StringRef Features, - const TargetOptions &Options, Reloc::Model RM, - CodeModel::Model CM, CodeGenOpt::Level OL, - TargetMachine::CodeGenFileType FileType) { - std::unique_ptr TM(TheTarget->createTargetMachine( - M->getTargetTriple(), CPU, Features, Options, RM, CM, OL)); - +static void +codegen(Module *M, llvm::raw_pwrite_stream &OS, + const std::function()> &TMFactory, + TargetMachine::CodeGenFileType FileType) { + std::unique_ptr TM = TMFactory(); legacy::PassManager CodeGenPasses; if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType)) report_fatal_error("Failed to setup codegen"); CodeGenPasses.run(*M); } -std::unique_ptr llvm::splitCodeGen( - std::unique_ptr M, ArrayRef OSs, - ArrayRef BCOSs, StringRef CPU, - StringRef Features, const TargetOptions &Options, Reloc::Model RM, - CodeModel::Model CM, CodeGenOpt::Level OL, - TargetMachine::CodeGenFileType FileType, bool PreserveLocals) { +std::unique_ptr +llvm::splitCodeGen(std::unique_ptr M, ArrayRef OSs, + ArrayRef BCOSs, StringRef CPU, + StringRef Features, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, + TargetMachine::CodeGenFileType FileType, + bool PreserveLocals) { StringRef TripleStr = M->getTargetTriple(); std::string ErrMsg; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg); if (!TheTarget) report_fatal_error(Twine("Target not found: ") + ErrMsg); + return splitCodeGen(std::move(M), OSs, BCOSs, [&]() { + return std::unique_ptr(TheTarget->createTargetMachine( + TripleStr, CPU, Features, Options, RM, CM, OL)); + }, FileType, PreserveLocals); +} +std::unique_ptr llvm::splitCodeGen( + std::unique_ptr M, ArrayRef OSs, + ArrayRef BCOSs, + const std::function()> &TMFactory, + TargetMachine::CodeGenFileType FileType, bool PreserveLocals) { assert(BCOSs.empty() || BCOSs.size() == OSs.size()); if (OSs.size() == 1) { if (!BCOSs.empty()) WriteBitcodeToFile(M.get(), *BCOSs[0]); - codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, OL, - FileType); + codegen(M.get(), *OSs[0], TMFactory, FileType); return M; } @@ -88,8 +96,7 @@ std::unique_ptr llvm::splitCodeGen( llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++]; // Enqueue the task CodegenThreadPool.async( - [TheTarget, CPU, Features, Options, RM, CM, OL, FileType, - ThreadOS](const SmallVector &BC) { + [&TMFactory, FileType, ThreadOS](const SmallVector &BC) { LLVMContext Ctx; ErrorOr> MOrErr = parseBitcodeFile( MemoryBufferRef(StringRef(BC.data(), BC.size()), @@ -99,8 +106,7 @@ std::unique_ptr llvm::splitCodeGen( report_fatal_error("Failed to read bitcode"); std::unique_ptr MPartInCtx = std::move(MOrErr.get()); - codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features, - Options, RM, CM, OL, FileType); + codegen(MPartInCtx.get(), *ThreadOS, TMFactory, FileType); }, // Pass BC using std::move to ensure that it get moved rather than // copied into the thread's context.