summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/ParallelCG.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2015-08-27 23:37:36 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2015-08-27 23:37:36 +0000
commitc269ed511584d9044a4e28a25fa6a0d24df68a9f (patch)
treeeb8ec1c70b5fc9d78ab61aacaffab6d9ab1bb16d /llvm/lib/CodeGen/ParallelCG.cpp
parent0e2882345daead6cd9368eda4107e860d9141e35 (diff)
downloadbcm5719-llvm-c269ed511584d9044a4e28a25fa6a0d24df68a9f.tar.gz
bcm5719-llvm-c269ed511584d9044a4e28a25fa6a0d24df68a9f.zip
CodeGen: Introduce splitCodeGen and teach LTOCodeGenerator to use it.
llvm::splitCodeGen is a function that implements the core of parallel LTO code generation. It uses llvm::SplitModule to split the module into linkable partitions and spawning one code generation thread per partition. The function produces multiple object files which can be linked in the usual way. This has been threaded through to LTOCodeGenerator (and llvm-lto for testing purposes). Separate patches will add parallel LTO support to the gold plugin and lld. Differential Revision: http://reviews.llvm.org/D12260 llvm-svn: 246236
Diffstat (limited to 'llvm/lib/CodeGen/ParallelCG.cpp')
-rw-r--r--llvm/lib/CodeGen/ParallelCG.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/ParallelCG.cpp b/llvm/lib/CodeGen/ParallelCG.cpp
new file mode 100644
index 00000000000..3e6a71d602b
--- /dev/null
+++ b/llvm/lib/CodeGen/ParallelCG.cpp
@@ -0,0 +1,95 @@
+//===-- ParallelCG.cpp ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines functions that can be used for parallel code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/ParallelCG.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/thread.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Utils/SplitModule.h"
+
+using namespace llvm;
+
+static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
+ const Target *TheTarget, StringRef CPU, StringRef Features,
+ const TargetOptions &Options, Reloc::Model RM,
+ CodeModel::Model CM, CodeGenOpt::Level OL) {
+ std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine(
+ M->getTargetTriple(), CPU, Features, Options, RM, CM, OL));
+
+ legacy::PassManager CodeGenPasses;
+ if (TM->addPassesToEmitFile(CodeGenPasses, OS,
+ TargetMachine::CGFT_ObjectFile))
+ report_fatal_error("Failed to setup codegen");
+ CodeGenPasses.run(*M);
+}
+
+std::unique_ptr<Module>
+llvm::splitCodeGen(std::unique_ptr<Module> M,
+ ArrayRef<llvm::raw_pwrite_stream *> OSs, StringRef CPU,
+ StringRef Features, const TargetOptions &Options,
+ Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) {
+ StringRef TripleStr = M->getTargetTriple();
+ std::string ErrMsg;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
+ if (!TheTarget)
+ report_fatal_error(Twine("Target not found: ") + ErrMsg);
+
+ if (OSs.size() == 1) {
+ codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM,
+ OL);
+ return M;
+ }
+
+ std::vector<std::thread> Threads;
+ SplitModule(std::move(M), OSs.size(), [&](std::unique_ptr<Module> MPart) {
+ // We want to clone the module in a new context to multi-thread the codegen.
+ // We do it by serializing partition modules to bitcode (while still on the
+ // main thread, in order to avoid data races) and spinning up new threads
+ // which deserialize the partitions into separate contexts.
+ // FIXME: Provide a more direct way to do this in LLVM.
+ SmallVector<char, 0> BC;
+ raw_svector_ostream BCOS(BC);
+ WriteBitcodeToFile(MPart.get(), BCOS);
+
+ llvm::raw_pwrite_stream *ThreadOS = OSs[Threads.size()];
+ Threads.emplace_back(
+ [TheTarget, CPU, Features, Options, RM, CM, OL,
+ ThreadOS](const SmallVector<char, 0> &BC) {
+ LLVMContext Ctx;
+ ErrorOr<std::unique_ptr<Module>> MOrErr =
+ parseBitcodeFile(MemoryBufferRef(StringRef(BC.data(), BC.size()),
+ "<split-module>"),
+ Ctx);
+ if (!MOrErr)
+ report_fatal_error("Failed to read bitcode");
+ std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
+
+ codegen(MPartInCtx.get(), *ThreadOS, TheTarget, CPU, Features,
+ Options, RM, CM, OL);
+ },
+ // Pass BC using std::move to ensure that it get moved rather than
+ // copied into the thread's context.
+ std::move(BC));
+ });
+
+ for (std::thread &T : Threads)
+ T.join();
+
+ return {};
+}
OpenPOWER on IntegriCloud