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 | PM.add(P: llvm::createLoopRotatePass()); |
52 | if (PollyInliner) { |
53 | PM.add(P: llvm::createPromoteMemoryToRegisterPass()); |
54 | PM.add(P: llvm::createCFGSimplificationPass()); |
55 | PM.add(P: llvm::createInstructionCombiningPass()); |
56 | PM.add(P: createBarrierNoopPass()); |
57 | } |
58 | PM.add(P: llvm::createInstructionCombiningPass()); |
59 | } |
60 | |
61 | /// Adapted from llvm::PassBuilder::buildInlinerPipeline |
62 | static ModuleInlinerWrapperPass |
63 | buildInlinePasses(llvm::OptimizationLevel Level) { |
64 | InlineParams IP = getInlineParams(Threshold: 200); |
65 | ModuleInlinerWrapperPass MIWP(IP); |
66 | |
67 | // Require the GlobalsAA analysis for the module so we can query it within |
68 | // the CGSCC pipeline. |
69 | MIWP.addModulePass(Pass: RequireAnalysisPass<GlobalsAA, Module>()); |
70 | // Invalidate AAManager so it can be recreated and pick up the newly available |
71 | // GlobalsAA. |
72 | MIWP.addModulePass( |
73 | Pass: createModuleToFunctionPassAdaptor(Pass: InvalidateAnalysisPass<AAManager>())); |
74 | |
75 | // Require the ProfileSummaryAnalysis for the module so we can query it within |
76 | // the inliner pass. |
77 | MIWP.addModulePass(Pass: RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); |
78 | |
79 | // Now begin the main postorder CGSCC pipeline. |
80 | // FIXME: The current CGSCC pipeline has its origins in the legacy pass |
81 | // manager and trying to emulate its precise behavior. Much of this doesn't |
82 | // make a lot of sense and we should revisit the core CGSCC structure. |
83 | CGSCCPassManager &MainCGPipeline = MIWP.getPM(); |
84 | |
85 | // Now deduce any function attributes based in the current code. |
86 | MainCGPipeline.addPass(Pass: PostOrderFunctionAttrsPass()); |
87 | |
88 | return MIWP; |
89 | } |
90 | |
91 | FunctionPassManager |
92 | polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM, |
93 | llvm::OptimizationLevel Level) { |
94 | FunctionPassManager FPM; |
95 | |
96 | bool UseMemSSA = true; |
97 | FPM.addPass(Pass: PromotePass()); |
98 | FPM.addPass(Pass: EarlyCSEPass(UseMemSSA)); |
99 | FPM.addPass(Pass: InstCombinePass()); |
100 | FPM.addPass(Pass: SimplifyCFGPass()); |
101 | FPM.addPass(Pass: TailCallElimPass()); |
102 | FPM.addPass(Pass: SimplifyCFGPass()); |
103 | FPM.addPass(Pass: ReassociatePass()); |
104 | { |
105 | LoopPassManager LPM; |
106 | LPM.addPass(Pass: LoopRotatePass(Level != OptimizationLevel::Oz)); |
107 | FPM.addPass(Pass: createFunctionToLoopPassAdaptor<LoopPassManager>( |
108 | Pass: std::move(LPM), /*UseMemorySSA=*/false, |
109 | /*UseBlockFrequencyInfo=*/false)); |
110 | } |
111 | if (PollyInliner) { |
112 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM))); |
113 | MPM.addPass(Pass: buildInlinePasses(Level)); |
114 | FPM = FunctionPassManager(); |
115 | |
116 | FPM.addPass(Pass: PromotePass()); |
117 | FPM.addPass(Pass: SimplifyCFGPass()); |
118 | FPM.addPass(Pass: InstCombinePass()); |
119 | } |
120 | FPM.addPass(Pass: InstCombinePass()); |
121 | { |
122 | LoopPassManager LPM; |
123 | LPM.addPass(Pass: IndVarSimplifyPass()); |
124 | FPM.addPass(Pass: createFunctionToLoopPassAdaptor<LoopPassManager>( |
125 | Pass: std::move(LPM), /*UseMemorySSA=*/false, |
126 | /*UseBlockFrequencyInfo=*/true)); |
127 | } |
128 | |
129 | return FPM; |
130 | } |
131 | |
132 | namespace { |
133 | class PollyCanonicalize final : public ModulePass { |
134 | PollyCanonicalize(const PollyCanonicalize &) = delete; |
135 | const PollyCanonicalize &operator=(const PollyCanonicalize &) = delete; |
136 | |
137 | public: |
138 | static char ID; |
139 | |
140 | explicit PollyCanonicalize() : ModulePass(ID) {} |
141 | ~PollyCanonicalize(); |
142 | |
143 | /// @name FunctionPass interface. |
144 | //@{ |
145 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
146 | void releaseMemory() override; |
147 | bool runOnModule(Module &M) override; |
148 | void print(raw_ostream &OS, const Module *) const override; |
149 | //@} |
150 | }; |
151 | } // namespace |
152 | |
153 | PollyCanonicalize::~PollyCanonicalize() {} |
154 | |
155 | void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {} |
156 | |
157 | void PollyCanonicalize::releaseMemory() {} |
158 | |
159 | bool PollyCanonicalize::runOnModule(Module &M) { |
160 | legacy::PassManager PM; |
161 | registerCanonicalicationPasses(PM); |
162 | PM.run(M); |
163 | |
164 | return true; |
165 | } |
166 | |
167 | void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {} |
168 | |
169 | char PollyCanonicalize::ID = 0; |
170 | |
171 | Pass *polly::createPollyCanonicalizePass() { return new PollyCanonicalize(); } |
172 | |
173 | INITIALIZE_PASS_BEGIN(PollyCanonicalize, "polly-canonicalize" , |
174 | "Polly - Run canonicalization passes" , false, false) |
175 | INITIALIZE_PASS_END(PollyCanonicalize, "polly-canonicalize" , |
176 | "Polly - Run canonicalization passes" , false, false) |
177 | |