Home | History | Annotate | Download | only in CodeGen
      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/thread.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   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   if (OSs.size() == 1) {
     55     codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM,
     56             OL, FileType);
     57     return M;
     58   }
     59 
     60   std::vector<thread> Threads;
     61   SplitModule(std::move(M), OSs.size(), [&](std::unique_ptr<Module> MPart) {
     62     // We want to clone the module in a new context to multi-thread the codegen.
     63     // We do it by serializing partition modules to bitcode (while still on the
     64     // main thread, in order to avoid data races) and spinning up new threads
     65     // which deserialize the partitions into separate contexts.
     66     // FIXME: Provide a more direct way to do this in LLVM.
     67     SmallVector<char, 0> BC;
     68     raw_svector_ostream BCOS(BC);
     69     WriteBitcodeToFile(MPart.get(), BCOS);
     70 
     71     llvm::raw_pwrite_stream *ThreadOS = OSs[Threads.size()];
     72     Threads.emplace_back(
     73         [TheTarget, CPU, Features, Options, RM, CM, OL, FileType,
     74          ThreadOS](const SmallVector<char, 0> &BC) {
     75           LLVMContext Ctx;
     76           ErrorOr<std::unique_ptr<Module>> MOrErr =
     77               parseBitcodeFile(MemoryBufferRef(StringRef(BC.data(), BC.size()),
     78                                                "<split-module>"),
     79                                Ctx);
     80           if (!MOrErr)
     81             report_fatal_error("Failed to read bitcode");
     82           std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
     83 
     84           codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features,
     85                   Options, RM, CM, OL, FileType);
     86         },
     87         // Pass BC using std::move to ensure that it get moved rather than
     88         // copied into the thread's context.
     89         std::move(BC));
     90   });
     91 
     92   for (thread &T : Threads)
     93     T.join();
     94 
     95   return {};
     96 }
     97