Mercurial > hg > CbC > CbC_llvm
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 } |