Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -547,13 +547,166 @@ assert(Level != O0 && "Must request optimizations for the default pipeline!"); ModulePassManager MPM(DebugLogging); - // FIXME: Finish fleshing this out to match the legacy LTO pipelines. - FunctionPassManager LateFPM(DebugLogging); - LateFPM.addPass(InstCombinePass()); - LateFPM.addPass(SimplifyCFGPass()); + // Remove unused virtual tables to improve the quality of code generated by + // whole-program devirtualization and bitset lowering. + MPM.addPass(GlobalDCEPass()); + + // Force any function attributes we want the rest of the pipeline to observe. + MPM.addPass(ForceFunctionAttrsPass()); + + // Do basic inference of function attributes from known properties of system + // libraries and other oracles. + MPM.addPass(InferFunctionAttrsPass()); + + if (Level > 1) { + // Indirect call promotion. This should promote all the targets that are + // left by the earlier promotion pass that promotes intra-module targets. + // This two-step promotion is to save the compile time. For LTO, it should + // produce the same result as if we only do promotion here. + MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */)); + + // Propagate constants at call sites into the functions they call. This + // opens opportunities for globalopt (and inlining) by substituting function + // pointers passed as arguments to direct uses of functions. + MPM.addPass(IPSCCPPass()); + } + + // Now deduce any function attributes based in the current code. + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( + PostOrderFunctionAttrsPass())); + + // Do RPO function attribute inference across the module to forward-propagate + // attributes where applicable. + // FIXME: Is this really an optimization rather than a canonicalization? + MPM.addPass(ReversePostOrderFunctionAttrsPass()); + + // Use inragne annotations on GEP indices to split globals where beneficial. + MPM.addPass(GlobalSplitPass()); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM))); + // Run whole program optimization of virtual call when the list of callees + // is fixed. + MPM.addPass(WholeProgramDevirtPass()); + + // Stop here at -O1. + if (Level == 1) + return MPM; + + // Optimize globals to try and fold them into constants. + MPM.addPass(GlobalOptPass()); + + // Promote any localized globals to SSA registers. + MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass())); + + // Linking modules together can lead to duplicate global constant, only + // keep one copy of each constant. + MPM.addPass(ConstantMergePass()); + + // Remove unused arguments from functions. + MPM.addPass(DeadArgumentEliminationPass()); + + // Reduce the code after globalopt and ipsccp. Both can open up significant + // simplification opportunities, and both can propagate functions through + // function pointers. When this happens, we often have to resolve varargs + // calls, etc, so let instcombine do this. + // FIXME: add peephole extensions here as the legacy PM does. + MPM.addPass(createModuleToFunctionPassAdaptor(InstCombinePass())); + + // Note: historically, the PruneEH pass was run first to deduce nounwind and + // generally clean up exception handling overhead. It isn't clear this is + // valuable as the inliner doesn't currently care whether it is inlining an + // invoke or a call. + // Run the inliner now. + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(InlinerPass())); + + // Optimize globals again after we ran the inliner. + MPM.addPass(GlobalOptPass()); + + // Garbage collect dead functions. + // FIXME: Add ArgumentPromotion pass after once it's ported. + MPM.addPass(GlobalDCEPass()); + + FunctionPassManager FPM(DebugLogging); + + // The IPO Passes may leave cruft around. Clean up after them. + // FIXME: add peephole extensions here as the legacy PM does. + FPM.addPass(InstCombinePass()); + FPM.addPass(JumpThreadingPass()); + + // Break up allocas + FPM.addPass(SROA()); + + // Run a few AA driver optimizations here and now to cleanup the code. + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( + PostOrderFunctionAttrsPass())); + // FIXME: here we run IP alias analysis in the legacy PM. + + FunctionPassManager MainFPM; + + // FIXME: once we fix LoopPass Manager, add LICM here. + // FIXME: once we provide support for enabling MLSM, add it here. + // FIXME: once we provide support for enabling NewGVN, add it here. + MainFPM.addPass(GVN()); + + // Remove dead memcpy()'s. + MainFPM.addPass(MemCpyOptPass()); + + // Nuke dead stores. + MainFPM.addPass(DSEPass()); + + // FIXME: at this point, we run a bunch of loop passes: + // indVarSimplify, loopDeletion, loopInterchange, loopUnrool, + // loopVectorize. Enable them once the remaining issue with LPM + // are sorted out. + + MainFPM.addPass(InstCombinePass()); + MainFPM.addPass(SimplifyCFGPass()); + MainFPM.addPass(SCCPPass()); + MainFPM.addPass(InstCombinePass()); + MainFPM.addPass(BDCEPass()); + + // FIXME: We may want to run SLPVectorizer here. + // After vectorization, assume intrinsics may tell us more + // about pointer alignments. +#if 0 + MainFPM.add(AlignmentFromAssumptionsPass()); +#endif + + // FIXME: Conditionally run LoadCombine here, after it's ported + // (in case we still have this pass, given its questionable usefulness). + + // FIXME: add peephole extensions to the PM here. + MainFPM.addPass(InstCombinePass()); + MainFPM.addPass(JumpThreadingPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM))); + + // Create a function that performs CFI checks for cross-DSO calls with + // targets in the current module. + MPM.addPass(CrossDSOCFIPass()); + + // Lower type metadata and the type.test intrinsic. This pass supports + // clang's control flow integrity mechanisms (-fsanitize=cfi*) and needs + // to be run at link time if CFI is enabled. This pass does nothing if + // CFI is disabled. + // Enable once we add support for the summary in the new PM. +#if 0 + MPM.addPass(LowerTypeTestsPass(Summary ? LowerTypeTestsSummaryAction::Export : + LowerTypeTestsSummaryAction::None, + Summary)); +#endif + + // Add late LTO optimization passes. + // Delete basic blocks, which optimization passes may have killed. + MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass())); + + // Drop bodies of available eternally objects to improve GlobalDCE. + MPM.addPass(EliminateAvailableExternallyPass()); + + // Now that we have optimized the program, discard unreachable functions. + MPM.addPass(GlobalDCEPass()); + // FIXME: Enable MergeFuncs, conditionally, after ported, maybe. return MPM; } Index: test/Other/new-pass-manager.ll =================================================================== --- test/Other/new-pass-manager.ll +++ test/Other/new-pass-manager.ll @@ -384,13 +384,6 @@ ; CHECK-O0-NEXT: Finished llvm::Module pass manager run ; RUN: opt -disable-output -disable-verify -debug-pass-manager \ -; RUN: -passes='lto' %s 2>&1 \ -; RUN: | FileCheck %s --check-prefix=CHECK-LTO-O2 -; CHECK-LTO-O2: Starting llvm::Module pass manager run -; CHECK-LTO-O2: Running pass: InstCombinePass -; CHECK-LTO-O2: Running pass: SimplifyCFGPass - -; RUN: opt -disable-output -disable-verify -debug-pass-manager \ ; RUN: -passes='repeat<3>(no-op-module)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-REPEAT-MODULE-PASS ; CHECK-REPEAT-MODULE-PASS: Starting llvm::Module pass manager run Index: test/Other/new-pm-lto-defaults.ll =================================================================== --- /dev/null +++ test/Other/new-pm-lto-defaults.ll @@ -0,0 +1,105 @@ +; Basic test for the new LTO pipeline. +; For now the only difference is between -O1 and everything else, so +; -O2, -O3, -Os, -Oz are the same. + +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes='lto' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes='lto' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes='lto' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes='lto' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 +; RUN: opt -disable-verify -debug-pass-manager \ +; RUN: -passes='lto' -S %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 + +; CHECK-O: Starting llvm::Module pass manager run. +; CHECK-O-NEXT: Running pass: PassManager +; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy, llvm::Module> +; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy, llvm::Module> +; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis +; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy +; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy, llvm::LazyCallGraph::SCC> +; CHECK-O-NEXT: Running analysis: AAManager +; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: ReversePostOrderFunctionAttrsPass +; CHECK-O-NEXT: Running analysis: CallGraphAnalysis +; CHECK-O-NEXT: Invalidating analysis: CallGraphAnalysis +; CHECK-O-NEXT: Running pass: GlobalSplitPass +; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass +; CHECK-O2-NEXT: Running pass: GlobalOptPass +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-O2-NEXT: Running analysis: DominatorTreeAnalysis +; CHECK-O2-NEXT: Running analysis: AssumptionAnalysis +; CHECK-O2-NEXT: Running pass: ConstantMergePass +; CHECK-O2-NEXT: Running pass: DeadArgumentEliminationPass +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-O2-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis +; CHECK-O2-NEXT: Running pass: GlobalOptPass +; CHECK-O2-NEXT: Running pass: GlobalDCEPass +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor > +; CHECK-O2-NEXT: Starting llvm::Function pass manager run. +; CHECK-O2-NEXT: Running pass: InstCombinePass +; CHECK-O2-NEXT: Running pass: JumpThreadingPass +; CHECK-O2-NEXT: Running analysis: LazyValueAnalysis +; CHECK-O2-NEXT: Invalidating analysis: LazyValueAnalysis +; CHECK-O2-NEXT: Running pass: SROA on foo +; CHECK-O2-NEXT: Finished llvm::Function pass manager run. +; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor > +; CHECK-O2-NEXT: Running analysis: MemoryDependenceAnalysis +; CHECK-O2-NEXT: Running analysis: TargetIRAnalysis +; CHECK-O2-NEXT: Running analysis: DemandedBitsAnalysis +; CHECK-O2-NEXT: Running analysis: LazyValueAnalysis +; CHECK-O2-NEXT: Invalidating analysis: LazyValueAnalysis +; CHECK-O2-NEXT: Running pass: CrossDSOCFIPass +; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-O2-NEXT: Running pass: EliminateAvailableExternallyPass +; CHECK-O2-NEXT: Running pass: GlobalDCEPass +; CHECK-O-NEXT: Finished llvm::Module pass manager run. +; CHECK-O-NEXT: Running pass: PrintModulePass + +; Make sure we get the IR back out without changes when we print the module. +; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr { +; CHECK-O-NEXT: entry: +; CHECK-O-NEXT: br label %loop +; CHECK-O: loop: +; CHECK-O-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] +; CHECK-O-NEXT: %iv.next = add i32 %iv, 1 +; CHECK-O-NEXT: tail call void @bar() +; CHECK-O-NEXT: %cmp = icmp eq i32 %iv, %n +; CHECK-O-NEXT: br i1 %cmp, label %exit, label %loop +; CHECK-O: exit: +; CHECK-O-NEXT: ret void +; CHECK-O-NEXT: } +; +; CHECK-O-NEXT: Finished llvm::Module pass manager run. + +declare void @bar() local_unnamed_addr + +define void @foo(i32 %n) local_unnamed_addr { +entry: + br label %loop +loop: + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %iv.next = add i32 %iv, 1 + tail call void @bar() + %cmp = icmp eq i32 %iv, %n + br i1 %cmp, label %exit, label %loop +exit: + ret void +}