ParallelCG.cpp revision 353358
1194955Strasz//===-- ParallelCG.cpp ----------------------------------------------------===// 2194955Strasz// 3194955Strasz// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4194955Strasz// See https://llvm.org/LICENSE.txt for license information. 5194955Strasz// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6194955Strasz// 7194955Strasz//===----------------------------------------------------------------------===// 8194955Strasz// 9194955Strasz// This file defines functions that can be used for parallel code generation. 10194955Strasz// 11194955Strasz//===----------------------------------------------------------------------===// 12194955Strasz 13194955Strasz#include "llvm/CodeGen/ParallelCG.h" 14194955Strasz#include "llvm/Bitcode/BitcodeReader.h" 15194955Strasz#include "llvm/Bitcode/BitcodeWriter.h" 16194955Strasz#include "llvm/IR/LLVMContext.h" 17194955Strasz#include "llvm/IR/LegacyPassManager.h" 18194955Strasz#include "llvm/IR/Module.h" 19194955Strasz#include "llvm/Support/ErrorOr.h" 20194955Strasz#include "llvm/Support/MemoryBuffer.h" 21194955Strasz#include "llvm/Support/ThreadPool.h" 22194955Strasz#include "llvm/Target/TargetMachine.h" 23194955Strasz#include "llvm/Transforms/Utils/SplitModule.h" 24194955Strasz 25194955Straszusing namespace llvm; 26194955Strasz 27194955Straszstatic void codegen(Module *M, llvm::raw_pwrite_stream &OS, 28194955Strasz function_ref<std::unique_ptr<TargetMachine>()> TMFactory, 29194955Strasz TargetMachine::CodeGenFileType FileType) { 30194955Strasz std::unique_ptr<TargetMachine> TM = TMFactory(); 31194955Strasz legacy::PassManager CodeGenPasses; 32194955Strasz if (TM->addPassesToEmitFile(CodeGenPasses, OS, nullptr, FileType)) 33194955Strasz report_fatal_error("Failed to setup codegen"); 34194955Strasz CodeGenPasses.run(*M); 35194955Strasz} 36194955Strasz 37194955Straszstd::unique_ptr<Module> llvm::splitCodeGen( 38194955Strasz std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs, 39194955Strasz ArrayRef<llvm::raw_pwrite_stream *> BCOSs, 40194955Strasz const std::function<std::unique_ptr<TargetMachine>()> &TMFactory, 41194955Strasz TargetMachine::CodeGenFileType FileType, bool PreserveLocals) { 42194955Strasz assert(BCOSs.empty() || BCOSs.size() == OSs.size()); 43194955Strasz 44194955Strasz if (OSs.size() == 1) { 45194955Strasz if (!BCOSs.empty()) 46194955Strasz WriteBitcodeToFile(*M, *BCOSs[0]); 47194955Strasz codegen(M.get(), *OSs[0], TMFactory, FileType); 48194955Strasz return M; 49194955Strasz } 50194955Strasz 51194955Strasz // Create ThreadPool in nested scope so that threads will be joined 52194955Strasz // on destruction. 53194955Strasz { 54194955Strasz ThreadPool CodegenThreadPool(OSs.size()); 55194955Strasz int ThreadCount = 0; 56194955Strasz 57194955Strasz SplitModule( 58194955Strasz std::move(M), OSs.size(), 59194955Strasz [&](std::unique_ptr<Module> MPart) { 60194955Strasz // We want to clone the module in a new context to multi-thread the 61194955Strasz // codegen. We do it by serializing partition modules to bitcode 62194955Strasz // (while still on the main thread, in order to avoid data races) and 63194955Strasz // spinning up new threads which deserialize the partitions into 64194955Strasz // separate contexts. 65194955Strasz // FIXME: Provide a more direct way to do this in LLVM. 66194955Strasz SmallString<0> BC; 67194955Strasz raw_svector_ostream BCOS(BC); 68194955Strasz WriteBitcodeToFile(*MPart, BCOS); 69194955Strasz 70194955Strasz if (!BCOSs.empty()) { 71194955Strasz BCOSs[ThreadCount]->write(BC.begin(), BC.size()); 72194955Strasz BCOSs[ThreadCount]->flush(); 73194955Strasz } 74287547Sdelphij 75194955Strasz llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++]; 76194955Strasz // Enqueue the task 77194955Strasz CodegenThreadPool.async( 78194955Strasz [TMFactory, FileType, ThreadOS](const SmallString<0> &BC) { 79194955Strasz LLVMContext Ctx; 80194955Strasz Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile( 81194955Strasz MemoryBufferRef(StringRef(BC.data(), BC.size()), 82194955Strasz "<split-module>"), 83194955Strasz Ctx); 84194955Strasz if (!MOrErr) 85194955Strasz report_fatal_error("Failed to read bitcode"); 86194955Strasz std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get()); 87194955Strasz 88194955Strasz codegen(MPartInCtx.get(), *ThreadOS, TMFactory, FileType); 89194955Strasz }, 90194955Strasz // Pass BC using std::move to ensure that it get moved rather than 91194955Strasz // copied into the thread's context. 92194955Strasz std::move(BC)); 93194955Strasz }, 94194955Strasz PreserveLocals); 95194955Strasz } 96194955Strasz 97194955Strasz return {}; 98194955Strasz} 99194955Strasz