mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-25 23:45:36 +00:00
[gold] Save bitcode for module partitions (save-temps + split codegen).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265583 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fe58f90a22
commit
d8c5d5c30e
@ -29,10 +29,14 @@ class raw_pwrite_stream;
|
||||
/// files if linked together are intended to be equivalent to the single output
|
||||
/// file that would have been code generated from M.
|
||||
///
|
||||
/// Writes bitcode for individual partitions into output streams in BCOSs, if
|
||||
/// BCOSs is not empty.
|
||||
///
|
||||
/// \returns M if OSs.size() == 1, otherwise returns std::unique_ptr<Module>().
|
||||
std::unique_ptr<Module>
|
||||
splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs,
|
||||
StringRef CPU, StringRef Features, const TargetOptions &Options,
|
||||
ArrayRef<llvm::raw_pwrite_stream *> BCOSs, StringRef CPU,
|
||||
StringRef Features, const TargetOptions &Options,
|
||||
Reloc::Model RM = Reloc::Default,
|
||||
CodeModel::Model CM = CodeModel::Default,
|
||||
CodeGenOpt::Level OL = CodeGenOpt::Default,
|
||||
|
@ -39,22 +39,25 @@ static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
|
||||
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,
|
||||
TargetMachine::CodeGenFileType FileType,
|
||||
bool PreserveLocals) {
|
||||
std::unique_ptr<Module> llvm::splitCodeGen(
|
||||
std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
|
||||
ArrayRef<llvm::raw_pwrite_stream *> BCOSs, StringRef CPU,
|
||||
StringRef Features, const TargetOptions &Options, Reloc::Model RM,
|
||||
CodeModel::Model CM, CodeGenOpt::Level OL,
|
||||
TargetMachine::CodeGenFileType FileType, bool PreserveLocals) {
|
||||
StringRef TripleStr = M->getTargetTriple();
|
||||
std::string ErrMsg;
|
||||
const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
|
||||
if (!TheTarget)
|
||||
report_fatal_error(Twine("Target not found: ") + ErrMsg);
|
||||
|
||||
assert(BCOSs.empty() || BCOSs.size() == OSs.size());
|
||||
|
||||
if (OSs.size() == 1) {
|
||||
codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM,
|
||||
OL, FileType);
|
||||
if (!BCOSs.empty())
|
||||
WriteBitcodeToFile(M.get(), *BCOSs[0]);
|
||||
codegen(M.get(), *OSs[0], TheTarget, CPU, Features, Options, RM, CM, OL,
|
||||
FileType);
|
||||
return M;
|
||||
}
|
||||
|
||||
@ -77,6 +80,11 @@ llvm::splitCodeGen(std::unique_ptr<Module> M,
|
||||
raw_svector_ostream BCOS(BC);
|
||||
WriteBitcodeToFile(MPart.get(), BCOS);
|
||||
|
||||
if (!BCOSs.empty()) {
|
||||
BCOSs[ThreadCount]->write(BC.begin(), BC.size());
|
||||
BCOSs[ThreadCount]->flush();
|
||||
}
|
||||
|
||||
llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++];
|
||||
// Enqueue the task
|
||||
CodegenThreadPool.async(
|
||||
|
@ -562,10 +562,9 @@ bool LTOCodeGenerator::compileOptimized(ArrayRef<raw_pwrite_stream *> Out) {
|
||||
// parallelism level 1. This is achieved by having splitCodeGen return the
|
||||
// original module at parallelism level 1 which we then assign back to
|
||||
// MergedModule.
|
||||
MergedModule =
|
||||
splitCodeGen(std::move(MergedModule), Out, MCpu, FeatureStr, Options,
|
||||
RelocModel, CodeModel::Default, CGOptLevel, FileType,
|
||||
ShouldRestoreGlobalsLinkage);
|
||||
MergedModule = splitCodeGen(
|
||||
std::move(MergedModule), Out, {}, MCpu, FeatureStr, Options, RelocModel,
|
||||
CodeModel::Default, CGOptLevel, FileType, ShouldRestoreGlobalsLinkage);
|
||||
|
||||
// If statistics were requested, print them out after codegen.
|
||||
if (llvm::AreStatisticsEnabled())
|
||||
|
@ -1,10 +1,14 @@
|
||||
; RUN: llvm-as -o %t.bc %s
|
||||
; RUN: env LD_PRELOAD=%llvmshlibdir/LLVMgold.so %gold -plugin %llvmshlibdir/LLVMgold.so -u foo -u bar -plugin-opt jobs=2 -plugin-opt save-temps -m elf_x86_64 -o %t %t.bc
|
||||
; RUN: llvm-dis %t.opt.bc0 -o - | FileCheck --check-prefix=CHECK-BC0 %s
|
||||
; RUN: llvm-dis %t.opt.bc1 -o - | FileCheck --check-prefix=CHECK-BC1 %s
|
||||
; RUN: llvm-nm %t.o0 | FileCheck --check-prefix=CHECK0 %s
|
||||
; RUN: llvm-nm %t.o1 | FileCheck --check-prefix=CHECK1 %s
|
||||
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; CHECK-BC0: define void @foo
|
||||
; CHECK-BC0: declare void @bar
|
||||
; CHECK0-NOT: bar
|
||||
; CHECK0: T foo
|
||||
; CHECK0-NOT: bar
|
||||
@ -13,6 +17,8 @@ define void @foo() {
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-BC1: declare void @foo
|
||||
; CHECK-BC1: define void @bar
|
||||
; CHECK1-NOT: foo
|
||||
; CHECK1: T bar
|
||||
; CHECK1-NOT: foo
|
||||
|
@ -888,7 +888,9 @@ private:
|
||||
|
||||
/// Sets up output files necessary to perform optional multi-threaded
|
||||
/// split code generation, and invokes the code generation implementation.
|
||||
void runSplitCodeGen();
|
||||
/// If BCFileName is not empty, saves bitcode for module partitions into
|
||||
/// {BCFileName}0 .. {BCFileName}N.
|
||||
void runSplitCodeGen(const SmallString<128> &BCFilename);
|
||||
};
|
||||
}
|
||||
|
||||
@ -987,7 +989,7 @@ void CodeGen::runCodegenPasses() {
|
||||
CodeGenPasses.run(*M);
|
||||
}
|
||||
|
||||
void CodeGen::runSplitCodeGen() {
|
||||
void CodeGen::runSplitCodeGen(const SmallString<128> &BCFilename) {
|
||||
const std::string &TripleStr = M->getTargetTriple();
|
||||
Triple TheTriple(TripleStr);
|
||||
|
||||
@ -1010,6 +1012,7 @@ void CodeGen::runSplitCodeGen() {
|
||||
unsigned int MaxThreads = options::Parallelism ? options::Parallelism : 1;
|
||||
|
||||
std::vector<SmallString<128>> Filenames(MaxThreads);
|
||||
std::vector<SmallString<128>> BCFilenames(MaxThreads);
|
||||
bool TempOutFile = Filename.empty();
|
||||
{
|
||||
// Open a file descriptor for each backend task. This is done in a block
|
||||
@ -1024,8 +1027,18 @@ void CodeGen::runSplitCodeGen() {
|
||||
OSPtrs[I] = &OSs.back();
|
||||
}
|
||||
|
||||
std::list<llvm::raw_fd_ostream> BCOSs;
|
||||
std::vector<llvm::raw_pwrite_stream *> BCOSPtrs;
|
||||
if (!BCFilename.empty() && MaxThreads > 1) {
|
||||
for (unsigned I = 0; I != MaxThreads; ++I) {
|
||||
int FD = openOutputFile(BCFilename, false, BCFilenames[I], I);
|
||||
BCOSs.emplace_back(FD, true);
|
||||
BCOSPtrs.push_back(&BCOSs.back());
|
||||
}
|
||||
}
|
||||
|
||||
// Run backend tasks.
|
||||
splitCodeGen(std::move(M), OSPtrs, options::mcpu, Features.getString(),
|
||||
splitCodeGen(std::move(M), OSPtrs, BCOSPtrs, options::mcpu, Features.getString(),
|
||||
Options, RelocationModel, CodeModel::Default, CGOptLevel);
|
||||
}
|
||||
|
||||
@ -1036,14 +1049,16 @@ void CodeGen::runSplitCodeGen() {
|
||||
void CodeGen::runAll() {
|
||||
runLTOPasses();
|
||||
|
||||
SmallString<128> OptFilename;
|
||||
if (options::TheOutputType == options::OT_SAVE_TEMPS) {
|
||||
std::string OptFilename = output_name;
|
||||
OptFilename = output_name;
|
||||
// If the CodeGen client provided a filename, use it. Always expect
|
||||
// a provided filename if we are in a task (i.e. ThinLTO backend).
|
||||
assert(!SaveTempsFilename.empty() || TaskID == -1);
|
||||
if (!SaveTempsFilename.empty())
|
||||
OptFilename = SaveTempsFilename;
|
||||
saveBCFile(OptFilename + ".opt.bc", *M);
|
||||
OptFilename += ".opt.bc";
|
||||
saveBCFile(OptFilename, *M);
|
||||
}
|
||||
|
||||
// If we are already in a thread (i.e. ThinLTO), just perform
|
||||
@ -1052,7 +1067,7 @@ void CodeGen::runAll() {
|
||||
runCodegenPasses();
|
||||
// Otherwise attempt split code gen.
|
||||
else
|
||||
runSplitCodeGen();
|
||||
runSplitCodeGen(OptFilename);
|
||||
}
|
||||
|
||||
/// Links the module in \p View from file \p F into the combined module
|
||||
|
Loading…
x
Reference in New Issue
Block a user