1 //===-- ParallelCG.cpp ----------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines functions that can be used for parallel code generation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/ParallelCG.h" 15 #include "llvm/Bitcode/ReaderWriter.h" 16 #include "llvm/IR/LLVMContext.h" 17 #include "llvm/IR/LegacyPassManager.h" 18 #include "llvm/IR/Module.h" 19 #include "llvm/Support/ErrorOr.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/TargetRegistry.h" 22 #include "llvm/Support/ThreadPool.h" 23 #include "llvm/Target/TargetMachine.h" 24 #include "llvm/Transforms/Utils/SplitModule.h" 25 26 using namespace llvm; 27 28 static void codegen(Module *M, llvm::raw_pwrite_stream &OS, 29 const Target *TheTarget, StringRef CPU, StringRef Features, 30 const TargetOptions &Options, Reloc::Model RM, 31 CodeModel::Model CM, CodeGenOpt::Level OL, 32 TargetMachine::CodeGenFileType FileType) { 33 std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine( 34 M->getTargetTriple(), CPU, Features, Options, RM, CM, OL)); 35 36 legacy::PassManager CodeGenPasses; 37 if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType)) 38 report_fatal_error("Failed to setup codegen"); 39 CodeGenPasses.run(*M); 40 } 41 42 std::unique_ptr<Module> 43 llvm::splitCodeGen(std::unique_ptr<Module> M, 44 ArrayRef<llvm::raw_pwrite_stream *> OSs, StringRef CPU, 45 StringRef Features, const TargetOptions &Options, 46 Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, 47 TargetMachine::CodeGenFileType FileType, 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 55 if (OSs.size() == 1) { 56 codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, 57 OL, FileType); 58 return M; 59 } 60 61 // Create ThreadPool in nested scope so that threads will be joined 62 // on destruction. 63 { 64 ThreadPool CodegenThreadPool(OSs.size()); 65 int ThreadCount = 0; 66 67 SplitModule( 68 std::move(M), OSs.size(), 69 [&](std::unique_ptr<Module> MPart) { 70 // We want to clone the module in a new context to multi-thread the 71 // codegen. We do it by serializing partition modules to bitcode 72 // (while still on the main thread, in order to avoid data races) and 73 // spinning up new threads which deserialize the partitions into 74 // separate contexts. 75 // FIXME: Provide a more direct way to do this in LLVM. 76 SmallVector<char, 0> BC; 77 raw_svector_ostream BCOS(BC); 78 WriteBitcodeToFile(MPart.get(), BCOS); 79 80 llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++]; 81 // Enqueue the task 82 CodegenThreadPool.async( 83 [TheTarget, CPU, Features, Options, RM, CM, OL, FileType, 84 ThreadOS](const SmallVector<char, 0> &BC) { 85 LLVMContext Ctx; 86 ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( 87 MemoryBufferRef(StringRef(BC.data(), BC.size()), 88 "<split-module>"), 89 Ctx); 90 if (!MOrErr) 91 report_fatal_error("Failed to read bitcode"); 92 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 93 94 codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features, 95 Options, RM, CM, OL, FileType); 96 }, 97 // Pass BC using std::move to ensure that it get moved rather than 98 // copied into the thread's context. 99 std::move(BC)); 100 }, 101 PreserveLocals); 102 } 103 104 return {}; 105 } 106