comparison 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
comparison
equal deleted inserted replaced
101:34baf5011add 120:1172e4bd9c6f
10 // This file defines functions that can be used for parallel code generation. 10 // This file defines functions that can be used for parallel code generation.
11 // 11 //
12 //===----------------------------------------------------------------------===// 12 //===----------------------------------------------------------------------===//
13 13
14 #include "llvm/CodeGen/ParallelCG.h" 14 #include "llvm/CodeGen/ParallelCG.h"
15 #include "llvm/Bitcode/ReaderWriter.h" 15 #include "llvm/Bitcode/BitcodeReader.h"
16 #include "llvm/Bitcode/BitcodeWriter.h"
16 #include "llvm/IR/LLVMContext.h" 17 #include "llvm/IR/LLVMContext.h"
17 #include "llvm/IR/LegacyPassManager.h" 18 #include "llvm/IR/LegacyPassManager.h"
18 #include "llvm/IR/Module.h" 19 #include "llvm/IR/Module.h"
19 #include "llvm/Support/ErrorOr.h" 20 #include "llvm/Support/ErrorOr.h"
20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/TargetRegistry.h" 22 #include "llvm/Support/TargetRegistry.h"
22 #include "llvm/Support/thread.h" 23 #include "llvm/Support/ThreadPool.h"
23 #include "llvm/Target/TargetMachine.h" 24 #include "llvm/Target/TargetMachine.h"
24 #include "llvm/Transforms/Utils/SplitModule.h" 25 #include "llvm/Transforms/Utils/SplitModule.h"
25 26
26 using namespace llvm; 27 using namespace llvm;
27 28
28 static void codegen(Module *M, llvm::raw_pwrite_stream &OS, 29 static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
29 const Target *TheTarget, StringRef CPU, StringRef Features, 30 function_ref<std::unique_ptr<TargetMachine>()> TMFactory,
30 const TargetOptions &Options, Reloc::Model RM,
31 CodeModel::Model CM, CodeGenOpt::Level OL,
32 TargetMachine::CodeGenFileType FileType) { 31 TargetMachine::CodeGenFileType FileType) {
33 std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine( 32 std::unique_ptr<TargetMachine> TM = TMFactory();
34 M->getTargetTriple(), CPU, Features, Options, RM, CM, OL));
35
36 legacy::PassManager CodeGenPasses; 33 legacy::PassManager CodeGenPasses;
37 if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType)) 34 if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType))
38 report_fatal_error("Failed to setup codegen"); 35 report_fatal_error("Failed to setup codegen");
39 CodeGenPasses.run(*M); 36 CodeGenPasses.run(*M);
40 } 37 }
41 38
42 std::unique_ptr<Module> 39 std::unique_ptr<Module> llvm::splitCodeGen(
43 llvm::splitCodeGen(std::unique_ptr<Module> M, 40 std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
44 ArrayRef<llvm::raw_pwrite_stream *> OSs, StringRef CPU, 41 ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
45 StringRef Features, const TargetOptions &Options, 42 const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
46 Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, 43 TargetMachine::CodeGenFileType FileType, bool PreserveLocals) {
47 TargetMachine::CodeGenFileType FileType, 44 assert(BCOSs.empty() || BCOSs.size() == OSs.size());
48 bool PreserveLocals) {
49 StringRef TripleStr = M->getTargetTriple();
50 std::string ErrMsg;
51 const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
52 if (!TheTarget)
53 report_fatal_error(Twine("Target not found: ") + ErrMsg);
54 45
55 if (OSs.size() == 1) { 46 if (OSs.size() == 1) {
56 codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, 47 if (!BCOSs.empty())
57 OL, FileType); 48 WriteBitcodeToFile(M.get(), *BCOSs[0]);
49 codegen(M.get(), *OSs[0], TMFactory, FileType);
58 return M; 50 return M;
59 } 51 }
60 52
61 std::vector<thread> Threads; 53 // Create ThreadPool in nested scope so that threads will be joined
62 SplitModule(std::move(M), OSs.size(), [&](std::unique_ptr<Module> MPart) { 54 // on destruction.
63 // We want to clone the module in a new context to multi-thread the codegen. 55 {
64 // We do it by serializing partition modules to bitcode (while still on the 56 ThreadPool CodegenThreadPool(OSs.size());
65 // main thread, in order to avoid data races) and spinning up new threads 57 int ThreadCount = 0;
66 // which deserialize the partitions into separate contexts.
67 // FIXME: Provide a more direct way to do this in LLVM.
68 SmallVector<char, 0> BC;
69 raw_svector_ostream BCOS(BC);
70 WriteBitcodeToFile(MPart.get(), BCOS);
71 58
72 llvm::raw_pwrite_stream *ThreadOS = OSs[Threads.size()]; 59 SplitModule(
73 Threads.emplace_back( 60 std::move(M), OSs.size(),
74 [TheTarget, CPU, Features, Options, RM, CM, OL, FileType, 61 [&](std::unique_ptr<Module> MPart) {
75 ThreadOS](const SmallVector<char, 0> &BC) { 62 // We want to clone the module in a new context to multi-thread the
76 LLVMContext Ctx; 63 // codegen. We do it by serializing partition modules to bitcode
77 ErrorOr<std::unique_ptr<Module>> MOrErr = 64 // (while still on the main thread, in order to avoid data races) and
78 parseBitcodeFile(MemoryBufferRef(StringRef(BC.data(), BC.size()), 65 // spinning up new threads which deserialize the partitions into
79 "<split-module>"), 66 // separate contexts.
80 Ctx); 67 // FIXME: Provide a more direct way to do this in LLVM.
81 if (!MOrErr) 68 SmallString<0> BC;
82 report_fatal_error("Failed to read bitcode"); 69 raw_svector_ostream BCOS(BC);
83 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 70 WriteBitcodeToFile(MPart.get(), BCOS);
84 71
85 codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features, 72 if (!BCOSs.empty()) {
86 Options, RM, CM, OL, FileType); 73 BCOSs[ThreadCount]->write(BC.begin(), BC.size());
74 BCOSs[ThreadCount]->flush();
75 }
76
77 llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++];
78 // Enqueue the task
79 CodegenThreadPool.async(
80 [TMFactory, FileType, ThreadOS](const SmallString<0> &BC) {
81 LLVMContext Ctx;
82 Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
83 MemoryBufferRef(StringRef(BC.data(), BC.size()),
84 "<split-module>"),
85 Ctx);
86 if (!MOrErr)
87 report_fatal_error("Failed to read bitcode");
88 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
89
90 codegen(MPartInCtx.get(), *ThreadOS, TMFactory, FileType);
91 },
92 // Pass BC using std::move to ensure that it get moved rather than
93 // copied into the thread's context.
94 std::move(BC));
87 }, 95 },
88 // Pass BC using std::move to ensure that it get moved rather than 96 PreserveLocals);
89 // copied into the thread's context. 97 }
90 std::move(BC));
91 }, PreserveLocals);
92
93 for (thread &T : Threads)
94 T.join();
95 98
96 return {}; 99 return {};
97 } 100 }