X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FLTO%2FLTOCodeGenerator.cpp;h=8dcc53c8033ac870e1e57e33f9136cba93f0d097;hb=b6cb6238b9c5243ec813a860ae153adda1acddff;hp=345b22463889d6626f65699634c6d365e87bdb03;hpb=d044549557efc225189f2eabba83d2d02ff58ea7;p=oota-llvm.git diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 345b2246388..8dcc53c8033 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/ParallelCG.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/Config/config.h" #include "llvm/IR/Constants.h" @@ -29,7 +30,6 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" -#include "llvm/IR/UseListOrder.h" #include "llvm/IR/Verifier.h" #include "llvm/InitializePasses.h" #include "llvm/LTO/LTOModule.h" @@ -64,52 +64,29 @@ const char* LTOCodeGenerator::getVersionString() { #endif } +static void handleLTODiagnostic(const DiagnosticInfo &DI) { + DiagnosticPrinterRawOStream DP(errs()); + DI.print(DP); + errs() << "\n"; +} + LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)) { - initialize(); + : Context(getGlobalContext()), + MergedModule(new Module("ld-temp.o", Context)), + IRLinker(MergedModule.get(), handleLTODiagnostic) { + initializeLTOPasses(); } LTOCodeGenerator::LTOCodeGenerator(std::unique_ptr Context) : OwnedContext(std::move(Context)), Context(*OwnedContext), - IRLinker(new Module("ld-temp.o", *OwnedContext)), OptLevel(2) { - initialize(); -} - -void LTOCodeGenerator::initialize() { - TargetMach = nullptr; - EmitDwarfDebugInfo = false; - ScopeRestrictionsDone = false; - CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; - DiagHandler = nullptr; - DiagContext = nullptr; - OwnedModule = nullptr; - + MergedModule(new Module("ld-temp.o", *OwnedContext)), + IRLinker(MergedModule.get(), handleLTODiagnostic) { initializeLTOPasses(); } -void LTOCodeGenerator::destroyMergedModule() { - if (OwnedModule) { - assert(IRLinker.getModule() == &OwnedModule->getModule() && - "The linker's module should be the same as the owned module"); - delete OwnedModule; - OwnedModule = nullptr; - } else if (IRLinker.getModule()) - IRLinker.deleteModule(); -} - -LTOCodeGenerator::~LTOCodeGenerator() { - destroyMergedModule(); +LTOCodeGenerator::~LTOCodeGenerator() {} - delete TargetMach; - TargetMach = nullptr; - - for (std::vector::iterator I = CodegenOptions.begin(), - E = CodegenOptions.end(); - I != E; ++I) - free(*I); -} - -// Initialize LTO passes. Please keep this funciton in sync with +// Initialize LTO passes. Please keep this function in sync with // PassManagerBuilder::populateLTOPassManager(), and make sure all LTO // passes are initialized. void LTOCodeGenerator::initializeLTOPasses() { @@ -126,11 +103,11 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeGlobalDCEPass(R); initializeArgPromotionPass(R); initializeJumpThreadingPass(R); - initializeSROAPass(R); + initializeSROALegacyPassPass(R); initializeSROA_DTPass(R); initializeSROA_SSAUpPass(R); initializeFunctionAttrsPass(R); - initializeGlobalsModRefPass(R); + initializeGlobalsAAWrapperPassPass(R); initializeLICMPass(R); initializeMergedLoadStoreMotionPass(R); initializeGVNPass(R); @@ -139,41 +116,39 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeCFGSimplifyPassPass(R); } -bool LTOCodeGenerator::addModule(LTOModule *mod) { - assert(&mod->getModule().getContext() == &Context && +bool LTOCodeGenerator::addModule(LTOModule *Mod) { + assert(&Mod->getModule().getContext() == &Context && "Expected module in same context"); - bool ret = IRLinker.linkInModule(&mod->getModule()); + bool ret = IRLinker.linkInModule(&Mod->getModule()); - const std::vector &undefs = mod->getAsmUndefinedRefs(); + const std::vector &undefs = Mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) AsmUndefinedRefs[undefs[i]] = 1; return !ret; } -void LTOCodeGenerator::setModule(LTOModule *Mod) { +void LTOCodeGenerator::setModule(std::unique_ptr Mod) { assert(&Mod->getModule().getContext() == &Context && "Expected module in same context"); - // Delete the old merged module. - destroyMergedModule(); AsmUndefinedRefs.clear(); - OwnedModule = Mod; - IRLinker.setModule(&Mod->getModule()); + MergedModule = Mod->takeModule(); + IRLinker.setModule(MergedModule.get()); const std::vector &Undefs = Mod->getAsmUndefinedRefs(); for (int I = 0, E = Undefs.size(); I != E; ++I) AsmUndefinedRefs[Undefs[I]] = 1; } -void LTOCodeGenerator::setTargetOptions(TargetOptions options) { - Options = options; +void LTOCodeGenerator::setTargetOptions(TargetOptions Options) { + this->Options = Options; } -void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { - switch (debug) { +void LTOCodeGenerator::setDebugInfo(lto_debug_model Debug) { + switch (Debug) { case LTO_DEBUG_MODEL_NONE: EmitDwarfDebugInfo = false; return; @@ -185,21 +160,27 @@ void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) { llvm_unreachable("Unknown debug format!"); } -void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) { - switch (model) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - case LTO_CODEGEN_PIC_MODEL_DEFAULT: - CodeModel = model; - return; +void LTOCodeGenerator::setOptLevel(unsigned Level) { + OptLevel = Level; + switch (OptLevel) { + case 0: + CGOptLevel = CodeGenOpt::None; + break; + case 1: + CGOptLevel = CodeGenOpt::Less; + break; + case 2: + CGOptLevel = CodeGenOpt::Default; + break; + case 3: + CGOptLevel = CodeGenOpt::Aggressive; + break; } - llvm_unreachable("Unknown PIC model!"); } -bool LTOCodeGenerator::writeMergedModules(const char *path, - std::string &errMsg) { - if (!determineTarget(errMsg)) +bool LTOCodeGenerator::writeMergedModules(const char *Path, + std::string &ErrMsg) { + if (!determineTarget(ErrMsg)) return false; // mark which symbols can not be internalized @@ -207,20 +188,20 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, // create output file std::error_code EC; - tool_output_file Out(path, EC, sys::fs::F_None); + tool_output_file Out(Path, EC, sys::fs::F_None); if (EC) { - errMsg = "could not open bitcode file for writing: "; - errMsg += path; + ErrMsg = "could not open bitcode file for writing: "; + ErrMsg += Path; return false; } // write bitcode to it - WriteBitcodeToFile(IRLinker.getModule(), Out.os()); + WriteBitcodeToFile(MergedModule.get(), Out.os(), ShouldEmbedUselists); Out.os().close(); if (Out.os().has_error()) { - errMsg = "could not write bitcode file: "; - errMsg += path; + ErrMsg = "could not write bitcode file: "; + ErrMsg += Path; Out.os().clear_error(); return false; } @@ -229,22 +210,22 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, return true; } -bool LTOCodeGenerator::compileOptimizedToFile(const char **name, - std::string &errMsg) { +bool LTOCodeGenerator::compileOptimizedToFile(const char **Name, + std::string &ErrMsg) { // make unique temp .o file to put generated object file SmallString<128> Filename; int FD; std::error_code EC = sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename); if (EC) { - errMsg = EC.message(); + ErrMsg = EC.message(); return false; } // generate object file tool_output_file objFile(Filename.c_str(), FD); - bool genResult = compileOptimized(objFile.os(), errMsg); + bool genResult = compileOptimized(&objFile.os(), ErrMsg); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); @@ -259,98 +240,75 @@ bool LTOCodeGenerator::compileOptimizedToFile(const char **name, } NativeObjectPath = Filename.c_str(); - *name = NativeObjectPath.c_str(); + *Name = NativeObjectPath.c_str(); return true; } -const void *LTOCodeGenerator::compileOptimized(size_t *length, - std::string &errMsg) { +std::unique_ptr +LTOCodeGenerator::compileOptimized(std::string &ErrMsg) { const char *name; - if (!compileOptimizedToFile(&name, errMsg)) + if (!compileOptimizedToFile(&name, ErrMsg)) return nullptr; // read .o file into memory buffer ErrorOr> BufferOrErr = MemoryBuffer::getFile(name, -1, false); if (std::error_code EC = BufferOrErr.getError()) { - errMsg = EC.message(); + ErrMsg = EC.message(); sys::fs::remove(NativeObjectPath); return nullptr; } - NativeObjectFile = std::move(*BufferOrErr); // remove temp files sys::fs::remove(NativeObjectPath); - // return buffer, unless error - if (!NativeObjectFile) - return nullptr; - *length = NativeObjectFile->getBufferSize(); - return NativeObjectFile->getBufferStart(); + return std::move(*BufferOrErr); } - -bool LTOCodeGenerator::compile_to_file(const char **name, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string &errMsg) { - if (!optimize(disableInline, disableGVNLoadPRE, - disableVectorization, errMsg)) +bool LTOCodeGenerator::compile_to_file(const char **Name, bool DisableVerify, + bool DisableInline, + bool DisableGVNLoadPRE, + bool DisableVectorization, + std::string &ErrMsg) { + if (!optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, + DisableVectorization, ErrMsg)) return false; - return compileOptimizedToFile(name, errMsg); + return compileOptimizedToFile(Name, ErrMsg); } -const void* LTOCodeGenerator::compile(size_t *length, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string &errMsg) { - if (!optimize(disableInline, disableGVNLoadPRE, - disableVectorization, errMsg)) +std::unique_ptr +LTOCodeGenerator::compile(bool DisableVerify, bool DisableInline, + bool DisableGVNLoadPRE, bool DisableVectorization, + std::string &ErrMsg) { + if (!optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, + DisableVectorization, ErrMsg)) return nullptr; - return compileOptimized(length, errMsg); + return compileOptimized(ErrMsg); } -bool LTOCodeGenerator::determineTarget(std::string &errMsg) { +bool LTOCodeGenerator::determineTarget(std::string &ErrMsg) { if (TargetMach) return true; - std::string TripleStr = IRLinker.getModule()->getTargetTriple(); - if (TripleStr.empty()) + std::string TripleStr = MergedModule->getTargetTriple(); + if (TripleStr.empty()) { TripleStr = sys::getDefaultTargetTriple(); + MergedModule->setTargetTriple(TripleStr); + } llvm::Triple Triple(TripleStr); // create target machine from info for merged modules - const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg); + const Target *march = TargetRegistry::lookupTarget(TripleStr, ErrMsg); if (!march) return false; - // The relocation model is actually a static member of TargetMachine and - // needs to be set before the TargetMachine is instantiated. - Reloc::Model RelocModel = Reloc::Default; - switch (CodeModel) { - case LTO_CODEGEN_PIC_MODEL_STATIC: - RelocModel = Reloc::Static; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC: - RelocModel = Reloc::PIC_; - break; - case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC: - RelocModel = Reloc::DynamicNoPIC; - break; - case LTO_CODEGEN_PIC_MODEL_DEFAULT: - // RelocModel is already the default, so leave it that way. - break; - } - // Construct LTOModule, hand over ownership of module and target. Use MAttr as // the default set of features. SubtargetFeatures Features(MAttr); Features.getDefaultSubtargetFeatures(Triple); - std::string FeatureStr = Features.getString(); + FeatureStr = Features.getString(); // Set a default CPU for Darwin triples. if (MCpu.empty() && Triple.isOSDarwin()) { if (Triple.getArch() == llvm::Triple::x86_64) @@ -361,25 +319,9 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { MCpu = "cyclone"; } - CodeGenOpt::Level CGOptLevel; - switch (OptLevel) { - case 0: - CGOptLevel = CodeGenOpt::None; - break; - case 1: - CGOptLevel = CodeGenOpt::Less; - break; - case 2: - CGOptLevel = CodeGenOpt::Default; - break; - case 3: - CGOptLevel = CodeGenOpt::Aggressive; - break; - } - - TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options, - RelocModel, CodeModel::Default, - CGOptLevel); + TargetMach.reset(march->createTargetMachine(TripleStr, MCpu, FeatureStr, + Options, RelocModel, + CodeModel::Default, CGOptLevel)); return true; } @@ -464,36 +406,32 @@ static void accumulateAndSortLibcalls(std::vector &Libcalls, } void LTOCodeGenerator::applyScopeRestrictions() { - if (ScopeRestrictionsDone) + if (ScopeRestrictionsDone || !ShouldInternalize) return; - Module *mergedModule = IRLinker.getModule(); // Start off with a verification pass. legacy::PassManager passes; passes.add(createVerifierPass()); // mark which symbols can not be internalized - Mangler Mangler(TargetMach->getDataLayout()); + Mangler Mangler; std::vector MustPreserveList; SmallPtrSet AsmUsed; std::vector Libcalls; TargetLibraryInfoImpl TLII(Triple(TargetMach->getTargetTriple())); TargetLibraryInfo TLI(TLII); - accumulateAndSortLibcalls(Libcalls, TLI, *mergedModule, *TargetMach); + accumulateAndSortLibcalls(Libcalls, TLI, *MergedModule, *TargetMach); - for (Module::iterator f = mergedModule->begin(), - e = mergedModule->end(); f != e; ++f) - applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler); - for (Module::global_iterator v = mergedModule->global_begin(), - e = mergedModule->global_end(); v != e; ++v) - applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler); - for (Module::alias_iterator a = mergedModule->alias_begin(), - e = mergedModule->alias_end(); a != e; ++a) - applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler); + for (Function &f : *MergedModule) + applyRestriction(f, Libcalls, MustPreserveList, AsmUsed, Mangler); + for (GlobalVariable &v : MergedModule->globals()) + applyRestriction(v, Libcalls, MustPreserveList, AsmUsed, Mangler); + for (GlobalAlias &a : MergedModule->aliases()) + applyRestriction(a, Libcalls, MustPreserveList, AsmUsed, Mangler); GlobalVariable *LLVMCompilerUsed = - mergedModule->getGlobalVariable("llvm.compiler.used"); + MergedModule->getGlobalVariable("llvm.compiler.used"); findUsedValues(LLVMCompilerUsed, AsmUsed); if (LLVMCompilerUsed) LLVMCompilerUsed->eraseFromParent(); @@ -508,7 +446,7 @@ void LTOCodeGenerator::applyScopeRestrictions() { llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size()); LLVMCompilerUsed = - new llvm::GlobalVariable(*mergedModule, ATy, false, + new llvm::GlobalVariable(*MergedModule, ATy, false, llvm::GlobalValue::AppendingLinkage, llvm::ConstantArray::get(ATy, asmUsed2), "llvm.compiler.used"); @@ -519,21 +457,19 @@ void LTOCodeGenerator::applyScopeRestrictions() { passes.add(createInternalizePass(MustPreserveList)); // apply scope restrictions - passes.run(*mergedModule); + passes.run(*MergedModule); ScopeRestrictionsDone = true; } /// Optimize merged modules using various IPO passes -bool LTOCodeGenerator::optimize(bool DisableInline, +bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, bool DisableGVNLoadPRE, bool DisableVectorization, - std::string &errMsg) { - if (!this->determineTarget(errMsg)) + std::string &ErrMsg) { + if (!this->determineTarget(ErrMsg)) return false; - Module *mergedModule = IRLinker.getModule(); - // Mark which symbols can not be internalized this->applyScopeRestrictions(); @@ -541,7 +477,7 @@ bool LTOCodeGenerator::optimize(bool DisableInline, legacy::PassManager passes; // Add an appropriate DataLayout instance for this module... - mergedModule->setDataLayout(*TargetMach->getDataLayout()); + MergedModule->setDataLayout(TargetMach->createDataLayout()); passes.add( createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis())); @@ -555,63 +491,58 @@ bool LTOCodeGenerator::optimize(bool DisableInline, PMB.Inliner = createFunctionInliningPass(); PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple); PMB.OptLevel = OptLevel; - PMB.VerifyInput = true; - PMB.VerifyOutput = true; + PMB.VerifyInput = !DisableVerify; + PMB.VerifyOutput = !DisableVerify; PMB.populateLTOPassManager(passes); // Run our queue of passes all at once now, efficiently. - passes.run(*mergedModule); + passes.run(*MergedModule); return true; } -bool LTOCodeGenerator::compileOptimized(raw_ostream &out, std::string &errMsg) { - if (!this->determineTarget(errMsg)) +bool LTOCodeGenerator::compileOptimized(ArrayRef Out, + std::string &ErrMsg) { + if (!this->determineTarget(ErrMsg)) return false; - Module *mergedModule = IRLinker.getModule(); - - legacy::PassManager codeGenPasses; + legacy::PassManager preCodeGenPasses; // If the bitcode files contain ARC code and were compiled with optimization, // the ObjCARCContractPass must be run, so do it unconditionally here. - codeGenPasses.add(createObjCARCContractPass()); - - if (TargetMach->addPassesToEmitFile(codeGenPasses, out, - TargetMachine::CGFT_ObjectFile)) { - errMsg = "target file type not supported"; - return false; - } - - // Run the code generator, and write assembly file - codeGenPasses.run(*mergedModule); + preCodeGenPasses.add(createObjCARCContractPass()); + preCodeGenPasses.run(*MergedModule); + + // Do code generation. We need to preserve the module in case the client calls + // writeMergedModules() after compilation, but we only need to allow this at + // 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); return true; } /// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging /// LTO problems. -void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) { - for (std::pair o = getToken(options); - !o.first.empty(); o = getToken(o.second)) { - // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add - // that. - if (CodegenOptions.empty()) - CodegenOptions.push_back(strdup("libLLVMLTO")); - CodegenOptions.push_back(strdup(o.first.str().c_str())); - } +void LTOCodeGenerator::setCodeGenDebugOptions(const char *Options) { + for (std::pair o = getToken(Options); !o.first.empty(); + o = getToken(o.second)) + CodegenOptions.push_back(o.first); } void LTOCodeGenerator::parseCodeGenDebugOptions() { - // Turn on -preserve-bc-uselistorder by default, but let the command-line - // override it. - setPreserveBitcodeUseListOrder(true); - // if options were requested, set them - if (!CodegenOptions.empty()) - cl::ParseCommandLineOptions(CodegenOptions.size(), - const_cast(&CodegenOptions[0])); + if (!CodegenOptions.empty()) { + // ParseCommandLineOptions() expects argv[0] to be program name. + std::vector CodegenArgv(1, "libLLVMLTO"); + for (std::string &Arg : CodegenOptions) + CodegenArgv.push_back(Arg.c_str()); + cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data()); + } } void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,