xref: /llvm-project/polly/lib/Transform/Canonicalization.cpp (revision 8d6b451b452f5b0568297b4638530171215716eb)
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 
registerCanonicalicationPasses(llvm::legacy::PassManagerBase & PM)42 void polly::registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM) {
43   bool UseMemSSA = true;
44   PM.add(llvm::createPromoteMemoryToRegisterPass());
45   PM.add(llvm::createEarlyCSEPass(UseMemSSA));
46   PM.add(llvm::createInstructionCombiningPass());
47   PM.add(llvm::createCFGSimplificationPass());
48   PM.add(llvm::createTailCallEliminationPass());
49   PM.add(llvm::createCFGSimplificationPass());
50   PM.add(llvm::createReassociatePass());
51   if (PollyInliner) {
52     PM.add(llvm::createPromoteMemoryToRegisterPass());
53     PM.add(llvm::createCFGSimplificationPass());
54     PM.add(llvm::createInstructionCombiningPass());
55     PM.add(createBarrierNoopPass());
56   }
57   PM.add(llvm::createInstructionCombiningPass());
58 }
59 
60 /// Adapted from llvm::PassBuilder::buildInlinerPipeline
61 static ModuleInlinerWrapperPass
buildInlinePasses(llvm::OptimizationLevel Level)62 buildInlinePasses(llvm::OptimizationLevel Level) {
63   InlineParams IP = getInlineParams(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(RequireAnalysisPass<GlobalsAA, Module>());
69   // Invalidate AAManager so it can be recreated and pick up the newly available
70   // GlobalsAA.
71   MIWP.addModulePass(
72       createModuleToFunctionPassAdaptor(InvalidateAnalysisPass<AAManager>()));
73 
74   // Require the ProfileSummaryAnalysis for the module so we can query it within
75   // the inliner pass.
76   MIWP.addModulePass(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(PostOrderFunctionAttrsPass());
86 
87   return MIWP;
88 }
89 
90 FunctionPassManager
buildCanonicalicationPassesForNPM(llvm::ModulePassManager & MPM,llvm::OptimizationLevel Level)91 polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM,
92                                          llvm::OptimizationLevel Level) {
93   FunctionPassManager FPM;
94 
95   bool UseMemSSA = true;
96   FPM.addPass(PromotePass());
97   FPM.addPass(EarlyCSEPass(UseMemSSA));
98   FPM.addPass(InstCombinePass());
99   FPM.addPass(SimplifyCFGPass());
100   FPM.addPass(TailCallElimPass());
101   FPM.addPass(SimplifyCFGPass());
102   FPM.addPass(ReassociatePass());
103   {
104     LoopPassManager LPM;
105     LPM.addPass(LoopRotatePass(Level != OptimizationLevel::Oz));
106     FPM.addPass(createFunctionToLoopPassAdaptor<LoopPassManager>(
107         std::move(LPM), /*UseMemorySSA=*/false,
108         /*UseBlockFrequencyInfo=*/false));
109   }
110   if (PollyInliner) {
111     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
112     MPM.addPass(buildInlinePasses(Level));
113     FPM = FunctionPassManager();
114 
115     FPM.addPass(PromotePass());
116     FPM.addPass(SimplifyCFGPass());
117     FPM.addPass(InstCombinePass());
118   }
119   FPM.addPass(InstCombinePass());
120   {
121     LoopPassManager LPM;
122     LPM.addPass(IndVarSimplifyPass());
123     FPM.addPass(createFunctionToLoopPassAdaptor<LoopPassManager>(
124         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 
PollyCanonicalize()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 
~PollyCanonicalize()152 PollyCanonicalize::~PollyCanonicalize() {}
153 
getAnalysisUsage(AnalysisUsage & AU) const154 void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {}
155 
releaseMemory()156 void PollyCanonicalize::releaseMemory() {}
157 
runOnModule(Module & M)158 bool PollyCanonicalize::runOnModule(Module &M) {
159   legacy::PassManager PM;
160   registerCanonicalicationPasses(PM);
161   PM.run(M);
162 
163   return true;
164 }
165 
print(raw_ostream & OS,const Module *) const166 void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {}
167 
168 char PollyCanonicalize::ID = 0;
169 
createPollyCanonicalizePass()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