diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -191,8 +191,15 @@ /// destructor. class NativeObjectStream { public: - NativeObjectStream(std::unique_ptr OS) : OS(std::move(OS)) {} - std::unique_ptr OS; + NativeObjectStream(std::unique_ptr OS) + : OS_(std::move(OS)) { + this->OS = &*this->OS_; + } + NativeObjectStream(raw_pwrite_stream *OS) : OS(OS) {} + /// NativeObjectStream may own the allocation of the used raw_pwrite_stream, + /// if the caller requested that. + std::unique_ptr OS_; + raw_pwrite_stream *OS; virtual ~NativeObjectStream() = default; }; diff --git a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h --- a/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -41,6 +41,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Module.h" +#include "llvm/LTO/Config.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ToolOutputFile.h" @@ -73,6 +74,10 @@ LTOCodeGenerator(LLVMContext &Context); ~LTOCodeGenerator(); + /// Return a lto::Config object which contains the options set in + /// LTOCodeGenerator. + lto::Config toConfig() const; + /// Merge given module. Return true on success. /// /// Resets \a HasVerifiedInput. @@ -188,8 +193,6 @@ void DiagnosticHandler(const DiagnosticInfo &DI); private: - void initializeLTOPasses(); - /// Verify the merged module on first call. /// /// Sets \a HasVerifiedInput on first call and doesn't run again on the same diff --git a/llvm/lib/LTO/Caching.cpp b/llvm/lib/LTO/Caching.cpp --- a/llvm/lib/LTO/Caching.cpp +++ b/llvm/lib/LTO/Caching.cpp @@ -85,7 +85,8 @@ ~CacheStream() { // Make sure the stream is closed before committing it. - OS.reset(); + OS_.reset(); + OS = nullptr; // Open the file first to avoid racing with a cache pruner. ErrorOr> MBOrErr = diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -37,6 +37,7 @@ #include "llvm/IR/Verifier.h" #include "llvm/InitializePasses.h" #include "llvm/LTO/LTO.h" +#include "llvm/LTO/LTOBackend.h" #include "llvm/LTO/legacy/LTOModule.h" #include "llvm/LTO/legacy/UpdateCompilerUsed.h" #include "llvm/Linker/Linker.h" @@ -123,41 +124,29 @@ TheLinker(new Linker(*MergedModule)) { Context.setDiscardValueNames(LTODiscardValueNames); Context.enableDebugTypeODRUniquing(); - initializeLTOPasses(); } LTOCodeGenerator::~LTOCodeGenerator() {} -// Initialize LTO passes. Please keep this function in sync with -// PassManagerBuilder::populateLTOPassManager(), and make sure all LTO -// passes are initialized. -void LTOCodeGenerator::initializeLTOPasses() { - PassRegistry &R = *PassRegistry::getPassRegistry(); - - initializeInternalizeLegacyPassPass(R); - initializeIPSCCPLegacyPassPass(R); - initializeGlobalOptLegacyPassPass(R); - initializeConstantMergeLegacyPassPass(R); - initializeDAHPass(R); - initializeInstructionCombiningPassPass(R); - initializeSimpleInlinerPass(R); - initializePruneEHPass(R); - initializeGlobalDCELegacyPassPass(R); - initializeOpenMPOptLegacyPassPass(R); - initializeArgPromotionPass(R); - initializeJumpThreadingPass(R); - initializeSROALegacyPassPass(R); - initializeAttributorLegacyPassPass(R); - initializeAttributorCGSCCLegacyPassPass(R); - initializePostOrderFunctionAttrsLegacyPassPass(R); - initializeReversePostOrderFunctionAttrsLegacyPassPass(R); - initializeGlobalsAAWrapperPassPass(R); - initializeLegacyLICMPassPass(R); - initializeMergedLoadStoreMotionLegacyPassPass(R); - initializeGVNLegacyPassPass(R); - initializeMemCpyOptLegacyPassPass(R); - initializeDCELegacyPassPass(R); - initializeCFGSimplifyPassPass(R); +lto::Config LTOCodeGenerator::toConfig() const { + lto::Config Conf; + Conf.CGFileType = FileType; + Conf.CPU = MCpu; + Conf.MAttrs = MAttrs; + Conf.RelocModel = RelocModel; + Conf.Options = Options; + Conf.CodeModel = None; + Conf.StatsFile = LTOStatsFile; + Conf.OptLevel = OptLevel; + Conf.Freestanding = Freestanding; + Conf.PTO.LoopVectorization = OptLevel > 1; + Conf.PTO.SLPVectorization = OptLevel > 1; + Conf.DisableVerify = DisableVerify; + Conf.PreCodeGenPassesHook = [](legacy::PassManager &PM) { + PM.add(createObjCARCContractPass()); + }; + + return Conf; } void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) { @@ -300,6 +289,13 @@ return false; } + // If statistics were requested, save them to the specified file or + // print them out after codegen. + if (StatsFile) + PrintStatisticsJSON(StatsFile->os()); + else if (AreStatisticsEnabled()) + PrintStatistics(); + NativeObjectPath = Filename.c_str(); *Name = NativeObjectPath.c_str(); return true; @@ -565,31 +561,19 @@ // Write LTOPostLink flag for passes that require all the modules. MergedModule->addModuleFlag(Module::Error, "LTOPostLink", 1); - // Instantiate the pass manager to organize the passes. - legacy::PassManager passes; - // Add an appropriate DataLayout instance for this module... MergedModule->setDataLayout(TargetMach->createDataLayout()); - passes.add( - createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis())); - - Triple TargetTriple(TargetMach->getTargetTriple()); - PassManagerBuilder PMB; - PMB.LoopVectorize = true; - PMB.SLPVectorize = true; - PMB.Inliner = createFunctionInliningPass(); - PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple); - if (Freestanding) - PMB.LibraryInfo->disableAllFunctions(); - PMB.OptLevel = OptLevel; - PMB.VerifyInput = !DisableVerify; - PMB.VerifyOutput = !DisableVerify; - - PMB.populateLTOPassManager(passes); + lto::Config Conf = toConfig(); - // Run our queue of passes all at once now, efficiently. - passes.run(*MergedModule); + ModuleSummaryIndex CombinedIndex(false); + TargetMach = createTargetMachine(); + if (!opt(Conf, TargetMach.get(), 0, *MergedModule, /*IsThinLTO=*/false, + /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr, + /*CmdArgs*/ std::vector())) { + emitError("LTO middle-end optimizations failed"); + return false; + } return true; } @@ -602,20 +586,22 @@ // been called in optimize(), this call will return early. verifyMergedModuleOnce(); - 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. - preCodeGenPasses.add(createObjCARCContractPass()); - preCodeGenPasses.run(*MergedModule); + auto AddStream = + [&](size_t Task) -> std::unique_ptr { + return std::make_unique(Out[Task]); + }; // Re-externalize globals that may have been internalized to increase scope // for splitting restoreLinkageForExternals(); - splitCodeGen( - *MergedModule, Out, {}, [&]() { return createTargetMachine(); }, FileType, - ShouldRestoreGlobalsLinkage); + lto::Config Conf = toConfig(); + ModuleSummaryIndex CombinedIndex(false); + + Error Err = + backend(Conf, AddStream, Out.size(), *MergedModule, CombinedIndex); + assert(!Err && "unexpected code-generation failure"); + (void)Err; // If statistics were requested, save them to the specified file or // print them out after codegen. diff --git a/llvm/test/LTO/X86/disable-verify.ll b/llvm/test/LTO/X86/disable-verify.ll --- a/llvm/test/LTO/X86/disable-verify.ll +++ b/llvm/test/LTO/X86/disable-verify.ll @@ -7,7 +7,7 @@ ; -disable-verify should disable verification from the optimization pipeline. ; CHECK: Pass Arguments: -; CHECK-NOT: -verify +; CHECK-NOT: -verify {{.*}} -verify ; VERIFY: Pass Arguments: {{.*}} -verify {{.*}} -verify diff --git a/llvm/test/tools/lto/print-stats.ll b/llvm/test/tools/lto/print-stats.ll --- a/llvm/test/tools/lto/print-stats.ll +++ b/llvm/test/tools/lto/print-stats.ll @@ -5,5 +5,12 @@ target triple = "x86_64-apple-macosx10.8.0" +define i32 @test(i32 %a) { + %r = add i32 %a, 1 + %r.1 = add i32 1, %a + %r.2 = add i32 %r, %r.1 + ret i32 %r.2 +} + ; STATS: Statistics Collected ; NO_STATS-NOT: Statistics Collected