Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- polly/ScopBuilder.h --------------------------------------*- 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 | // Create a polyhedral description for a static control flow region. |
||
10 | // |
||
11 | // The pass creates a polyhedral description of the Scops detected by the SCoP |
||
12 | // detection derived from their LLVM-IR code. |
||
13 | // |
||
14 | //===----------------------------------------------------------------------===// |
||
15 | |||
16 | #ifndef POLLY_SCOPBUILDER_H |
||
17 | #define POLLY_SCOPBUILDER_H |
||
18 | |||
19 | #include "polly/ScopInfo.h" |
||
20 | #include "polly/Support/ScopHelper.h" |
||
21 | #include "llvm/ADT/ArrayRef.h" |
||
22 | #include "llvm/ADT/SetVector.h" |
||
23 | |||
24 | namespace polly { |
||
25 | using llvm::SmallSetVector; |
||
26 | |||
27 | class ScopDetection; |
||
28 | |||
29 | /// Command line switch whether to model read-only accesses. |
||
30 | extern bool ModelReadOnlyScalars; |
||
31 | |||
32 | /// Build the Polly IR (Scop and ScopStmt) on a Region. |
||
33 | class ScopBuilder final { |
||
34 | |||
35 | /// The AAResults to build AliasSetTracker. |
||
36 | AAResults &AA; |
||
37 | |||
38 | /// Target data for element size computing. |
||
39 | const DataLayout &DL; |
||
40 | |||
41 | /// DominatorTree to reason about guaranteed execution. |
||
42 | DominatorTree &DT; |
||
43 | |||
44 | /// LoopInfo for information about loops. |
||
45 | LoopInfo &LI; |
||
46 | |||
47 | /// Valid Regions for Scop |
||
48 | ScopDetection &SD; |
||
49 | |||
50 | /// The ScalarEvolution to help building Scop. |
||
51 | ScalarEvolution &SE; |
||
52 | |||
53 | /// An optimization diagnostic interface to add optimization remarks. |
||
54 | OptimizationRemarkEmitter &ORE; |
||
55 | |||
56 | /// Set of instructions that might read any memory location. |
||
57 | SmallVector<std::pair<ScopStmt *, Instruction *>, 16> GlobalReads; |
||
58 | |||
59 | /// Set of all accessed array base pointers. |
||
60 | SmallSetVector<Value *, 16> ArrayBasePointers; |
||
61 | |||
62 | // The Scop |
||
63 | std::unique_ptr<Scop> scop; |
||
64 | |||
65 | /// Collection to hold taken assumptions. |
||
66 | /// |
||
67 | /// There are two reasons why we want to record assumptions first before we |
||
68 | /// add them to the assumed/invalid context: |
||
69 | /// 1) If the SCoP is not profitable or otherwise invalid without the |
||
70 | /// assumed/invalid context we do not have to compute it. |
||
71 | /// 2) Information about the context are gathered rather late in the SCoP |
||
72 | /// construction (basically after we know all parameters), thus the user |
||
73 | /// might see overly complicated assumptions to be taken while they will |
||
74 | /// only be simplified later on. |
||
75 | RecordedAssumptionsTy RecordedAssumptions; |
||
76 | |||
77 | // Build the SCoP for Region @p R. |
||
78 | void buildScop(Region &R, AssumptionCache &AC); |
||
79 | |||
80 | /// Adjust the dimensions of @p Dom that was constructed for @p OldL |
||
81 | /// to be compatible to domains constructed for loop @p NewL. |
||
82 | /// |
||
83 | /// This function assumes @p NewL and @p OldL are equal or there is a CFG |
||
84 | /// edge from @p OldL to @p NewL. |
||
85 | isl::set adjustDomainDimensions(isl::set Dom, Loop *OldL, Loop *NewL); |
||
86 | |||
87 | /// Compute the domain for each basic block in @p R. |
||
88 | /// |
||
89 | /// @param R The region we currently traverse. |
||
90 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
91 | /// region. |
||
92 | /// |
||
93 | /// @returns True if there was no problem and false otherwise. |
||
94 | bool buildDomains(Region *R, |
||
95 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
96 | |||
97 | /// Compute the branching constraints for each basic block in @p R. |
||
98 | /// |
||
99 | /// @param R The region we currently build branching conditions |
||
100 | /// for. |
||
101 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
102 | /// region. |
||
103 | /// |
||
104 | /// @returns True if there was no problem and false otherwise. |
||
105 | bool buildDomainsWithBranchConstraints( |
||
106 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
107 | |||
108 | /// Build the conditions sets for the terminator @p TI in the @p Domain. |
||
109 | /// |
||
110 | /// This will fill @p ConditionSets with the conditions under which control |
||
111 | /// will be moved from @p TI to its successors. Hence, @p ConditionSets will |
||
112 | /// have as many elements as @p TI has successors. |
||
113 | bool buildConditionSets(BasicBlock *BB, Instruction *TI, Loop *L, |
||
114 | __isl_keep isl_set *Domain, |
||
115 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, |
||
116 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); |
||
117 | |||
118 | /// Build the conditions sets for the branch condition @p Condition in |
||
119 | /// the @p Domain. |
||
120 | /// |
||
121 | /// This will fill @p ConditionSets with the conditions under which control |
||
122 | /// will be moved from @p TI to its successors. Hence, @p ConditionSets will |
||
123 | /// have as many elements as @p TI has successors. If @p TI is nullptr the |
||
124 | /// context under which @p Condition is true/false will be returned as the |
||
125 | /// new elements of @p ConditionSets. |
||
126 | bool buildConditionSets(BasicBlock *BB, Value *Condition, Instruction *TI, |
||
127 | Loop *L, __isl_keep isl_set *Domain, |
||
128 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, |
||
129 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); |
||
130 | |||
131 | /// Build the conditions sets for the switch @p SI in the @p Domain. |
||
132 | /// |
||
133 | /// This will fill @p ConditionSets with the conditions under which control |
||
134 | /// will be moved from @p SI to its successors. Hence, @p ConditionSets will |
||
135 | /// have as many elements as @p SI has successors. |
||
136 | bool buildConditionSets(BasicBlock *BB, SwitchInst *SI, Loop *L, |
||
137 | __isl_keep isl_set *Domain, |
||
138 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, |
||
139 | SmallVectorImpl<__isl_give isl_set *> &ConditionSets); |
||
140 | |||
141 | /// Build condition sets for unsigned ICmpInst(s). |
||
142 | /// Special handling is required for unsigned operands to ensure that if |
||
143 | /// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst |
||
144 | /// it should wrap around. |
||
145 | /// |
||
146 | /// @param IsStrictUpperBound holds information on the predicate relation |
||
147 | /// between TestVal and UpperBound, i.e, |
||
148 | /// TestVal < UpperBound OR TestVal <= UpperBound |
||
149 | __isl_give isl_set *buildUnsignedConditionSets( |
||
150 | BasicBlock *BB, Value *Condition, __isl_keep isl_set *Domain, |
||
151 | const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound, |
||
152 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, |
||
153 | bool IsStrictUpperBound); |
||
154 | |||
155 | /// Propagate the domain constraints through the region @p R. |
||
156 | /// |
||
157 | /// @param R The region we currently build branching |
||
158 | /// conditions for. |
||
159 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
160 | /// region. |
||
161 | /// |
||
162 | /// @returns True if there was no problem and false otherwise. |
||
163 | bool propagateDomainConstraints( |
||
164 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
165 | |||
166 | /// Propagate domains that are known due to graph properties. |
||
167 | /// |
||
168 | /// As a CFG is mostly structured we use the graph properties to propagate |
||
169 | /// domains without the need to compute all path conditions. In particular, |
||
170 | /// if a block A dominates a block B and B post-dominates A we know that the |
||
171 | /// domain of B is a superset of the domain of A. As we do not have |
||
172 | /// post-dominator information available here we use the less precise region |
||
173 | /// information. Given a region R, we know that the exit is always executed |
||
174 | /// if the entry was executed, thus the domain of the exit is a superset of |
||
175 | /// the domain of the entry. In case the exit can only be reached from |
||
176 | /// within the region the domains are in fact equal. This function will use |
||
177 | /// this property to avoid the generation of condition constraints that |
||
178 | /// determine when a branch is taken. If @p BB is a region entry block we |
||
179 | /// will propagate its domain to the region exit block. Additionally, we put |
||
180 | /// the region exit block in the @p FinishedExitBlocks set so we can later |
||
181 | /// skip edges from within the region to that block. |
||
182 | /// |
||
183 | /// @param BB The block for which the domain is currently |
||
184 | /// propagated. |
||
185 | /// @param BBLoop The innermost affine loop surrounding @p BB. |
||
186 | /// @param FinishedExitBlocks Set of region exits the domain was set for. |
||
187 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
188 | /// region. |
||
189 | void propagateDomainConstraintsToRegionExit( |
||
190 | BasicBlock *BB, Loop *BBLoop, |
||
191 | SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, |
||
192 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
193 | |||
194 | /// Propagate invalid domains of statements through @p R. |
||
195 | /// |
||
196 | /// This method will propagate invalid statement domains through @p R and at |
||
197 | /// the same time add error block domains to them. Additionally, the domains |
||
198 | /// of error statements and those only reachable via error statements will |
||
199 | /// be replaced by an empty set. Later those will be removed completely. |
||
200 | /// |
||
201 | /// @param R The currently traversed region. |
||
202 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
203 | /// region. |
||
204 | // |
||
205 | /// @returns True if there was no problem and false otherwise. |
||
206 | bool propagateInvalidStmtDomains( |
||
207 | Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
208 | |||
209 | /// Compute the union of predecessor domains for @p BB. |
||
210 | /// |
||
211 | /// To compute the union of all domains of predecessors of @p BB this |
||
212 | /// function applies similar reasoning on the CFG structure as described for |
||
213 | /// @see propagateDomainConstraintsToRegionExit |
||
214 | /// |
||
215 | /// @param BB The block for which the predecessor domains are collected. |
||
216 | /// @param Domain The domain under which BB is executed. |
||
217 | /// |
||
218 | /// @returns The domain under which @p BB is executed. |
||
219 | isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain); |
||
220 | |||
221 | /// Add loop carried constraints to the header block of the loop @p L. |
||
222 | /// |
||
223 | /// @param L The loop to process. |
||
224 | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
||
225 | /// region. |
||
226 | /// |
||
227 | /// @returns True if there was no problem and false otherwise. |
||
228 | bool addLoopBoundsToHeaderDomain( |
||
229 | Loop *L, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
230 | |||
231 | /// Compute the isl representation for the SCEV @p E in this BB. |
||
232 | /// |
||
233 | /// @param BB The BB for which isl representation is to be |
||
234 | /// computed. |
||
235 | /// @param InvalidDomainMap A map of BB to their invalid domains. |
||
236 | /// @param E The SCEV that should be translated. |
||
237 | /// @param NonNegative Flag to indicate the @p E has to be |
||
238 | /// non-negative. |
||
239 | /// |
||
240 | /// Note that this function will also adjust the invalid context |
||
241 | /// accordingly. |
||
242 | __isl_give isl_pw_aff * |
||
243 | getPwAff(BasicBlock *BB, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, |
||
244 | const SCEV *E, bool NonNegative = false); |
||
245 | |||
246 | /// Create equivalence classes for required invariant accesses. |
||
247 | /// |
||
248 | /// These classes will consolidate multiple required invariant loads from the |
||
249 | /// same address in order to keep the number of dimensions in the SCoP |
||
250 | /// description small. For each such class equivalence class only one |
||
251 | /// representing element, hence one required invariant load, will be chosen |
||
252 | /// and modeled as parameter. The method |
||
253 | /// Scop::getRepresentingInvariantLoadSCEV() will replace each element from an |
||
254 | /// equivalence class with the representing element that is modeled. As a |
||
255 | /// consequence Scop::getIdForParam() will only return an id for the |
||
256 | /// representing element of each equivalence class, thus for each required |
||
257 | /// invariant location. |
||
258 | void buildInvariantEquivalenceClasses(); |
||
259 | |||
260 | /// Try to build a multi-dimensional fixed sized MemoryAccess from the |
||
261 | /// Load/Store instruction. |
||
262 | /// |
||
263 | /// @param Inst The Load/Store instruction that access the memory |
||
264 | /// @param Stmt The parent statement of the instruction |
||
265 | /// |
||
266 | /// @returns True if the access could be built, False otherwise. |
||
267 | bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt); |
||
268 | |||
269 | /// Try to build a multi-dimensional parametric sized MemoryAccess. |
||
270 | /// from the Load/Store instruction. |
||
271 | /// |
||
272 | /// @param Inst The Load/Store instruction that access the memory |
||
273 | /// @param Stmt The parent statement of the instruction |
||
274 | /// |
||
275 | /// @returns True if the access could be built, False otherwise. |
||
276 | bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt); |
||
277 | |||
278 | /// Try to build a MemoryAccess for a memory intrinsic. |
||
279 | /// |
||
280 | /// @param Inst The instruction that access the memory |
||
281 | /// @param Stmt The parent statement of the instruction |
||
282 | /// |
||
283 | /// @returns True if the access could be built, False otherwise. |
||
284 | bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt); |
||
285 | |||
286 | /// Try to build a MemoryAccess for a call instruction. |
||
287 | /// |
||
288 | /// @param Inst The call instruction that access the memory |
||
289 | /// @param Stmt The parent statement of the instruction |
||
290 | /// |
||
291 | /// @returns True if the access could be built, False otherwise. |
||
292 | bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt); |
||
293 | |||
294 | /// Build a single-dimensional parametric sized MemoryAccess |
||
295 | /// from the Load/Store instruction. |
||
296 | /// |
||
297 | /// @param Inst The Load/Store instruction that access the memory |
||
298 | /// @param Stmt The parent statement of the instruction |
||
299 | /// |
||
300 | /// @returns True if the access could be built, False otherwise. |
||
301 | bool buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt); |
||
302 | |||
303 | /// Finalize all access relations. |
||
304 | /// |
||
305 | /// When building up access relations, temporary access relations that |
||
306 | /// correctly represent each individual access are constructed. However, these |
||
307 | /// access relations can be inconsistent or non-optimal when looking at the |
||
308 | /// set of accesses as a whole. This function finalizes the memory accesses |
||
309 | /// and constructs a globally consistent state. |
||
310 | void finalizeAccesses(); |
||
311 | |||
312 | /// Update access dimensionalities. |
||
313 | /// |
||
314 | /// When detecting memory accesses different accesses to the same array may |
||
315 | /// have built with different dimensionality, as outer zero-values dimensions |
||
316 | /// may not have been recognized as separate dimensions. This function goes |
||
317 | /// again over all memory accesses and updates their dimensionality to match |
||
318 | /// the dimensionality of the underlying ScopArrayInfo object. |
||
319 | void updateAccessDimensionality(); |
||
320 | |||
321 | /// Fold size constants to the right. |
||
322 | /// |
||
323 | /// In case all memory accesses in a given dimension are multiplied with a |
||
324 | /// common constant, we can remove this constant from the individual access |
||
325 | /// functions and move it to the size of the memory access. We do this as this |
||
326 | /// increases the size of the innermost dimension, consequently widens the |
||
327 | /// valid range the array subscript in this dimension can evaluate to, and |
||
328 | /// as a result increases the likelihood that our delinearization is |
||
329 | /// correct. |
||
330 | /// |
||
331 | /// Example: |
||
332 | /// |
||
333 | /// A[][n] |
||
334 | /// S[i,j] -> A[2i][2j+1] |
||
335 | /// S[i,j] -> A[2i][2j] |
||
336 | /// |
||
337 | /// => |
||
338 | /// |
||
339 | /// A[][2n] |
||
340 | /// S[i,j] -> A[i][2j+1] |
||
341 | /// S[i,j] -> A[i][2j] |
||
342 | /// |
||
343 | /// Constants in outer dimensions can arise when the elements of a parametric |
||
344 | /// multi-dimensional array are not elementary data types, but e.g., |
||
345 | /// structures. |
||
346 | void foldSizeConstantsToRight(); |
||
347 | |||
348 | /// Fold memory accesses to handle parametric offset. |
||
349 | /// |
||
350 | /// As a post-processing step, we 'fold' memory accesses to parametric |
||
351 | /// offsets in the access functions. @see MemoryAccess::foldAccess for |
||
352 | /// details. |
||
353 | void foldAccessRelations(); |
||
354 | |||
355 | /// Assume that all memory accesses are within bounds. |
||
356 | /// |
||
357 | /// After we have built a model of all memory accesses, we need to assume |
||
358 | /// that the model we built matches reality -- aka. all modeled memory |
||
359 | /// accesses always remain within bounds. We do this as last step, after |
||
360 | /// all memory accesses have been modeled and canonicalized. |
||
361 | void assumeNoOutOfBounds(); |
||
362 | |||
363 | /// Build the alias checks for this SCoP. |
||
364 | bool buildAliasChecks(); |
||
365 | |||
366 | /// A vector of memory accesses that belong to an alias group. |
||
367 | using AliasGroupTy = SmallVector<MemoryAccess *, 4>; |
||
368 | |||
369 | /// A vector of alias groups. |
||
370 | using AliasGroupVectorTy = SmallVector<AliasGroupTy, 4>; |
||
371 | |||
372 | /// Build a given alias group and its access data. |
||
373 | /// |
||
374 | /// @param AliasGroup The alias group to build. |
||
375 | /// @param HasWriteAccess A set of arrays through which memory is not only |
||
376 | /// read, but also written. |
||
377 | // |
||
378 | /// @returns True if __no__ error occurred, false otherwise. |
||
379 | bool buildAliasGroup(AliasGroupTy &AliasGroup, |
||
380 | DenseSet<const ScopArrayInfo *> HasWriteAccess); |
||
381 | |||
382 | /// Build all alias groups for this SCoP. |
||
383 | /// |
||
384 | /// @returns True if __no__ error occurred, false otherwise. |
||
385 | bool buildAliasGroups(); |
||
386 | |||
387 | /// Build alias groups for all memory accesses in the Scop. |
||
388 | /// |
||
389 | /// Using the alias analysis and an alias set tracker we build alias sets |
||
390 | /// for all memory accesses inside the Scop. For each alias set we then map |
||
391 | /// the aliasing pointers back to the memory accesses we know, thus obtain |
||
392 | /// groups of memory accesses which might alias. We also collect the set of |
||
393 | /// arrays through which memory is written. |
||
394 | /// |
||
395 | /// @returns A pair consistent of a vector of alias groups and a set of arrays |
||
396 | /// through which memory is written. |
||
397 | std::tuple<AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>> |
||
398 | buildAliasGroupsForAccesses(); |
||
399 | |||
400 | /// Split alias groups by iteration domains. |
||
401 | /// |
||
402 | /// We split each group based on the domains of the minimal/maximal accesses. |
||
403 | /// That means two minimal/maximal accesses are only in a group if their |
||
404 | /// access domains intersect. Otherwise, they are in different groups. |
||
405 | /// |
||
406 | /// @param AliasGroups The alias groups to split |
||
407 | void splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups); |
||
408 | |||
409 | /// Build an instance of MemoryAccess from the Load/Store instruction. |
||
410 | /// |
||
411 | /// @param Inst The Load/Store instruction that access the memory |
||
412 | /// @param Stmt The parent statement of the instruction |
||
413 | void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt); |
||
414 | |||
415 | /// Analyze and extract the cross-BB scalar dependences (or, dataflow |
||
416 | /// dependencies) of an instruction. |
||
417 | /// |
||
418 | /// @param UserStmt The statement @p Inst resides in. |
||
419 | /// @param Inst The instruction to be analyzed. |
||
420 | void buildScalarDependences(ScopStmt *UserStmt, Instruction *Inst); |
||
421 | |||
422 | /// Build the escaping dependences for @p Inst. |
||
423 | /// |
||
424 | /// Search for uses of the llvm::Value defined by @p Inst that are not |
||
425 | /// within the SCoP. If there is such use, add a SCALAR WRITE such that |
||
426 | /// it is available after the SCoP as escaping value. |
||
427 | /// |
||
428 | /// @param Inst The instruction to be analyzed. |
||
429 | void buildEscapingDependences(Instruction *Inst); |
||
430 | |||
431 | /// Create MemoryAccesses for the given PHI node in the given region. |
||
432 | /// |
||
433 | /// @param PHIStmt The statement @p PHI resides in. |
||
434 | /// @param PHI The PHI node to be handled |
||
435 | /// @param NonAffineSubRegion The non affine sub-region @p PHI is in. |
||
436 | /// @param IsExitBlock Flag to indicate that @p PHI is in the exit BB. |
||
437 | void buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, |
||
438 | Region *NonAffineSubRegion, bool IsExitBlock = false); |
||
439 | |||
440 | /// Build the access functions for the subregion @p SR. |
||
441 | void buildAccessFunctions(); |
||
442 | |||
443 | /// Should an instruction be modeled in a ScopStmt. |
||
444 | /// |
||
445 | /// @param Inst The instruction to check. |
||
446 | /// @param L The loop in which context the instruction is looked at. |
||
447 | /// |
||
448 | /// @returns True if the instruction should be modeled. |
||
449 | bool shouldModelInst(Instruction *Inst, Loop *L); |
||
450 | |||
451 | /// Create one or more ScopStmts for @p BB. |
||
452 | /// |
||
453 | /// Consecutive instructions are associated to the same statement until a |
||
454 | /// separator is found. |
||
455 | void buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore = false); |
||
456 | |||
457 | /// Create one or more ScopStmts for @p BB using equivalence classes. |
||
458 | /// |
||
459 | /// Instructions of a basic block that belong to the same equivalence class |
||
460 | /// are added to the same statement. |
||
461 | void buildEqivClassBlockStmts(BasicBlock *BB); |
||
462 | |||
463 | /// Create ScopStmt for all BBs and non-affine subregions of @p SR. |
||
464 | /// |
||
465 | /// @param SR A subregion of @p R. |
||
466 | /// |
||
467 | /// Some of the statements might be optimized away later when they do not |
||
468 | /// access any memory and thus have no effect. |
||
469 | void buildStmts(Region &SR); |
||
470 | |||
471 | /// Build the access functions for the statement @p Stmt in or represented by |
||
472 | /// @p BB. |
||
473 | /// |
||
474 | /// @param Stmt Statement to add MemoryAccesses to. |
||
475 | /// @param BB A basic block in @p R. |
||
476 | /// @param NonAffineSubRegion The non affine sub-region @p BB is in. |
||
477 | void buildAccessFunctions(ScopStmt *Stmt, BasicBlock &BB, |
||
478 | Region *NonAffineSubRegion = nullptr); |
||
479 | |||
480 | /// Create a new MemoryAccess object and add it to #AccFuncMap. |
||
481 | /// |
||
482 | /// @param Stmt The statement where the access takes place. |
||
483 | /// @param Inst The instruction doing the access. It is not necessarily |
||
484 | /// inside @p BB. |
||
485 | /// @param AccType The kind of access. |
||
486 | /// @param BaseAddress The accessed array's base address. |
||
487 | /// @param ElemType The type of the accessed array elements. |
||
488 | /// @param Affine Whether all subscripts are affine expressions. |
||
489 | /// @param AccessValue Value read or written. |
||
490 | /// @param Subscripts Access subscripts per dimension. |
||
491 | /// @param Sizes The array dimension's sizes. |
||
492 | /// @param Kind The kind of memory accessed. |
||
493 | /// |
||
494 | /// @return The created MemoryAccess, or nullptr if the access is not within |
||
495 | /// the SCoP. |
||
496 | MemoryAccess *addMemoryAccess(ScopStmt *Stmt, Instruction *Inst, |
||
497 | MemoryAccess::AccessType AccType, |
||
498 | Value *BaseAddress, Type *ElemType, bool Affine, |
||
499 | Value *AccessValue, |
||
500 | ArrayRef<const SCEV *> Subscripts, |
||
501 | ArrayRef<const SCEV *> Sizes, MemoryKind Kind); |
||
502 | |||
503 | /// Create a MemoryAccess that represents either a LoadInst or |
||
504 | /// StoreInst. |
||
505 | /// |
||
506 | /// @param Stmt The statement to add the MemoryAccess to. |
||
507 | /// @param MemAccInst The LoadInst or StoreInst. |
||
508 | /// @param AccType The kind of access. |
||
509 | /// @param BaseAddress The accessed array's base address. |
||
510 | /// @param ElemType The type of the accessed array elements. |
||
511 | /// @param IsAffine Whether all subscripts are affine expressions. |
||
512 | /// @param Subscripts Access subscripts per dimension. |
||
513 | /// @param Sizes The array dimension's sizes. |
||
514 | /// @param AccessValue Value read or written. |
||
515 | /// |
||
516 | /// @see MemoryKind |
||
517 | void addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst, |
||
518 | MemoryAccess::AccessType AccType, Value *BaseAddress, |
||
519 | Type *ElemType, bool IsAffine, |
||
520 | ArrayRef<const SCEV *> Subscripts, |
||
521 | ArrayRef<const SCEV *> Sizes, Value *AccessValue); |
||
522 | |||
523 | /// Create a MemoryAccess for writing an llvm::Instruction. |
||
524 | /// |
||
525 | /// The access will be created at the position of @p Inst. |
||
526 | /// |
||
527 | /// @param Inst The instruction to be written. |
||
528 | /// |
||
529 | /// @see ensureValueRead() |
||
530 | /// @see MemoryKind |
||
531 | void ensureValueWrite(Instruction *Inst); |
||
532 | |||
533 | /// Ensure an llvm::Value is available in the BB's statement, creating a |
||
534 | /// MemoryAccess for reloading it if necessary. |
||
535 | /// |
||
536 | /// @param V The value expected to be loaded. |
||
537 | /// @param UserStmt Where to reload the value. |
||
538 | /// |
||
539 | /// @see ensureValueStore() |
||
540 | /// @see MemoryKind |
||
541 | void ensureValueRead(Value *V, ScopStmt *UserStmt); |
||
542 | |||
543 | /// Create a write MemoryAccess for the incoming block of a phi node. |
||
544 | /// |
||
545 | /// Each of the incoming blocks write their incoming value to be picked in the |
||
546 | /// phi's block. |
||
547 | /// |
||
548 | /// @param PHI PHINode under consideration. |
||
549 | /// @param IncomingStmt The statement to add the MemoryAccess to. |
||
550 | /// @param IncomingBlock Some predecessor block. |
||
551 | /// @param IncomingValue @p PHI's value when coming from @p IncomingBlock. |
||
552 | /// @param IsExitBlock When true, uses the .s2a alloca instead of the |
||
553 | /// .phiops one. Required for values escaping through a |
||
554 | /// PHINode in the SCoP region's exit block. |
||
555 | /// @see addPHIReadAccess() |
||
556 | /// @see MemoryKind |
||
557 | void ensurePHIWrite(PHINode *PHI, ScopStmt *IncomintStmt, |
||
558 | BasicBlock *IncomingBlock, Value *IncomingValue, |
||
559 | bool IsExitBlock); |
||
560 | |||
561 | /// Add user provided parameter constraints to context (command line). |
||
562 | void addUserContext(); |
||
563 | |||
564 | /// Add user provided parameter constraints to context (source code). |
||
565 | void addUserAssumptions(AssumptionCache &AC, |
||
566 | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
||
567 | |||
568 | /// Add all recorded assumptions to the assumed context. |
||
569 | void addRecordedAssumptions(); |
||
570 | |||
571 | /// Create a MemoryAccess for reading the value of a phi. |
||
572 | /// |
||
573 | /// The modeling assumes that all incoming blocks write their incoming value |
||
574 | /// to the same location. Thus, this access will read the incoming block's |
||
575 | /// value as instructed by this @p PHI. |
||
576 | /// |
||
577 | /// @param PHIStmt Statement @p PHI resides in. |
||
578 | /// @param PHI PHINode under consideration; the READ access will be added |
||
579 | /// here. |
||
580 | /// |
||
581 | /// @see ensurePHIWrite() |
||
582 | /// @see MemoryKind |
||
583 | void addPHIReadAccess(ScopStmt *PHIStmt, PHINode *PHI); |
||
584 | |||
585 | /// Wrapper function to calculate minimal/maximal accesses to each array. |
||
586 | bool calculateMinMaxAccess(AliasGroupTy AliasGroup, |
||
587 | Scop::MinMaxVectorTy &MinMaxAccesses); |
||
588 | /// Build the domain of @p Stmt. |
||
589 | void buildDomain(ScopStmt &Stmt); |
||
590 | |||
591 | /// Fill NestLoops with loops surrounding @p Stmt. |
||
592 | void collectSurroundingLoops(ScopStmt &Stmt); |
||
593 | |||
594 | /// Check for reductions in @p Stmt. |
||
595 | /// |
||
596 | /// Iterate over all store memory accesses and check for valid binary |
||
597 | /// reduction like chains. For all candidates we check if they have the same |
||
598 | /// base address and there are no other accesses which overlap with them. The |
||
599 | /// base address check rules out impossible reductions candidates early. The |
||
600 | /// overlap check, together with the "only one user" check in |
||
601 | /// collectCandidateReductionLoads, guarantees that none of the intermediate |
||
602 | /// results will escape during execution of the loop nest. We basically check |
||
603 | /// here that no other memory access can access the same memory as the |
||
604 | /// potential reduction. |
||
605 | void checkForReductions(ScopStmt &Stmt); |
||
606 | |||
607 | /// Verify that all required invariant loads have been hoisted. |
||
608 | /// |
||
609 | /// Invariant load hoisting is not guaranteed to hoist all loads that were |
||
610 | /// assumed to be scop invariant during scop detection. This function checks |
||
611 | /// for cases where the hoisting failed, but where it would have been |
||
612 | /// necessary for our scop modeling to be correct. In case of insufficient |
||
613 | /// hoisting the scop is marked as invalid. |
||
614 | /// |
||
615 | /// In the example below Bound[1] is required to be invariant: |
||
616 | /// |
||
617 | /// for (int i = 1; i < Bound[0]; i++) |
||
618 | /// for (int j = 1; j < Bound[1]; j++) |
||
619 | /// ... |
||
620 | void verifyInvariantLoads(); |
||
621 | |||
622 | /// Hoist invariant memory loads and check for required ones. |
||
623 | /// |
||
624 | /// We first identify "common" invariant loads, thus loads that are invariant |
||
625 | /// and can be hoisted. Then we check if all required invariant loads have |
||
626 | /// been identified as (common) invariant. A load is a required invariant load |
||
627 | /// if it was assumed to be invariant during SCoP detection, e.g., to assume |
||
628 | /// loop bounds to be affine or runtime alias checks to be placeable. In case |
||
629 | /// a required invariant load was not identified as (common) invariant we will |
||
630 | /// drop this SCoP. An example for both "common" as well as required invariant |
||
631 | /// loads is given below: |
||
632 | /// |
||
633 | /// for (int i = 1; i < *LB[0]; i++) |
||
634 | /// for (int j = 1; j < *LB[1]; j++) |
||
635 | /// A[i][j] += A[0][0] + (*V); |
||
636 | /// |
||
637 | /// Common inv. loads: V, A[0][0], LB[0], LB[1] |
||
638 | /// Required inv. loads: LB[0], LB[1], (V, if it may alias with A or LB) |
||
639 | void hoistInvariantLoads(); |
||
640 | |||
641 | /// Add invariant loads listed in @p InvMAs with the domain of @p Stmt. |
||
642 | void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs); |
||
643 | |||
644 | /// Check if @p MA can always be hoisted without execution context. |
||
645 | bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, |
||
646 | bool MAInvalidCtxIsEmpty, |
||
647 | bool NonHoistableCtxIsEmpty); |
||
648 | |||
649 | /// Return true if and only if @p LI is a required invariant load. |
||
650 | bool isRequiredInvariantLoad(LoadInst *LI) const { |
||
651 | return scop->getRequiredInvariantLoads().count(LI); |
||
652 | } |
||
653 | |||
654 | /// Check if the base ptr of @p MA is in the SCoP but not hoistable. |
||
655 | bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes); |
||
656 | |||
657 | /// Return the context under which the access cannot be hoisted. |
||
658 | /// |
||
659 | /// @param Access The access to check. |
||
660 | /// @param Writes The set of all memory writes in the scop. |
||
661 | /// |
||
662 | /// @return Return the context under which the access cannot be hoisted or a |
||
663 | /// nullptr if it cannot be hoisted at all. |
||
664 | isl::set getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes); |
||
665 | |||
666 | /// Collect loads which might form a reduction chain with @p StoreMA. |
||
667 | /// |
||
668 | /// Check if the stored value for @p StoreMA is a binary operator with one or |
||
669 | /// two loads as operands. If the binary operand is commutative & associative, |
||
670 | /// used only once (by @p StoreMA) and its load operands are also used only |
||
671 | /// once, we have found a possible reduction chain. It starts at an operand |
||
672 | /// load and includes the binary operator and @p StoreMA. |
||
673 | /// |
||
674 | /// Note: We allow only one use to ensure the load and binary operator cannot |
||
675 | /// escape this block or into any other store except @p StoreMA. |
||
676 | void collectCandidateReductionLoads(MemoryAccess *StoreMA, |
||
677 | SmallVectorImpl<MemoryAccess *> &Loads); |
||
678 | |||
679 | /// Build the access relation of all memory accesses of @p Stmt. |
||
680 | void buildAccessRelations(ScopStmt &Stmt); |
||
681 | |||
682 | /// Canonicalize arrays with base pointers from the same equivalence class. |
||
683 | /// |
||
684 | /// Some context: in our normal model we assume that each base pointer is |
||
685 | /// related to a single specific memory region, where memory regions |
||
686 | /// associated with different base pointers are disjoint. Consequently we do |
||
687 | /// not need to compute additional data dependences that model possible |
||
688 | /// overlaps of these memory regions. To verify our assumption we compute |
||
689 | /// alias checks that verify that modeled arrays indeed do not overlap. In |
||
690 | /// case an overlap is detected the runtime check fails and we fall back to |
||
691 | /// the original code. |
||
692 | /// |
||
693 | /// In case of arrays where the base pointers are know to be identical, |
||
694 | /// because they are dynamically loaded by accesses that are in the same |
||
695 | /// invariant load equivalence class, such run-time alias check would always |
||
696 | /// be false. |
||
697 | /// |
||
698 | /// This function makes sure that we do not generate consistently failing |
||
699 | /// run-time checks for code that contains distinct arrays with known |
||
700 | /// equivalent base pointers. It identifies for each invariant load |
||
701 | /// equivalence class a single canonical array and canonicalizes all memory |
||
702 | /// accesses that reference arrays that have base pointers that are known to |
||
703 | /// be equal to the base pointer of such a canonical array to this canonical |
||
704 | /// array. |
||
705 | /// |
||
706 | /// We currently do not canonicalize arrays for which certain memory accesses |
||
707 | /// have been hoisted as loop invariant. |
||
708 | void canonicalizeDynamicBasePtrs(); |
||
709 | |||
710 | /// Construct the schedule of this SCoP. |
||
711 | void buildSchedule(); |
||
712 | |||
713 | /// A loop stack element to keep track of per-loop information during |
||
714 | /// schedule construction. |
||
715 | using LoopStackElementTy = struct LoopStackElement { |
||
716 | // The loop for which we keep information. |
||
717 | Loop *L; |
||
718 | |||
719 | // The (possibly incomplete) schedule for this loop. |
||
720 | isl::schedule Schedule; |
||
721 | |||
722 | // The number of basic blocks in the current loop, for which a schedule has |
||
723 | // already been constructed. |
||
724 | unsigned NumBlocksProcessed; |
||
725 | |||
726 | LoopStackElement(Loop *L, isl::schedule S, unsigned NumBlocksProcessed) |
||
727 | : L(L), Schedule(S), NumBlocksProcessed(NumBlocksProcessed) {} |
||
728 | }; |
||
729 | |||
730 | /// The loop stack used for schedule construction. |
||
731 | /// |
||
732 | /// The loop stack keeps track of schedule information for a set of nested |
||
733 | /// loops as well as an (optional) 'nullptr' loop that models the outermost |
||
734 | /// schedule dimension. The loops in a loop stack always have a parent-child |
||
735 | /// relation where the loop at position n is the parent of the loop at |
||
736 | /// position n + 1. |
||
737 | using LoopStackTy = SmallVector<LoopStackElementTy, 4>; |
||
738 | |||
739 | /// Construct schedule information for a given Region and add the |
||
740 | /// derived information to @p LoopStack. |
||
741 | /// |
||
742 | /// Given a Region we derive schedule information for all RegionNodes |
||
743 | /// contained in this region ensuring that the assigned execution times |
||
744 | /// correctly model the existing control flow relations. |
||
745 | /// |
||
746 | /// @param R The region which to process. |
||
747 | /// @param LoopStack A stack of loops that are currently under |
||
748 | /// construction. |
||
749 | void buildSchedule(Region *R, LoopStackTy &LoopStack); |
||
750 | |||
751 | /// Build Schedule for the region node @p RN and add the derived |
||
752 | /// information to @p LoopStack. |
||
753 | /// |
||
754 | /// In case @p RN is a BasicBlock or a non-affine Region, we construct the |
||
755 | /// schedule for this @p RN and also finalize loop schedules in case the |
||
756 | /// current @p RN completes the loop. |
||
757 | /// |
||
758 | /// In case @p RN is a not-non-affine Region, we delegate the construction to |
||
759 | /// buildSchedule(Region *R, ...). |
||
760 | /// |
||
761 | /// @param RN The RegionNode region traversed. |
||
762 | /// @param LoopStack A stack of loops that are currently under |
||
763 | /// construction. |
||
764 | void buildSchedule(RegionNode *RN, LoopStackTy &LoopStack); |
||
765 | |||
766 | public: |
||
767 | explicit ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, |
||
768 | const DataLayout &DL, DominatorTree &DT, LoopInfo &LI, |
||
769 | ScopDetection &SD, ScalarEvolution &SE, |
||
770 | OptimizationRemarkEmitter &ORE); |
||
771 | ScopBuilder(const ScopBuilder &) = delete; |
||
772 | ScopBuilder &operator=(const ScopBuilder &) = delete; |
||
773 | ~ScopBuilder() = default; |
||
774 | |||
775 | /// Try to build the Polly IR of static control part on the current |
||
776 | /// SESE-Region. |
||
777 | /// |
||
778 | /// @return Give up the ownership of the scop object or static control part |
||
779 | /// for the region |
||
780 | std::unique_ptr<Scop> getScop() { return std::move(scop); } |
||
781 | }; |
||
782 | } // end namespace polly |
||
783 | |||
784 | #endif // POLLY_SCOPBUILDER_H |