ParallelCG.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. #include "llvm/CodeGen/ParallelCG.h"
  14. #include "llvm/Bitcode/ReaderWriter.h"
  15. #include "llvm/IR/LLVMContext.h"
  16. #include "llvm/IR/LegacyPassManager.h"
  17. #include "llvm/IR/Module.h"
  18. #include "llvm/Support/ErrorOr.h"
  19. #include "llvm/Support/MemoryBuffer.h"
  20. #include "llvm/Support/TargetRegistry.h"
  21. #include "llvm/Support/ThreadPool.h"
  22. #include "llvm/Target/TargetMachine.h"
  23. #include "llvm/Transforms/Utils/SplitModule.h"
  24. using namespace llvm;
  25. static void
  26. codegen(Module *M, llvm::raw_pwrite_stream &OS,
  27. std::function<std::unique_ptr<TargetMachine>()> TMFactory,
  28. TargetMachine::CodeGenFileType FileType) {
  29. std::unique_ptr<TargetMachine> TM = TMFactory();
  30. legacy::PassManager CodeGenPasses;
  31. if (TM->addPassesToEmitFile(CodeGenPasses, OS, FileType))
  32. report_fatal_error("Failed to setup codegen");
  33. CodeGenPasses.run(*M);
  34. }
  35. std::unique_ptr<Module> llvm::splitCodeGen(
  36. std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
  37. ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
  38. const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
  39. TargetMachine::CodeGenFileType FileType, bool PreserveLocals) {
  40. assert(BCOSs.empty() || BCOSs.size() == OSs.size());
  41. if (OSs.size() == 1) {
  42. if (!BCOSs.empty())
  43. WriteBitcodeToFile(M.get(), *BCOSs[0]);
  44. codegen(M.get(), *OSs[0], TMFactory, FileType);
  45. return M;
  46. }
  47. // Create ThreadPool in nested scope so that threads will be joined
  48. // on destruction.
  49. {
  50. ThreadPool CodegenThreadPool(OSs.size());
  51. int ThreadCount = 0;
  52. SplitModule(
  53. std::move(M), OSs.size(),
  54. [&](std::unique_ptr<Module> MPart) {
  55. // We want to clone the module in a new context to multi-thread the
  56. // codegen. We do it by serializing partition modules to bitcode
  57. // (while still on the main thread, in order to avoid data races) and
  58. // spinning up new threads which deserialize the partitions into
  59. // separate contexts.
  60. // FIXME: Provide a more direct way to do this in LLVM.
  61. SmallVector<char, 0> BC;
  62. raw_svector_ostream BCOS(BC);
  63. WriteBitcodeToFile(MPart.get(), BCOS);
  64. if (!BCOSs.empty()) {
  65. BCOSs[ThreadCount]->write(BC.begin(), BC.size());
  66. BCOSs[ThreadCount]->flush();
  67. }
  68. llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++];
  69. // Enqueue the task
  70. CodegenThreadPool.async(
  71. [TMFactory, FileType, ThreadOS](const SmallVector<char, 0> &BC) {
  72. LLVMContext Ctx;
  73. ErrorOr<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
  74. MemoryBufferRef(StringRef(BC.data(), BC.size()),
  75. "<split-module>"),
  76. Ctx);
  77. if (!MOrErr)
  78. report_fatal_error("Failed to read bitcode");
  79. std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
  80. codegen(MPartInCtx.get(), *ThreadOS, TMFactory, FileType);
  81. },
  82. // Pass BC using std::move to ensure that it get moved rather than
  83. // copied into the thread's context.
  84. std::move(BC));
  85. },
  86. PreserveLocals);
  87. }
  88. return {};
  89. }