1 | //===---- Canonicalization.cpp - Run canonicalization passes --------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Run the set of default canonicalization passes. |
10 | // |
11 | // This pass is mainly used for debugging. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "polly/Canonicalization.h" |
16 | #include "polly/LinkAllPasses.h" |
17 | #include "polly/Options.h" |
18 | #include "llvm/Analysis/GlobalsModRef.h" |
19 | #include "llvm/Analysis/ProfileSummaryInfo.h" |
20 | #include "llvm/IR/LegacyPassManager.h" |
21 | #include "llvm/Transforms/IPO.h" |
22 | #include "llvm/Transforms/IPO/FunctionAttrs.h" |
23 | #include "llvm/Transforms/InstCombine/InstCombine.h" |
24 | #include "llvm/Transforms/Scalar.h" |
25 | #include "llvm/Transforms/Scalar/EarlyCSE.h" |
26 | #include "llvm/Transforms/Scalar/IndVarSimplify.h" |
27 | #include "llvm/Transforms/Scalar/LoopRotation.h" |
28 | #include "llvm/Transforms/Scalar/Reassociate.h" |
29 | #include "llvm/Transforms/Scalar/SimplifyCFG.h" |
30 | #include "llvm/Transforms/Scalar/TailRecursionElimination.h" |
31 | #include "llvm/Transforms/Utils.h" |
32 | #include "llvm/Transforms/Utils/Mem2Reg.h" |
33 | |
34 | using namespace llvm; |
35 | using namespace polly; |
36 | |
37 | static cl::opt<bool> |
38 | PollyInliner("polly-run-inliner" , |
39 | cl::desc("Run an early inliner pass before Polly" ), cl::Hidden, |
40 | cl::cat(PollyCategory)); |
41 | |
42 | void polly::registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM) { |
43 | bool UseMemSSA = true; |
44 | PM.add(P: llvm::createPromoteMemoryToRegisterPass()); |
45 | PM.add(P: llvm::createEarlyCSEPass(UseMemorySSA: UseMemSSA)); |
46 | PM.add(P: llvm::createInstructionCombiningPass()); |
47 | PM.add(P: llvm::createCFGSimplificationPass()); |
48 | PM.add(P: llvm::createTailCallEliminationPass()); |
49 | PM.add(P: llvm::createCFGSimplificationPass()); |
50 | PM.add(P: llvm::createReassociatePass()); |
51 | if (PollyInliner) { |
52 | PM.add(P: llvm::createPromoteMemoryToRegisterPass()); |
53 | PM.add(P: llvm::createCFGSimplificationPass()); |
54 | PM.add(P: llvm::createInstructionCombiningPass()); |
55 | PM.add(P: createBarrierNoopPass()); |
56 | } |
57 | PM.add(P: llvm::createInstructionCombiningPass()); |
58 | } |
59 | |
60 | /// Adapted from llvm::PassBuilder::buildInlinerPipeline |
61 | static ModuleInlinerWrapperPass |
62 | buildInlinePasses(llvm::OptimizationLevel Level) { |
63 | InlineParams IP = getInlineParams(Threshold: 200); |
64 | ModuleInlinerWrapperPass MIWP(IP); |
65 | |
66 | // Require the GlobalsAA analysis for the module so we can query it within |
67 | // the CGSCC pipeline. |
68 | MIWP.addModulePass(Pass: RequireAnalysisPass<GlobalsAA, Module>()); |
69 | // Invalidate AAManager so it can be recreated and pick up the newly available |
70 | // GlobalsAA. |
71 | MIWP.addModulePass( |
72 | Pass: createModuleToFunctionPassAdaptor(Pass: InvalidateAnalysisPass<AAManager>())); |
73 | |
74 | // Require the ProfileSummaryAnalysis for the module so we can query it within |
75 | // the inliner pass. |
76 | MIWP.addModulePass(Pass: RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); |
77 | |
78 | // Now begin the main postorder CGSCC pipeline. |
79 | // FIXME: The current CGSCC pipeline has its origins in the legacy pass |
80 | // manager and trying to emulate its precise behavior. Much of this doesn't |
81 | // make a lot of sense and we should revisit the core CGSCC structure. |
82 | CGSCCPassManager &MainCGPipeline = MIWP.getPM(); |
83 | |
84 | // Now deduce any function attributes based in the current code. |
85 | MainCGPipeline.addPass(Pass: PostOrderFunctionAttrsPass()); |
86 | |
87 | return MIWP; |
88 | } |
89 | |
90 | FunctionPassManager |
91 | polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM, |
92 | llvm::OptimizationLevel Level) { |
93 | FunctionPassManager FPM; |
94 | |
95 | bool UseMemSSA = true; |
96 | FPM.addPass(Pass: PromotePass()); |
97 | FPM.addPass(Pass: EarlyCSEPass(UseMemSSA)); |
98 | FPM.addPass(Pass: InstCombinePass()); |
99 | FPM.addPass(Pass: SimplifyCFGPass()); |
100 | FPM.addPass(Pass: TailCallElimPass()); |
101 | FPM.addPass(Pass: SimplifyCFGPass()); |
102 | FPM.addPass(Pass: ReassociatePass()); |
103 | { |
104 | LoopPassManager LPM; |
105 | LPM.addPass(Pass: LoopRotatePass(Level != OptimizationLevel::Oz)); |
106 | FPM.addPass(Pass: createFunctionToLoopPassAdaptor<LoopPassManager>( |
107 | Pass: std::move(LPM), /*UseMemorySSA=*/false, |
108 | /*UseBlockFrequencyInfo=*/false)); |
109 | } |
110 | if (PollyInliner) { |
111 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM))); |
112 | MPM.addPass(Pass: buildInlinePasses(Level)); |
113 | FPM = FunctionPassManager(); |
114 | |
115 | FPM.addPass(Pass: PromotePass()); |
116 | FPM.addPass(Pass: SimplifyCFGPass()); |
117 | FPM.addPass(Pass: InstCombinePass()); |
118 | } |
119 | FPM.addPass(Pass: InstCombinePass()); |
120 | { |
121 | LoopPassManager LPM; |
122 | LPM.addPass(Pass: IndVarSimplifyPass()); |
123 | FPM.addPass(Pass: createFunctionToLoopPassAdaptor<LoopPassManager>( |
124 | Pass: std::move(LPM), /*UseMemorySSA=*/false, |
125 | /*UseBlockFrequencyInfo=*/true)); |
126 | } |
127 | |
128 | return FPM; |
129 | } |
130 | |
131 | namespace { |
132 | class PollyCanonicalize final : public ModulePass { |
133 | PollyCanonicalize(const PollyCanonicalize &) = delete; |
134 | const PollyCanonicalize &operator=(const PollyCanonicalize &) = delete; |
135 | |
136 | public: |
137 | static char ID; |
138 | |
139 | explicit PollyCanonicalize() : ModulePass(ID) {} |
140 | ~PollyCanonicalize(); |
141 | |
142 | /// @name FunctionPass interface. |
143 | //@{ |
144 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
145 | void releaseMemory() override; |
146 | bool runOnModule(Module &M) override; |
147 | void print(raw_ostream &OS, const Module *) const override; |
148 | //@} |
149 | }; |
150 | } // namespace |
151 | |
152 | PollyCanonicalize::~PollyCanonicalize() {} |
153 | |
154 | void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {} |
155 | |
156 | void PollyCanonicalize::releaseMemory() {} |
157 | |
158 | bool PollyCanonicalize::runOnModule(Module &M) { |
159 | legacy::PassManager PM; |
160 | registerCanonicalicationPasses(PM); |
161 | PM.run(M); |
162 | |
163 | return true; |
164 | } |
165 | |
166 | void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {} |
167 | |
168 | char PollyCanonicalize::ID = 0; |
169 | |
170 | Pass *polly::createPollyCanonicalizePass() { return new PollyCanonicalize(); } |
171 | |
172 | INITIALIZE_PASS_BEGIN(PollyCanonicalize, "polly-canonicalize" , |
173 | "Polly - Run canonicalization passes" , false, false) |
174 | INITIALIZE_PASS_END(PollyCanonicalize, "polly-canonicalize" , |
175 | "Polly - Run canonicalization passes" , false, false) |
176 | |