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> llvm::splitCodeGen(
43     std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
44     ArrayRef<llvm::raw_pwrite_stream *> BCOSs, StringRef CPU,
45     StringRef Features, const TargetOptions &Options, Reloc::Model RM,
46     CodeModel::Model CM, CodeGenOpt::Level OL,
47     TargetMachine::CodeGenFileType FileType, bool PreserveLocals) {
48   StringRef TripleStr = M->getTargetTriple();
49   std::string ErrMsg;
50   const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
51   if (!TheTarget)
52     report_fatal_error(Twine("Target not found: ") + ErrMsg);
53 
54   assert(BCOSs.empty() || BCOSs.size() == OSs.size());
55 
56   if (OSs.size() == 1) {
57     if (!BCOSs.empty())
58       WriteBitcodeToFile(M.get(), *BCOSs[0]);
59     codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, OL,
60             FileType);
61     return M;
62   }
63 
64   // Create ThreadPool in nested scope so that threads will be joined
65   // on destruction.
66   {
67     ThreadPool CodegenThreadPool(OSs.size());
68     int ThreadCount = 0;
69 
70     SplitModule(
71         std::move(M), OSs.size(),
72         [&](std::unique_ptr<Module> MPart) {
73           // We want to clone the module in a new context to multi-thread the
74           // codegen. We do it by serializing partition modules to bitcode
75           // (while still on the main thread, in order to avoid data races) and
76           // spinning up new threads which deserialize the partitions into
77           // separate contexts.
78           // FIXME: Provide a more direct way to do this in LLVM.
79           SmallVector<char, 0> BC;
80           raw_svector_ostream BCOS(BC);
81           WriteBitcodeToFile(MPart.get(), BCOS);
82 
83           if (!BCOSs.empty()) {
84             BCOSs[ThreadCount]->write(BC.begin(), BC.size());
85             BCOSs[ThreadCount]->flush();
86           }
87 
88           llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++];
89           // Enqueue the task
90           CodegenThreadPool.async(
91               [TheTarget, CPU, Features, Options, RM, CM, OL, FileType,
92                ThreadOS](const SmallVector<char, 0> &BC) {
93                 LLVMContext Ctx;
94                 ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
95                     MemoryBufferRef(StringRef(BC.data(), BC.size()),
96                                     "<split-module>"),
97                     Ctx);
98                 if (!MOrErr)
99                   report_fatal_error("Failed to read bitcode");
100                 std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
101 
102                 codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features,
103                         Options, RM, CM, OL, FileType);
104               },
105               // Pass BC using std::move to ensure that it get moved rather than
106               // copied into the thread's context.
107               std::move(BC));
108         },
109         PreserveLocals);
110   }
111 
112   return {};
113 }
114