1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[PM] Flesh out the new pass manager LTO pipeline.

Differential Revision:  https://reviews.llvm.org/D28996

llvm-svn: 292863
This commit is contained in:
Davide Italiano 2017-01-24 00:57:39 +00:00
parent ddd0879068
commit ffa8336285
3 changed files with 263 additions and 12 deletions

View File

@ -547,13 +547,166 @@ ModulePassManager PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
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());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM)));
// 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());
// 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;
}

View File

@ -383,13 +383,6 @@
; CHECK-O0: Starting llvm::Module pass manager run
; CHECK-O0-NEXT: Finished llvm::Module pass manager run
; RUN: opt -disable-output -disable-verify -debug-pass-manager \
; RUN: -passes='lto<O2>' %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

View File

@ -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<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=CHECK-O
; RUN: opt -disable-verify -debug-pass-manager \
; RUN: -passes='lto<O2>' -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<O3>' -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<Os>' -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<Oz>' -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<llvm::Module
; CHECK-O-NEXT: Starting llvm::Module pass manager run.
; CHECK-O-NEXT: Running pass: GlobalDCEPass
; CHECK-O-NEXT: Running pass: ForceFunctionAttrsPass
; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass
; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
; CHECK-O2-NEXT: PGOIndirectCallPromotion
; CHECK-O2-NEXT: Running pass: IPSCCPPass
; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<llvm::PostOrderFunctionAttrsPass>
; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::Module>
; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy<llvm::AnalysisManager<llvm::Function>, llvm::Module>
; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis
; CHECK-O-NEXT: Running analysis: FunctionAnalysisManagerCGSCCProxy
; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<llvm::AnalysisManager<llvm::Module>, 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<llvm::PromotePass>
; 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<llvm::InstCombinePass>
; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<llvm::InlinerPass>
; CHECK-O2-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis
; CHECK-O2-NEXT: Running pass: GlobalOptPass
; CHECK-O2-NEXT: Running pass: GlobalDCEPass
; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<llvm::PassManager<llvm::Function> >
; 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<llvm::PostOrderFunctionAttrsPass>
; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<llvm::PassManager<llvm::Function> >
; 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<llvm::SimplifyCFGPass>
; 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
}