Mercurial > hg > CbC > CbC_llvm
diff lib/CodeGen/ParallelCG.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | 7d135dc70f03 |
children | 3a76565eade5 |
line wrap: on
line diff
--- a/lib/CodeGen/ParallelCG.cpp Tue Jan 26 22:56:36 2016 +0900 +++ b/lib/CodeGen/ParallelCG.cpp Fri Nov 25 19:14:25 2016 +0900 @@ -12,86 +12,89 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/ParallelCG.h" -#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/thread.h" +#include "llvm/Support/ThreadPool.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/SplitModule.h" 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, + function_ref<std::unique_ptr<TargetMachine>()> TMFactory, TargetMachine::CodeGenFileType FileType) { - std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine( - M->getTargetTriple(), CPU, Features, Options, RM, CM, OL)); - + std::unique_ptr<TargetMachine> TM = TMFactory(); legacy::PassManager CodeGenPasses; if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType)) report_fatal_error("Failed to setup codegen"); CodeGenPasses.run(*M); } -std::unique_ptr<Module> -llvm::splitCodeGen(std::unique_ptr<Module> M, - ArrayRef<llvm::raw_pwrite_stream *> OSs, 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); +std::unique_ptr<Module> llvm::splitCodeGen( + std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs, + ArrayRef<llvm::raw_pwrite_stream *> BCOSs, + const std::function<std::unique_ptr<TargetMachine>()> &TMFactory, + TargetMachine::CodeGenFileType FileType, bool PreserveLocals) { + assert(BCOSs.empty() || BCOSs.size() == OSs.size()); if (OSs.size() == 1) { - codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, - OL, FileType); + if (!BCOSs.empty()) + WriteBitcodeToFile(M.get(), *BCOSs[0]); + codegen(M.get(), *OSs[0], TMFactory, FileType); return M; } - std::vector<thread> Threads; - SplitModule(std::move(M), OSs.size(), [&](std::unique_ptr<Module> MPart) { - // We want to clone the module in a new context to multi-thread the codegen. - // We do it by serializing partition modules to bitcode (while still on the - // main thread, in order to avoid data races) and spinning up new threads - // which deserialize the partitions into separate contexts. - // FIXME: Provide a more direct way to do this in LLVM. - SmallVector<char, 0> BC; - raw_svector_ostream BCOS(BC); - WriteBitcodeToFile(MPart.get(), BCOS); + // Create ThreadPool in nested scope so that threads will be joined + // on destruction. + { + ThreadPool CodegenThreadPool(OSs.size()); + int ThreadCount = 0; + + SplitModule( + std::move(M), OSs.size(), + [&](std::unique_ptr<Module> MPart) { + // We want to clone the module in a new context to multi-thread the + // codegen. We do it by serializing partition modules to bitcode + // (while still on the main thread, in order to avoid data races) and + // spinning up new threads which deserialize the partitions into + // separate contexts. + // FIXME: Provide a more direct way to do this in LLVM. + SmallString<0> BC; + raw_svector_ostream BCOS(BC); + WriteBitcodeToFile(MPart.get(), BCOS); - llvm::raw_pwrite_stream *ThreadOS = OSs[Threads.size()]; - Threads.emplace_back( - [TheTarget, CPU, Features, Options, RM, CM, OL, FileType, - ThreadOS](const SmallVector<char, 0> &BC) { - LLVMContext Ctx; - ErrorOr<std::unique_ptr<Module>> MOrErr = - parseBitcodeFile(MemoryBufferRef(StringRef(BC.data(), BC.size()), - "<split-module>"), - Ctx); - if (!MOrErr) - report_fatal_error("Failed to read bitcode"); - std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); + if (!BCOSs.empty()) { + BCOSs[ThreadCount]->write(BC.begin(), BC.size()); + BCOSs[ThreadCount]->flush(); + } - codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features, - Options, RM, CM, OL, FileType); + llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++]; + // Enqueue the task + CodegenThreadPool.async( + [TMFactory, FileType, ThreadOS](const SmallString<0> &BC) { + LLVMContext Ctx; + Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( + MemoryBufferRef(StringRef(BC.data(), BC.size()), + "<split-module>"), + Ctx); + if (!MOrErr) + report_fatal_error("Failed to read bitcode"); + std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); + + 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. + std::move(BC)); }, - // Pass BC using std::move to ensure that it get moved rather than - // copied into the thread's context. - std::move(BC)); - }, PreserveLocals); - - for (thread &T : Threads) - T.join(); + PreserveLocals); + } return {}; }