/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/include/polly/ScopPass.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--------- ScopPass.h - Pass for Static Control Parts --------*-C++ -*-===// |
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 | | // This file defines the ScopPass class. ScopPasses are just RegionPasses, |
10 | | // except they operate on Polly IR (Scop and ScopStmt) built by ScopInfo Pass. |
11 | | // Because they operate on Polly IR, not the LLVM IR, ScopPasses are not allowed |
12 | | // to modify the LLVM IR. Due to this limitation, the ScopPass class takes |
13 | | // care of declaring that no LLVM passes are invalidated. |
14 | | // |
15 | | //===----------------------------------------------------------------------===// |
16 | | |
17 | | #ifndef POLLY_SCOP_PASS_H |
18 | | #define POLLY_SCOP_PASS_H |
19 | | |
20 | | #include "polly/ScopInfo.h" |
21 | | #include "llvm/ADT/PriorityWorklist.h" |
22 | | #include "llvm/Analysis/RegionPass.h" |
23 | | #include "llvm/IR/PassManager.h" |
24 | | |
25 | | using namespace llvm; |
26 | | |
27 | | namespace polly { |
28 | | class Scop; |
29 | | class SPMUpdater; |
30 | | struct ScopStandardAnalysisResults; |
31 | | |
32 | | using ScopAnalysisManager = |
33 | | AnalysisManager<Scop, ScopStandardAnalysisResults &>; |
34 | | using ScopAnalysisManagerFunctionProxy = |
35 | | InnerAnalysisManagerProxy<ScopAnalysisManager, Function>; |
36 | | using FunctionAnalysisManagerScopProxy = |
37 | | OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop, |
38 | | ScopStandardAnalysisResults &>; |
39 | | } // namespace polly |
40 | | |
41 | | namespace llvm { |
42 | | using polly::Scop; |
43 | | using polly::ScopAnalysisManager; |
44 | | using polly::ScopAnalysisManagerFunctionProxy; |
45 | | using polly::ScopInfo; |
46 | | using polly::ScopStandardAnalysisResults; |
47 | | using polly::SPMUpdater; |
48 | | |
49 | | template <> |
50 | | class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result { |
51 | | public: |
52 | | explicit Result(ScopAnalysisManager &InnerAM, ScopInfo &SI) |
53 | 0 | : InnerAM(&InnerAM), SI(&SI) {} |
54 | 0 | Result(Result &&R) : InnerAM(std::move(R.InnerAM)), SI(R.SI) { |
55 | 0 | R.InnerAM = nullptr; |
56 | 0 | } |
57 | 0 | Result &operator=(Result &&RHS) { |
58 | 0 | InnerAM = RHS.InnerAM; |
59 | 0 | SI = RHS.SI; |
60 | 0 | RHS.InnerAM = nullptr; |
61 | 0 | return *this; |
62 | 0 | } |
63 | 0 | ~Result() { |
64 | 0 | if (!InnerAM) |
65 | 0 | return; |
66 | 0 | InnerAM->clear(); |
67 | 0 | } |
68 | | |
69 | 0 | ScopAnalysisManager &getManager() { return *InnerAM; } |
70 | | |
71 | | bool invalidate(Function &F, const PreservedAnalyses &PA, |
72 | | FunctionAnalysisManager::Invalidator &Inv); |
73 | | |
74 | | private: |
75 | | ScopAnalysisManager *InnerAM; |
76 | | ScopInfo *SI; |
77 | | }; |
78 | | |
79 | | // A partial specialization of the require analysis template pass to handle |
80 | | // extra parameters |
81 | | template <typename AnalysisT> |
82 | | struct RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager, |
83 | | ScopStandardAnalysisResults &, SPMUpdater &> |
84 | | : PassInfoMixin< |
85 | | RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager, |
86 | | ScopStandardAnalysisResults &, SPMUpdater &>> { |
87 | | PreservedAnalyses run(Scop &L, ScopAnalysisManager &AM, |
88 | 0 | ScopStandardAnalysisResults &AR, SPMUpdater &) { |
89 | 0 | (void)AM.template getResult<AnalysisT>(L, AR); |
90 | 0 | return PreservedAnalyses::all(); |
91 | 0 | } Unexecuted instantiation: llvm::RequireAnalysisPass<polly::IslAstAnalysis, polly::Scop, llvm::AnalysisManager<polly::Scop, polly::ScopStandardAnalysisResults&>, polly::ScopStandardAnalysisResults&, polly::SPMUpdater&>::run(polly::Scop&, llvm::AnalysisManager<polly::Scop, polly::ScopStandardAnalysisResults&>&, polly::ScopStandardAnalysisResults&, polly::SPMUpdater&) Unexecuted instantiation: llvm::RequireAnalysisPass<polly::DependenceAnalysis, polly::Scop, llvm::AnalysisManager<polly::Scop, polly::ScopStandardAnalysisResults&>, polly::ScopStandardAnalysisResults&, polly::SPMUpdater&>::run(polly::Scop&, llvm::AnalysisManager<polly::Scop, polly::ScopStandardAnalysisResults&>&, polly::ScopStandardAnalysisResults&, polly::SPMUpdater&) |
92 | | }; |
93 | | |
94 | | template <> |
95 | | InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result |
96 | | InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run( |
97 | | Function &F, FunctionAnalysisManager &FAM); |
98 | | |
99 | | template <> |
100 | | PreservedAnalyses |
101 | | PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &, |
102 | | SPMUpdater &>::run(Scop &InitialS, ScopAnalysisManager &AM, |
103 | | ScopStandardAnalysisResults &, SPMUpdater &); |
104 | | extern template class PassManager<Scop, ScopAnalysisManager, |
105 | | ScopStandardAnalysisResults &, SPMUpdater &>; |
106 | | extern template class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>; |
107 | | extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop, |
108 | | ScopStandardAnalysisResults &>; |
109 | | } // namespace llvm |
110 | | |
111 | | namespace polly { |
112 | | |
113 | | template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs> |
114 | | class OwningInnerAnalysisManagerProxy |
115 | | : public InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT> { |
116 | | public: |
117 | | OwningInnerAnalysisManagerProxy() |
118 | 1.24k | : InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>(InnerAM) {} |
119 | | using Result = typename InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT, |
120 | | ExtraArgTs...>::Result; |
121 | | Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM, |
122 | | ExtraArgTs...) { |
123 | | return Result(InnerAM); |
124 | | } |
125 | | |
126 | 3.74k | AnalysisManagerT &getManager() { return InnerAM; } |
127 | | |
128 | | private: |
129 | | AnalysisManagerT InnerAM; |
130 | | }; |
131 | | |
132 | | template <> |
133 | | OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result |
134 | | OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run( |
135 | | Function &F, FunctionAnalysisManager &FAM); |
136 | | extern template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager, |
137 | | Function>; |
138 | | |
139 | | using OwningScopAnalysisManagerFunctionProxy = |
140 | | OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>; |
141 | | using ScopPassManager = |
142 | | PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &, |
143 | | SPMUpdater &>; |
144 | | |
145 | | /// ScopPass - This class adapts the RegionPass interface to allow convenient |
146 | | /// creation of passes that operate on the Polly IR. Instead of overriding |
147 | | /// runOnRegion, subclasses override runOnScop. |
148 | | class ScopPass : public RegionPass { |
149 | | Scop *S; |
150 | | |
151 | | protected: |
152 | 1.73k | explicit ScopPass(char &ID) : RegionPass(ID), S(0) {} |
153 | | |
154 | | /// runOnScop - This method must be overloaded to perform the |
155 | | /// desired Polyhedral transformation or analysis. |
156 | | /// |
157 | | virtual bool runOnScop(Scop &S) = 0; |
158 | | |
159 | | /// Print method for SCoPs. |
160 | 27 | virtual void printScop(raw_ostream &OS, Scop &S) const {} |
161 | | |
162 | | /// getAnalysisUsage - Subclasses that override getAnalysisUsage |
163 | | /// must call this. |
164 | | /// |
165 | | virtual void getAnalysisUsage(AnalysisUsage &AU) const override; |
166 | | |
167 | | private: |
168 | | bool runOnRegion(Region *R, RGPassManager &RGM) override; |
169 | | void print(raw_ostream &OS, const Module *) const override; |
170 | | }; |
171 | | |
172 | | struct ScopStandardAnalysisResults { |
173 | | DominatorTree &DT; |
174 | | ScopInfo &SI; |
175 | | ScalarEvolution &SE; |
176 | | LoopInfo &LI; |
177 | | RegionInfo &RI; |
178 | | }; |
179 | | |
180 | | class SPMUpdater { |
181 | | public: |
182 | | SPMUpdater(SmallPriorityWorklist<Region *, 4> &Worklist, |
183 | | ScopAnalysisManager &SAM) |
184 | 0 | : InvalidateCurrentScop(false), Worklist(Worklist), SAM(SAM) {} |
185 | | |
186 | 0 | bool invalidateCurrentScop() const { return InvalidateCurrentScop; } |
187 | | |
188 | 0 | void invalidateScop(Scop &S) { |
189 | 0 | if (&S == CurrentScop) |
190 | 0 | InvalidateCurrentScop = true; |
191 | 0 |
|
192 | 0 | Worklist.erase(&S.getRegion()); |
193 | 0 | SAM.clear(S, S.getName()); |
194 | 0 | } |
195 | | |
196 | | private: |
197 | | Scop *CurrentScop; |
198 | | bool InvalidateCurrentScop; |
199 | | SmallPriorityWorklist<Region *, 4> &Worklist; |
200 | | ScopAnalysisManager &SAM; |
201 | | template <typename ScopPassT> friend class FunctionToScopPassAdaptor; |
202 | | }; |
203 | | |
204 | | template <typename ScopPassT> |
205 | | class FunctionToScopPassAdaptor |
206 | | : public PassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> { |
207 | | public: |
208 | 2 | explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {} |
209 | | |
210 | 1 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { |
211 | 1 | PreservedAnalyses PA = PreservedAnalyses::all(); |
212 | 1 | auto &SD = AM.getResult<ScopAnalysis>(F); |
213 | 1 | auto &SI = AM.getResult<ScopInfoAnalysis>(F); |
214 | 1 | if (SI.empty()) |
215 | 1 | return PA; |
216 | 0 | |
217 | 0 | SmallPriorityWorklist<Region *, 4> Worklist; |
218 | 0 | for (auto &S : SI) |
219 | 0 | if (S.second) |
220 | 0 | Worklist.insert(S.first); |
221 | 0 |
|
222 | 0 | ScopStandardAnalysisResults AR = {AM.getResult<DominatorTreeAnalysis>(F), |
223 | 0 | AM.getResult<ScopInfoAnalysis>(F), |
224 | 0 | AM.getResult<ScalarEvolutionAnalysis>(F), |
225 | 0 | AM.getResult<LoopAnalysis>(F), |
226 | 0 | AM.getResult<RegionInfoAnalysis>(F)}; |
227 | 0 |
|
228 | 0 | ScopAnalysisManager &SAM = |
229 | 0 | AM.getResult<ScopAnalysisManagerFunctionProxy>(F).getManager(); |
230 | 0 |
|
231 | 0 | SPMUpdater Updater{Worklist, SAM}; |
232 | 0 |
|
233 | 0 | while (!Worklist.empty()) { |
234 | 0 | Region *R = Worklist.pop_back_val(); |
235 | 0 | if (!SD.isMaxRegionInScop(*R)) |
236 | 0 | continue; |
237 | 0 | Scop *scop = SI.getScop(R); |
238 | 0 | if (!scop) |
239 | 0 | continue; |
240 | 0 | Updater.CurrentScop = scop; |
241 | 0 | Updater.InvalidateCurrentScop = false; |
242 | 0 | PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater); |
243 | 0 |
|
244 | 0 | SAM.invalidate(*scop, PassPA); |
245 | 0 | PA.intersect(std::move(PassPA)); |
246 | 0 | if (Updater.invalidateCurrentScop()) |
247 | 0 | SI.recompute(); |
248 | 0 | }; |
249 | 0 |
|
250 | 0 | PA.preserveSet<AllAnalysesOn<Scop>>(); |
251 | 0 | PA.preserve<ScopAnalysisManagerFunctionProxy>(); |
252 | 0 | PA.preserve<DominatorTreeAnalysis>(); |
253 | 0 | PA.preserve<ScopAnalysis>(); |
254 | 0 | PA.preserve<ScopInfoAnalysis>(); |
255 | 0 | PA.preserve<ScalarEvolutionAnalysis>(); |
256 | 0 | PA.preserve<LoopAnalysis>(); |
257 | 0 | PA.preserve<RegionInfoAnalysis>(); |
258 | 0 | return PA; |
259 | 0 | } |
260 | | |
261 | | private: |
262 | | ScopPassT Pass; |
263 | | }; |
264 | | |
265 | | template <typename ScopPassT> |
266 | | FunctionToScopPassAdaptor<ScopPassT> |
267 | 2 | createFunctionToScopPassAdaptor(ScopPassT Pass) { |
268 | 2 | return FunctionToScopPassAdaptor<ScopPassT>(std::move(Pass)); |
269 | 2 | } |
270 | | } // namespace polly |
271 | | |
272 | | #endif |