/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/Transform/MaximalStaticExpansion.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- MaximalStaticExpansion.cpp -----------------------------------------===// |
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 pass fully expand the memory accesses of a Scop to get rid of |
10 | | // dependencies. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "polly/DependenceInfo.h" |
15 | | #include "polly/LinkAllPasses.h" |
16 | | #include "polly/ScopInfo.h" |
17 | | #include "polly/ScopPass.h" |
18 | | #include "polly/Support/ISLTools.h" |
19 | | #include "llvm/ADT/SmallPtrSet.h" |
20 | | #include "llvm/ADT/StringRef.h" |
21 | | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
22 | | #include "isl/isl-noexceptions.h" |
23 | | #include "isl/union_map.h" |
24 | | #include <cassert> |
25 | | #include <limits> |
26 | | #include <string> |
27 | | #include <vector> |
28 | | |
29 | | using namespace llvm; |
30 | | using namespace polly; |
31 | | |
32 | 14 | #define DEBUG_TYPE "polly-mse" |
33 | | |
34 | | namespace { |
35 | | |
36 | | class MaximalStaticExpander : public ScopPass { |
37 | | public: |
38 | | static char ID; |
39 | | |
40 | 17 | explicit MaximalStaticExpander() : ScopPass(ID) {} |
41 | | |
42 | 17 | ~MaximalStaticExpander() override = default; |
43 | | |
44 | | /// Expand the accesses of the SCoP. |
45 | | /// |
46 | | /// @param S The SCoP that must be expanded. |
47 | | bool runOnScop(Scop &S) override; |
48 | | |
49 | | /// Print the SCoP. |
50 | | /// |
51 | | /// @param OS The stream where to print. |
52 | | /// @param S The SCop that must be printed. |
53 | | void printScop(raw_ostream &OS, Scop &S) const override; |
54 | | |
55 | | /// Register all analyses and transformations required. |
56 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
57 | | |
58 | | private: |
59 | | /// OptimizationRemarkEmitter object for displaying diagnostic remarks. |
60 | | OptimizationRemarkEmitter *ORE; |
61 | | |
62 | | /// Emit remark |
63 | | void emitRemark(StringRef Msg, Instruction *Inst); |
64 | | |
65 | | /// Return true if the SAI in parameter is expandable. |
66 | | /// |
67 | | /// @param SAI the SAI that need to be checked. |
68 | | /// @param Writes A set that will contains all the write accesses. |
69 | | /// @param Reads A set that will contains all the read accesses. |
70 | | /// @param S The SCop in which the SAI is in. |
71 | | /// @param Dependences The RAW dependences of the SCop. |
72 | | bool isExpandable(const ScopArrayInfo *SAI, |
73 | | SmallPtrSetImpl<MemoryAccess *> &Writes, |
74 | | SmallPtrSetImpl<MemoryAccess *> &Reads, Scop &S, |
75 | | const isl::union_map &Dependences); |
76 | | |
77 | | /// Expand the MemoryAccess according to its domain. |
78 | | /// |
79 | | /// @param S The SCop in which the memory access appears in. |
80 | | /// @param MA The memory access that need to be expanded. |
81 | | ScopArrayInfo *expandAccess(Scop &S, MemoryAccess *MA); |
82 | | |
83 | | /// Filter the dependences to have only one related to current memory access. |
84 | | /// |
85 | | /// @param S The SCop in which the memory access appears in. |
86 | | /// @param MapDependences The dependences to filter. |
87 | | /// @param MA The memory access that need to be expanded. |
88 | | isl::union_map filterDependences(Scop &S, |
89 | | const isl::union_map &MapDependences, |
90 | | MemoryAccess *MA); |
91 | | |
92 | | /// Expand the MemoryAccess according to Dependences and already expanded |
93 | | /// MemoryAccesses. |
94 | | /// |
95 | | /// @param The SCop in which the memory access appears in. |
96 | | /// @param The memory access that need to be expanded. |
97 | | /// @param Dependences The RAW dependences of the SCop. |
98 | | /// @param ExpandedSAI The expanded SAI created during write expansion. |
99 | | /// @param Reverse if true, the Dependences union_map is reversed before |
100 | | /// intersection. |
101 | | void mapAccess(Scop &S, SmallPtrSetImpl<MemoryAccess *> &Accesses, |
102 | | const isl::union_map &Dependences, ScopArrayInfo *ExpandedSAI, |
103 | | bool Reverse); |
104 | | |
105 | | /// Expand PHI memory accesses. |
106 | | /// |
107 | | /// @param The SCop in which the memory access appears in. |
108 | | /// @param The ScopArrayInfo representing the PHI accesses to expand. |
109 | | /// @param Dependences The RAW dependences of the SCop. |
110 | | void expandPhi(Scop &S, const ScopArrayInfo *SAI, |
111 | | const isl::union_map &Dependences); |
112 | | }; |
113 | | } // namespace |
114 | | |
115 | | #ifndef NDEBUG |
116 | | /// Whether a dimension of a set is bounded (lower and upper) by a constant, |
117 | | /// i.e. there are two constants Min and Max, such that every value x of the |
118 | | /// chosen dimensions is Min <= x <= Max. |
119 | | static bool isDimBoundedByConstant(isl::set Set, unsigned dim) { |
120 | | auto ParamDims = Set.dim(isl::dim::param); |
121 | | Set = Set.project_out(isl::dim::param, 0, ParamDims); |
122 | | Set = Set.project_out(isl::dim::set, 0, dim); |
123 | | auto SetDims = Set.dim(isl::dim::set); |
124 | | Set = Set.project_out(isl::dim::set, 1, SetDims - 1); |
125 | | return bool(Set.is_bounded()); |
126 | | } |
127 | | #endif |
128 | | |
129 | | char MaximalStaticExpander::ID = 0; |
130 | | |
131 | | isl::union_map MaximalStaticExpander::filterDependences( |
132 | 90 | Scop &S, const isl::union_map &Dependences, MemoryAccess *MA) { |
133 | 90 | auto SAI = MA->getLatestScopArrayInfo(); |
134 | 90 | |
135 | 90 | auto AccessDomainSet = MA->getAccessRelation().domain(); |
136 | 90 | auto AccessDomainId = AccessDomainSet.get_tuple_id(); |
137 | 90 | |
138 | 90 | isl::union_map MapDependences = isl::union_map::empty(S.getParamSpace()); |
139 | 90 | |
140 | 1.07k | for (isl::map Map : Dependences.get_map_list()) { |
141 | 1.07k | // Filter out Statement to Statement dependences. |
142 | 1.07k | if (!Map.can_curry()) |
143 | 478 | continue; |
144 | 594 | |
145 | 594 | // Intersect with the relevant SAI. |
146 | 594 | auto TmpMapDomainId = |
147 | 594 | Map.get_space().domain().unwrap().range().get_tuple_id(isl::dim::set); |
148 | 594 | |
149 | 594 | ScopArrayInfo *UserSAI = |
150 | 594 | static_cast<ScopArrayInfo *>(TmpMapDomainId.get_user()); |
151 | 594 | |
152 | 594 | if (SAI != UserSAI) |
153 | 462 | continue; |
154 | 132 | |
155 | 132 | // Get the correct S1[] -> S2[] dependence. |
156 | 132 | auto NewMap = Map.factor_domain(); |
157 | 132 | auto NewMapDomainId = NewMap.domain().get_tuple_id(); |
158 | 132 | |
159 | 132 | if (AccessDomainId.get() != NewMapDomainId.get()) |
160 | 42 | continue; |
161 | 90 | |
162 | 90 | // Add the corresponding map to MapDependences. |
163 | 90 | MapDependences = MapDependences.add_map(NewMap); |
164 | 90 | } |
165 | 90 | |
166 | 90 | return MapDependences; |
167 | 90 | } |
168 | | |
169 | | bool MaximalStaticExpander::isExpandable( |
170 | | const ScopArrayInfo *SAI, SmallPtrSetImpl<MemoryAccess *> &Writes, |
171 | | SmallPtrSetImpl<MemoryAccess *> &Reads, Scop &S, |
172 | 63 | const isl::union_map &Dependences) { |
173 | 63 | if (SAI->isValueKind()) { |
174 | 3 | Writes.insert(S.getValueDef(SAI)); |
175 | 3 | for (auto MA : S.getValueUses(SAI)) |
176 | 4 | Reads.insert(MA); |
177 | 3 | return true; |
178 | 60 | } else if (SAI->isPHIKind()) { |
179 | 28 | auto Read = S.getPHIRead(SAI); |
180 | 28 | |
181 | 28 | auto StmtDomain = isl::union_set(Read->getStatement()->getDomain()); |
182 | 28 | |
183 | 28 | auto Writes = S.getPHIIncomings(SAI); |
184 | 28 | |
185 | 28 | // Get the domain where all the writes are writing to. |
186 | 28 | auto WriteDomain = isl::union_set::empty(S.getParamSpace()); |
187 | 28 | |
188 | 38 | for (auto Write : Writes) { |
189 | 38 | auto MapDeps = filterDependences(S, Dependences, Write); |
190 | 38 | for (isl::map Map : MapDeps.get_map_list()) |
191 | 38 | WriteDomain = WriteDomain.add_set(Map.range()); |
192 | 38 | } |
193 | 28 | |
194 | 28 | // For now, read from original scalar is not possible. |
195 | 28 | if (!StmtDomain.is_equal(WriteDomain)) { |
196 | 8 | emitRemark(SAI->getName() + " read from its original value.", |
197 | 8 | Read->getAccessInstruction()); |
198 | 8 | return false; |
199 | 8 | } |
200 | 20 | |
201 | 20 | return true; |
202 | 32 | } else if (SAI->isExitPHIKind()) { |
203 | 0 | // For now, we are not able to expand ExitPhi. |
204 | 0 | emitRemark(SAI->getName() + " is a ExitPhi node.", |
205 | 0 | S.getEnteringBlock()->getFirstNonPHI()); |
206 | 0 | return false; |
207 | 0 | } |
208 | 32 | |
209 | 32 | int NumberWrites = 0; |
210 | 90 | for (ScopStmt &Stmt : S) { |
211 | 90 | auto StmtReads = isl::union_map::empty(S.getParamSpace()); |
212 | 90 | auto StmtWrites = isl::union_map::empty(S.getParamSpace()); |
213 | 90 | |
214 | 186 | for (MemoryAccess *MA : Stmt) { |
215 | 186 | // Check if the current MemoryAccess involved the current SAI. |
216 | 186 | if (SAI != MA->getLatestScopArrayInfo()) |
217 | 140 | continue; |
218 | 46 | |
219 | 46 | // For now, we are not able to expand array where read come after write |
220 | 46 | // (to the same location) in a same statement. |
221 | 46 | auto AccRel = isl::union_map(MA->getAccessRelation()); |
222 | 46 | if (MA->isRead()) { |
223 | 12 | // Reject load after store to same location. |
224 | 12 | if (!StmtWrites.is_disjoint(AccRel)) { |
225 | 2 | emitRemark(SAI->getName() + " has read after write to the same " |
226 | 2 | "element in same statement. The " |
227 | 2 | "dependences found during analysis may " |
228 | 2 | "be wrong because Polly is not able to " |
229 | 2 | "handle such case for now.", |
230 | 2 | MA->getAccessInstruction()); |
231 | 2 | return false; |
232 | 2 | } |
233 | 10 | |
234 | 10 | StmtReads = StmtReads.unite(AccRel); |
235 | 34 | } else { |
236 | 34 | StmtWrites = StmtWrites.unite(AccRel); |
237 | 34 | } |
238 | 46 | |
239 | 46 | // For now, we are not able to expand MayWrite. |
240 | 46 | if (44 MA->isMayWrite()44 ) { |
241 | 0 | emitRemark(SAI->getName() + " has a maywrite access.", |
242 | 0 | MA->getAccessInstruction()); |
243 | 0 | return false; |
244 | 0 | } |
245 | 44 | |
246 | 44 | // For now, we are not able to expand SAI with more than one write. |
247 | 44 | if (MA->isMustWrite()) { |
248 | 34 | Writes.insert(MA); |
249 | 34 | NumberWrites++; |
250 | 34 | if (NumberWrites > 1) { |
251 | 2 | emitRemark(SAI->getName() + " has more than 1 write access.", |
252 | 2 | MA->getAccessInstruction()); |
253 | 2 | return false; |
254 | 2 | } |
255 | 42 | } |
256 | 42 | |
257 | 42 | // Check if it is possible to expand this read. |
258 | 42 | if (MA->isRead()) { |
259 | 10 | // Get the domain of the current ScopStmt. |
260 | 10 | auto StmtDomain = Stmt.getDomain(); |
261 | 10 | |
262 | 10 | // Get the domain of the future Read access. |
263 | 10 | auto ReadDomainSet = MA->getAccessRelation().domain(); |
264 | 10 | auto ReadDomain = isl::union_set(ReadDomainSet); |
265 | 10 | |
266 | 10 | // Get the dependences relevant for this MA |
267 | 10 | auto MapDependences = filterDependences(S, Dependences.reverse(), MA); |
268 | 10 | unsigned NumberElementMap = isl_union_map_n_map(MapDependences.get()); |
269 | 10 | |
270 | 10 | if (NumberElementMap == 0) { |
271 | 0 | emitRemark("The expansion of " + SAI->getName() + |
272 | 0 | " would lead to a read from the original array.", |
273 | 0 | MA->getAccessInstruction()); |
274 | 0 | return false; |
275 | 0 | } |
276 | 10 | |
277 | 10 | auto DepsDomain = MapDependences.domain(); |
278 | 10 | |
279 | 10 | // If there are multiple maps in the Deps, we cannot handle this case |
280 | 10 | // for now. |
281 | 10 | if (NumberElementMap != 1) { |
282 | 0 | emitRemark(SAI->getName() + |
283 | 0 | " has too many dependences to be handle for now.", |
284 | 0 | MA->getAccessInstruction()); |
285 | 0 | return false; |
286 | 0 | } |
287 | 10 | |
288 | 10 | auto DepsDomainSet = isl::set(DepsDomain); |
289 | 10 | |
290 | 10 | // For now, read from the original array is not possible. |
291 | 10 | if (!StmtDomain.is_subset(DepsDomainSet)) { |
292 | 2 | emitRemark("The expansion of " + SAI->getName() + |
293 | 2 | " would lead to a read from the original array.", |
294 | 2 | MA->getAccessInstruction()); |
295 | 2 | return false; |
296 | 2 | } |
297 | 8 | |
298 | 8 | Reads.insert(MA); |
299 | 8 | } |
300 | 42 | } |
301 | 90 | } |
302 | 32 | |
303 | 32 | // No need to expand SAI with no write. |
304 | 32 | if (26 NumberWrites == 026 ) { |
305 | 0 | emitRemark(SAI->getName() + " has 0 write access.", |
306 | 0 | S.getEnteringBlock()->getFirstNonPHI()); |
307 | 0 | return false; |
308 | 0 | } |
309 | 26 | |
310 | 26 | return true; |
311 | 26 | } |
312 | | |
313 | | void MaximalStaticExpander::mapAccess(Scop &S, |
314 | | SmallPtrSetImpl<MemoryAccess *> &Accesses, |
315 | | const isl::union_map &Dependences, |
316 | | ScopArrayInfo *ExpandedSAI, |
317 | 49 | bool Reverse) { |
318 | 49 | for (auto MA : Accesses) { |
319 | 42 | // Get the current AM. |
320 | 42 | auto CurrentAccessMap = MA->getAccessRelation(); |
321 | 42 | |
322 | 42 | // Get RAW dependences for the current WA. |
323 | 42 | auto DomainSet = MA->getAccessRelation().domain(); |
324 | 42 | auto Domain = isl::union_set(DomainSet); |
325 | 42 | |
326 | 42 | // Get the dependences relevant for this MA. |
327 | 42 | isl::union_map MapDependences = |
328 | 42 | filterDependences(S, Reverse ? Dependences.reverse()12 : Dependences30 , MA); |
329 | 42 | |
330 | 42 | // If no dependences, no need to modify anything. |
331 | 42 | if (MapDependences.is_empty()) |
332 | 0 | return; |
333 | 42 | |
334 | 42 | assert(isl_union_map_n_map(MapDependences.get()) == 1 && |
335 | 42 | "There are more than one RAW dependencies in the union map."); |
336 | 42 | auto NewAccessMap = isl::map::from_union_map(MapDependences); |
337 | 42 | |
338 | 42 | auto Id = ExpandedSAI->getBasePtrId(); |
339 | 42 | |
340 | 42 | // Replace the out tuple id with the one of the access array. |
341 | 42 | NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, Id); |
342 | 42 | |
343 | 42 | // Set the new access relation. |
344 | 42 | MA->setNewAccessRelation(NewAccessMap); |
345 | 42 | } |
346 | 49 | } |
347 | | |
348 | 49 | ScopArrayInfo *MaximalStaticExpander::expandAccess(Scop &S, MemoryAccess *MA) { |
349 | 49 | // Get the current AM. |
350 | 49 | auto CurrentAccessMap = MA->getAccessRelation(); |
351 | 49 | |
352 | 49 | unsigned in_dimensions = CurrentAccessMap.dim(isl::dim::in); |
353 | 49 | |
354 | 49 | // Get domain from the current AM. |
355 | 49 | auto Domain = CurrentAccessMap.domain(); |
356 | 49 | |
357 | 49 | // Create a new AM from the domain. |
358 | 49 | auto NewAccessMap = isl::map::from_domain(Domain); |
359 | 49 | |
360 | 49 | // Add dimensions to the new AM according to the current in_dim. |
361 | 49 | NewAccessMap = NewAccessMap.add_dims(isl::dim::out, in_dimensions); |
362 | 49 | |
363 | 49 | // Create the string representing the name of the new SAI. |
364 | 49 | // One new SAI for each statement so that each write go to a different memory |
365 | 49 | // cell. |
366 | 49 | auto CurrentStmtDomain = MA->getStatement()->getDomain(); |
367 | 49 | auto CurrentStmtName = CurrentStmtDomain.get_tuple_name(); |
368 | 49 | auto CurrentOutId = CurrentAccessMap.get_tuple_id(isl::dim::out); |
369 | 49 | std::string CurrentOutIdString = |
370 | 49 | MA->getScopArrayInfo()->getName() + "_" + CurrentStmtName + "_expanded"; |
371 | 49 | |
372 | 49 | // Set the tuple id for the out dimension. |
373 | 49 | NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, CurrentOutId); |
374 | 49 | |
375 | 49 | // Create the size vector. |
376 | 49 | std::vector<unsigned> Sizes; |
377 | 129 | for (unsigned i = 0; i < in_dimensions; i++80 ) { |
378 | 80 | assert(isDimBoundedByConstant(CurrentStmtDomain, i) && |
379 | 80 | "Domain boundary are not constant."); |
380 | 80 | auto UpperBound = getConstant(CurrentStmtDomain.dim_max(i), true, false); |
381 | 80 | assert(!UpperBound.is_null() && UpperBound.is_pos() && |
382 | 80 | !UpperBound.is_nan() && |
383 | 80 | "The upper bound is not a positive integer."); |
384 | 80 | assert(UpperBound.le(isl::val(CurrentAccessMap.get_ctx(), |
385 | 80 | std::numeric_limits<int>::max() - 1)) && |
386 | 80 | "The upper bound overflow a int."); |
387 | 80 | Sizes.push_back(UpperBound.get_num_si() + 1); |
388 | 80 | } |
389 | 49 | |
390 | 49 | // Get the ElementType of the current SAI. |
391 | 49 | auto ElementType = MA->getLatestScopArrayInfo()->getElementType(); |
392 | 49 | |
393 | 49 | // Create (or get if already existing) the new expanded SAI. |
394 | 49 | auto ExpandedSAI = |
395 | 49 | S.createScopArrayInfo(ElementType, CurrentOutIdString, Sizes); |
396 | 49 | ExpandedSAI->setIsOnHeap(true); |
397 | 49 | |
398 | 49 | // Get the out Id of the expanded Array. |
399 | 49 | auto NewOutId = ExpandedSAI->getBasePtrId(); |
400 | 49 | |
401 | 49 | // Set the out id of the new AM to the new SAI id. |
402 | 49 | NewAccessMap = NewAccessMap.set_tuple_id(isl::dim::out, NewOutId); |
403 | 49 | |
404 | 49 | // Add constraints to linked output with input id. |
405 | 49 | auto SpaceMap = NewAccessMap.get_space(); |
406 | 49 | auto ConstraintBasicMap = |
407 | 49 | isl::basic_map::equal(SpaceMap, SpaceMap.dim(isl::dim::in)); |
408 | 49 | NewAccessMap = isl::map(ConstraintBasicMap); |
409 | 49 | |
410 | 49 | // Set the new access relation map. |
411 | 49 | MA->setNewAccessRelation(NewAccessMap); |
412 | 49 | |
413 | 49 | return ExpandedSAI; |
414 | 49 | } |
415 | | |
416 | | void MaximalStaticExpander::expandPhi(Scop &S, const ScopArrayInfo *SAI, |
417 | 20 | const isl::union_map &Dependences) { |
418 | 20 | SmallPtrSet<MemoryAccess *, 4> Writes; |
419 | 20 | for (auto MA : S.getPHIIncomings(SAI)) |
420 | 30 | Writes.insert(MA); |
421 | 20 | auto Read = S.getPHIRead(SAI); |
422 | 20 | auto ExpandedSAI = expandAccess(S, Read); |
423 | 20 | |
424 | 20 | mapAccess(S, Writes, Dependences, ExpandedSAI, false); |
425 | 20 | } |
426 | | |
427 | 14 | void MaximalStaticExpander::emitRemark(StringRef Msg, Instruction *Inst) { |
428 | 14 | ORE->emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ExpansionRejection", Inst) |
429 | 14 | << Msg); |
430 | 14 | } |
431 | | |
432 | 17 | bool MaximalStaticExpander::runOnScop(Scop &S) { |
433 | 17 | // Get the ORE from OptimizationRemarkEmitterWrapperPass. |
434 | 17 | ORE = &(getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE()); |
435 | 17 | |
436 | 17 | // Get the RAW Dependences. |
437 | 17 | auto &DI = getAnalysis<DependenceInfo>(); |
438 | 17 | auto &D = DI.getDependences(Dependences::AL_Reference); |
439 | 17 | isl::union_map Dependences = D.getDependences(Dependences::TYPE_RAW); |
440 | 17 | |
441 | 17 | SmallVector<ScopArrayInfo *, 4> CurrentSAI(S.arrays().begin(), |
442 | 17 | S.arrays().end()); |
443 | 17 | |
444 | 63 | for (auto SAI : CurrentSAI) { |
445 | 63 | SmallPtrSet<MemoryAccess *, 4> AllWrites; |
446 | 63 | SmallPtrSet<MemoryAccess *, 4> AllReads; |
447 | 63 | if (!isExpandable(SAI, AllWrites, AllReads, S, Dependences)) |
448 | 14 | continue; |
449 | 49 | |
450 | 49 | if (SAI->isValueKind() || SAI->isArrayKind()46 ) { |
451 | 29 | assert(AllWrites.size() == 1 || SAI->isValueKind()); |
452 | 29 | |
453 | 29 | auto TheWrite = *(AllWrites.begin()); |
454 | 29 | ScopArrayInfo *ExpandedArray = expandAccess(S, TheWrite); |
455 | 29 | |
456 | 29 | mapAccess(S, AllReads, Dependences, ExpandedArray, true); |
457 | 29 | } else if (20 SAI->isPHIKind()20 ) { |
458 | 20 | expandPhi(S, SAI, Dependences); |
459 | 20 | } |
460 | 49 | } |
461 | 17 | |
462 | 17 | return false; |
463 | 17 | } |
464 | | |
465 | 17 | void MaximalStaticExpander::printScop(raw_ostream &OS, Scop &S) const { |
466 | 17 | S.print(OS, false); |
467 | 17 | } |
468 | | |
469 | 17 | void MaximalStaticExpander::getAnalysisUsage(AnalysisUsage &AU) const { |
470 | 17 | ScopPass::getAnalysisUsage(AU); |
471 | 17 | AU.addRequired<DependenceInfo>(); |
472 | 17 | AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); |
473 | 17 | } |
474 | | |
475 | 0 | Pass *polly::createMaximalStaticExpansionPass() { |
476 | 0 | return new MaximalStaticExpander(); |
477 | 0 | } |
478 | | |
479 | 48.2k | INITIALIZE_PASS_BEGIN(MaximalStaticExpander, "polly-mse", |
480 | 48.2k | "Polly - Maximal static expansion of SCoP", false, false); |
481 | 48.2k | INITIALIZE_PASS_DEPENDENCY(DependenceInfo); |
482 | 48.2k | INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass); |
483 | 48.2k | INITIALIZE_PASS_END(MaximalStaticExpander, "polly-mse", |
484 | | "Polly - Maximal static expansion of SCoP", false, false) |