/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/include/polly/ScopInfo.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- polly/ScopInfo.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 | | // Store the polyhedral model representation of a static control flow region, |
10 | | // also called SCoP (Static Control Part). |
11 | | // |
12 | | // This representation is shared among several tools in the polyhedral |
13 | | // community, which are e.g. CLooG, Pluto, Loopo, Graphite. |
14 | | // |
15 | | //===----------------------------------------------------------------------===// |
16 | | |
17 | | #ifndef POLLY_SCOPINFO_H |
18 | | #define POLLY_SCOPINFO_H |
19 | | |
20 | | #include "polly/ScopDetection.h" |
21 | | #include "polly/Support/SCEVAffinator.h" |
22 | | #include "llvm/ADT/ArrayRef.h" |
23 | | #include "llvm/ADT/MapVector.h" |
24 | | #include "llvm/ADT/SetVector.h" |
25 | | #include "llvm/Analysis/RegionPass.h" |
26 | | #include "llvm/IR/DebugLoc.h" |
27 | | #include "llvm/IR/Instruction.h" |
28 | | #include "llvm/IR/Instructions.h" |
29 | | #include "llvm/IR/PassManager.h" |
30 | | #include "llvm/IR/ValueHandle.h" |
31 | | #include "llvm/Pass.h" |
32 | | #include "isl/isl-noexceptions.h" |
33 | | #include <cassert> |
34 | | #include <cstddef> |
35 | | #include <forward_list> |
36 | | |
37 | | using namespace llvm; |
38 | | |
39 | | namespace llvm { |
40 | | void initializeScopInfoRegionPassPass(PassRegistry &); |
41 | | void initializeScopInfoWrapperPassPass(PassRegistry &); |
42 | | } // end namespace llvm |
43 | | |
44 | | namespace polly { |
45 | | |
46 | | class MemoryAccess; |
47 | | |
48 | | //===---------------------------------------------------------------------===// |
49 | | |
50 | | extern bool UseInstructionNames; |
51 | | |
52 | | // The maximal number of basic sets we allow during domain construction to |
53 | | // be created. More complex scops will result in very high compile time and |
54 | | // are also unlikely to result in good code. |
55 | | extern int const MaxDisjunctsInDomain; |
56 | | |
57 | | /// Enumeration of assumptions Polly can take. |
58 | | enum AssumptionKind { |
59 | | ALIASING, |
60 | | INBOUNDS, |
61 | | WRAPPING, |
62 | | UNSIGNED, |
63 | | PROFITABLE, |
64 | | ERRORBLOCK, |
65 | | COMPLEXITY, |
66 | | INFINITELOOP, |
67 | | INVARIANTLOAD, |
68 | | DELINEARIZATION, |
69 | | }; |
70 | | |
71 | | /// Enum to distinguish between assumptions and restrictions. |
72 | | enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION }; |
73 | | |
74 | | /// The different memory kinds used in Polly. |
75 | | /// |
76 | | /// We distinguish between arrays and various scalar memory objects. We use |
77 | | /// the term ``array'' to describe memory objects that consist of a set of |
78 | | /// individual data elements arranged in a multi-dimensional grid. A scalar |
79 | | /// memory object describes an individual data element and is used to model |
80 | | /// the definition and uses of llvm::Values. |
81 | | /// |
82 | | /// The polyhedral model does traditionally not reason about SSA values. To |
83 | | /// reason about llvm::Values we model them "as if" they were zero-dimensional |
84 | | /// memory objects, even though they were not actually allocated in (main) |
85 | | /// memory. Memory for such objects is only alloca[ed] at CodeGeneration |
86 | | /// time. To relate the memory slots used during code generation with the |
87 | | /// llvm::Values they belong to the new names for these corresponding stack |
88 | | /// slots are derived by appending suffixes (currently ".s2a" and ".phiops") |
89 | | /// to the name of the original llvm::Value. To describe how def/uses are |
90 | | /// modeled exactly we use these suffixes here as well. |
91 | | /// |
92 | | /// There are currently four different kinds of memory objects: |
93 | | enum class MemoryKind { |
94 | | /// MemoryKind::Array: Models a one or multi-dimensional array |
95 | | /// |
96 | | /// A memory object that can be described by a multi-dimensional array. |
97 | | /// Memory objects of this type are used to model actual multi-dimensional |
98 | | /// arrays as they exist in LLVM-IR, but they are also used to describe |
99 | | /// other objects: |
100 | | /// - A single data element allocated on the stack using 'alloca' is |
101 | | /// modeled as a one-dimensional, single-element array. |
102 | | /// - A single data element allocated as a global variable is modeled as |
103 | | /// one-dimensional, single-element array. |
104 | | /// - Certain multi-dimensional arrays with variable size, which in |
105 | | /// LLVM-IR are commonly expressed as a single-dimensional access with a |
106 | | /// complicated access function, are modeled as multi-dimensional |
107 | | /// memory objects (grep for "delinearization"). |
108 | | Array, |
109 | | |
110 | | /// MemoryKind::Value: Models an llvm::Value |
111 | | /// |
112 | | /// Memory objects of type MemoryKind::Value are used to model the data flow |
113 | | /// induced by llvm::Values. For each llvm::Value that is used across |
114 | | /// BasicBlocks, one ScopArrayInfo object is created. A single memory WRITE |
115 | | /// stores the llvm::Value at its definition into the memory object and at |
116 | | /// each use of the llvm::Value (ignoring trivial intra-block uses) a |
117 | | /// corresponding READ is added. For instance, the use/def chain of a |
118 | | /// llvm::Value %V depicted below |
119 | | /// ______________________ |
120 | | /// |DefBB: | |
121 | | /// | %V = float op ... | |
122 | | /// ---------------------- |
123 | | /// | | |
124 | | /// _________________ _________________ |
125 | | /// |UseBB1: | |UseBB2: | |
126 | | /// | use float %V | | use float %V | |
127 | | /// ----------------- ----------------- |
128 | | /// |
129 | | /// is modeled as if the following memory accesses occurred: |
130 | | /// |
131 | | /// __________________________ |
132 | | /// |entry: | |
133 | | /// | %V.s2a = alloca float | |
134 | | /// -------------------------- |
135 | | /// | |
136 | | /// ___________________________________ |
137 | | /// |DefBB: | |
138 | | /// | store %float %V, float* %V.s2a | |
139 | | /// ----------------------------------- |
140 | | /// | | |
141 | | /// ____________________________________ ___________________________________ |
142 | | /// |UseBB1: | |UseBB2: | |
143 | | /// | %V.reload1 = load float* %V.s2a | | %V.reload2 = load float* %V.s2a| |
144 | | /// | use float %V.reload1 | | use float %V.reload2 | |
145 | | /// ------------------------------------ ----------------------------------- |
146 | | /// |
147 | | Value, |
148 | | |
149 | | /// MemoryKind::PHI: Models PHI nodes within the SCoP |
150 | | /// |
151 | | /// Besides the MemoryKind::Value memory object used to model the normal |
152 | | /// llvm::Value dependences described above, PHI nodes require an additional |
153 | | /// memory object of type MemoryKind::PHI to describe the forwarding of values |
154 | | /// to |
155 | | /// the PHI node. |
156 | | /// |
157 | | /// As an example, a PHIInst instructions |
158 | | /// |
159 | | /// %PHI = phi float [ %Val1, %IncomingBlock1 ], [ %Val2, %IncomingBlock2 ] |
160 | | /// |
161 | | /// is modeled as if the accesses occurred this way: |
162 | | /// |
163 | | /// _______________________________ |
164 | | /// |entry: | |
165 | | /// | %PHI.phiops = alloca float | |
166 | | /// ------------------------------- |
167 | | /// | | |
168 | | /// __________________________________ __________________________________ |
169 | | /// |IncomingBlock1: | |IncomingBlock2: | |
170 | | /// | ... | | ... | |
171 | | /// | store float %Val1 %PHI.phiops | | store float %Val2 %PHI.phiops | |
172 | | /// | br label % JoinBlock | | br label %JoinBlock | |
173 | | /// ---------------------------------- ---------------------------------- |
174 | | /// \ / |
175 | | /// \ / |
176 | | /// _________________________________________ |
177 | | /// |JoinBlock: | |
178 | | /// | %PHI = load float, float* PHI.phiops | |
179 | | /// ----------------------------------------- |
180 | | /// |
181 | | /// Note that there can also be a scalar write access for %PHI if used in a |
182 | | /// different BasicBlock, i.e. there can be a memory object %PHI.phiops as |
183 | | /// well as a memory object %PHI.s2a. |
184 | | PHI, |
185 | | |
186 | | /// MemoryKind::ExitPHI: Models PHI nodes in the SCoP's exit block |
187 | | /// |
188 | | /// For PHI nodes in the Scop's exit block a special memory object kind is |
189 | | /// used. The modeling used is identical to MemoryKind::PHI, with the |
190 | | /// exception |
191 | | /// that there are no READs from these memory objects. The PHINode's |
192 | | /// llvm::Value is treated as a value escaping the SCoP. WRITE accesses |
193 | | /// write directly to the escaping value's ".s2a" alloca. |
194 | | ExitPHI |
195 | | }; |
196 | | |
197 | | /// Maps from a loop to the affine function expressing its backedge taken count. |
198 | | /// The backedge taken count already enough to express iteration domain as we |
199 | | /// only allow loops with canonical induction variable. |
200 | | /// A canonical induction variable is: |
201 | | /// an integer recurrence that starts at 0 and increments by one each time |
202 | | /// through the loop. |
203 | | using LoopBoundMapType = std::map<const Loop *, const SCEV *>; |
204 | | |
205 | | using AccFuncVector = std::vector<std::unique_ptr<MemoryAccess>>; |
206 | | |
207 | | /// A class to store information about arrays in the SCoP. |
208 | | /// |
209 | | /// Objects are accessible via the ScoP, MemoryAccess or the id associated with |
210 | | /// the MemoryAccess access function. |
211 | | /// |
212 | | class ScopArrayInfo { |
213 | | public: |
214 | | /// Construct a ScopArrayInfo object. |
215 | | /// |
216 | | /// @param BasePtr The array base pointer. |
217 | | /// @param ElementType The type of the elements stored in the array. |
218 | | /// @param IslCtx The isl context used to create the base pointer id. |
219 | | /// @param DimensionSizes A vector containing the size of each dimension. |
220 | | /// @param Kind The kind of the array object. |
221 | | /// @param DL The data layout of the module. |
222 | | /// @param S The scop this array object belongs to. |
223 | | /// @param BaseName The optional name of this memory reference. |
224 | | ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx IslCtx, |
225 | | ArrayRef<const SCEV *> DimensionSizes, MemoryKind Kind, |
226 | | const DataLayout &DL, Scop *S, const char *BaseName = nullptr); |
227 | | |
228 | | /// Destructor to free the isl id of the base pointer. |
229 | | ~ScopArrayInfo(); |
230 | | |
231 | | /// Update the element type of the ScopArrayInfo object. |
232 | | /// |
233 | | /// Memory accesses referencing this ScopArrayInfo object may use |
234 | | /// different element sizes. This function ensures the canonical element type |
235 | | /// stored is small enough to model accesses to the current element type as |
236 | | /// well as to @p NewElementType. |
237 | | /// |
238 | | /// @param NewElementType An element type that is used to access this array. |
239 | | void updateElementType(Type *NewElementType); |
240 | | |
241 | | /// Update the sizes of the ScopArrayInfo object. |
242 | | /// |
243 | | /// A ScopArrayInfo object may be created without all outer dimensions being |
244 | | /// available. This function is called when new memory accesses are added for |
245 | | /// this ScopArrayInfo object. It verifies that sizes are compatible and adds |
246 | | /// additional outer array dimensions, if needed. |
247 | | /// |
248 | | /// @param Sizes A vector of array sizes where the rightmost array |
249 | | /// sizes need to match the innermost array sizes already |
250 | | /// defined in SAI. |
251 | | /// @param CheckConsistency Update sizes, even if new sizes are inconsistent |
252 | | /// with old sizes |
253 | | bool updateSizes(ArrayRef<const SCEV *> Sizes, bool CheckConsistency = true); |
254 | | |
255 | | /// Make the ScopArrayInfo model a Fortran array. |
256 | | /// It receives the Fortran array descriptor and stores this. |
257 | | /// It also adds a piecewise expression for the outermost dimension |
258 | | /// since this information is available for Fortran arrays at runtime. |
259 | | void applyAndSetFAD(Value *FAD); |
260 | | |
261 | | /// Get the FortranArrayDescriptor corresponding to this array if it exists, |
262 | | /// nullptr otherwise. |
263 | 490 | Value *getFortranArrayDescriptor() const { return this->FAD; } |
264 | | |
265 | | /// Set the base pointer to @p BP. |
266 | 10 | void setBasePtr(Value *BP) { BasePtr = BP; } |
267 | | |
268 | | /// Return the base pointer. |
269 | 4.93k | Value *getBasePtr() const { return BasePtr; } |
270 | | |
271 | | // Set IsOnHeap to the value in parameter. |
272 | 55 | void setIsOnHeap(bool value) { IsOnHeap = value; } |
273 | | |
274 | | /// For indirect accesses return the origin SAI of the BP, else null. |
275 | 404 | const ScopArrayInfo *getBasePtrOriginSAI() const { return BasePtrOriginSAI; } |
276 | | |
277 | | /// The set of derived indirect SAIs for this origin SAI. |
278 | 105 | const SmallSetVector<ScopArrayInfo *, 2> &getDerivedSAIs() const { |
279 | 105 | return DerivedSAIs; |
280 | 105 | } |
281 | | |
282 | | /// Return the number of dimensions. |
283 | 23.6k | unsigned getNumberOfDimensions() const { |
284 | 23.6k | if (Kind == MemoryKind::PHI || Kind == MemoryKind::ExitPHI21.9k || |
285 | 23.6k | Kind == MemoryKind::Value21.5k ) |
286 | 4.67k | return 0; |
287 | 19.0k | return DimensionSizes.size(); |
288 | 19.0k | } |
289 | | |
290 | | /// Return the size of dimension @p dim as SCEV*. |
291 | | // |
292 | | // Scalars do not have array dimensions and the first dimension of |
293 | | // a (possibly multi-dimensional) array also does not carry any size |
294 | | // information, in case the array is not newly created. |
295 | 2.40k | const SCEV *getDimensionSize(unsigned Dim) const { |
296 | 2.40k | assert(Dim < getNumberOfDimensions() && "Invalid dimension"); |
297 | 2.40k | return DimensionSizes[Dim]; |
298 | 2.40k | } |
299 | | |
300 | | /// Return the size of dimension @p dim as isl::pw_aff. |
301 | | // |
302 | | // Scalars do not have array dimensions and the first dimension of |
303 | | // a (possibly multi-dimensional) array also does not carry any size |
304 | | // information, in case the array is not newly created. |
305 | 4.54k | isl::pw_aff getDimensionSizePw(unsigned Dim) const { |
306 | 4.54k | assert(Dim < getNumberOfDimensions() && "Invalid dimension"); |
307 | 4.54k | return DimensionSizesPw[Dim]; |
308 | 4.54k | } |
309 | | |
310 | | /// Get the canonical element type of this array. |
311 | | /// |
312 | | /// @returns The canonical element type of this array. |
313 | 3.87k | Type *getElementType() const { return ElementType; } |
314 | | |
315 | | /// Get element size in bytes. |
316 | | int getElemSizeInBytes() const; |
317 | | |
318 | | /// Get the name of this memory reference. |
319 | | std::string getName() const; |
320 | | |
321 | | /// Return the isl id for the base pointer. |
322 | | isl::id getBasePtrId() const; |
323 | | |
324 | | /// Return what kind of memory this represents. |
325 | 2.22k | MemoryKind getKind() const { return Kind; } |
326 | | |
327 | | /// Is this array info modeling an llvm::Value? |
328 | 365 | bool isValueKind() const { return Kind == MemoryKind::Value; } |
329 | | |
330 | | /// Is this array info modeling special PHI node memory? |
331 | | /// |
332 | | /// During code generation of PHI nodes, there is a need for two kinds of |
333 | | /// virtual storage. The normal one as it is used for all scalar dependences, |
334 | | /// where the result of the PHI node is stored and later loaded from as well |
335 | | /// as a second one where the incoming values of the PHI nodes are stored |
336 | | /// into and reloaded when the PHI is executed. As both memories use the |
337 | | /// original PHI node as virtual base pointer, we have this additional |
338 | | /// attribute to distinguish the PHI node specific array modeling from the |
339 | | /// normal scalar array modeling. |
340 | 619 | bool isPHIKind() const { return Kind == MemoryKind::PHI; } |
341 | | |
342 | | /// Is this array info modeling an MemoryKind::ExitPHI? |
343 | 341 | bool isExitPHIKind() const { return Kind == MemoryKind::ExitPHI; } |
344 | | |
345 | | /// Is this array info modeling an array? |
346 | 810 | bool isArrayKind() const { return Kind == MemoryKind::Array; } |
347 | | |
348 | | /// Is this array allocated on heap |
349 | | /// |
350 | | /// This property is only relevant if the array is allocated by Polly instead |
351 | | /// of pre-existing. If false, it is allocated using alloca instead malloca. |
352 | 10 | bool isOnHeap() const { return IsOnHeap; } |
353 | | |
354 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
355 | | /// Dump a readable representation to stderr. |
356 | | void dump() const; |
357 | | #endif |
358 | | |
359 | | /// Print a readable representation to @p OS. |
360 | | /// |
361 | | /// @param SizeAsPwAff Print the size as isl::pw_aff |
362 | | void print(raw_ostream &OS, bool SizeAsPwAff = false) const; |
363 | | |
364 | | /// Access the ScopArrayInfo associated with an access function. |
365 | | static const ScopArrayInfo *getFromAccessFunction(isl::pw_multi_aff PMA); |
366 | | |
367 | | /// Access the ScopArrayInfo associated with an isl Id. |
368 | | static const ScopArrayInfo *getFromId(isl::id Id); |
369 | | |
370 | | /// Get the space of this array access. |
371 | | isl::space getSpace() const; |
372 | | |
373 | | /// If the array is read only |
374 | | bool isReadOnly(); |
375 | | |
376 | | /// Verify that @p Array is compatible to this ScopArrayInfo. |
377 | | /// |
378 | | /// Two arrays are compatible if their dimensionality, the sizes of their |
379 | | /// dimensions, and their element sizes match. |
380 | | /// |
381 | | /// @param Array The array to compare against. |
382 | | /// |
383 | | /// @returns True, if the arrays are compatible, False otherwise. |
384 | | bool isCompatibleWith(const ScopArrayInfo *Array) const; |
385 | | |
386 | | private: |
387 | 93 | void addDerivedSAI(ScopArrayInfo *DerivedSAI) { |
388 | 93 | DerivedSAIs.insert(DerivedSAI); |
389 | 93 | } |
390 | | |
391 | | /// For indirect accesses this is the SAI of the BP origin. |
392 | | const ScopArrayInfo *BasePtrOriginSAI; |
393 | | |
394 | | /// For origin SAIs the set of derived indirect SAIs. |
395 | | SmallSetVector<ScopArrayInfo *, 2> DerivedSAIs; |
396 | | |
397 | | /// The base pointer. |
398 | | AssertingVH<Value> BasePtr; |
399 | | |
400 | | /// The canonical element type of this array. |
401 | | /// |
402 | | /// The canonical element type describes the minimal accessible element in |
403 | | /// this array. Not all elements accessed, need to be of the very same type, |
404 | | /// but the allocation size of the type of the elements loaded/stored from/to |
405 | | /// this array needs to be a multiple of the allocation size of the canonical |
406 | | /// type. |
407 | | Type *ElementType; |
408 | | |
409 | | /// The isl id for the base pointer. |
410 | | isl::id Id; |
411 | | |
412 | | /// True if the newly allocated array is on heap. |
413 | | bool IsOnHeap = false; |
414 | | |
415 | | /// The sizes of each dimension as SCEV*. |
416 | | SmallVector<const SCEV *, 4> DimensionSizes; |
417 | | |
418 | | /// The sizes of each dimension as isl::pw_aff. |
419 | | SmallVector<isl::pw_aff, 4> DimensionSizesPw; |
420 | | |
421 | | /// The type of this scop array info object. |
422 | | /// |
423 | | /// We distinguish between SCALAR, PHI and ARRAY objects. |
424 | | MemoryKind Kind; |
425 | | |
426 | | /// The data layout of the module. |
427 | | const DataLayout &DL; |
428 | | |
429 | | /// The scop this SAI object belongs to. |
430 | | Scop &S; |
431 | | |
432 | | /// If this array models a Fortran array, then this points |
433 | | /// to the Fortran array descriptor. |
434 | | Value *FAD = nullptr; |
435 | | }; |
436 | | |
437 | | /// Represent memory accesses in statements. |
438 | | class MemoryAccess { |
439 | | friend class Scop; |
440 | | friend class ScopStmt; |
441 | | friend class ScopBuilder; |
442 | | |
443 | | public: |
444 | | /// The access type of a memory access |
445 | | /// |
446 | | /// There are three kind of access types: |
447 | | /// |
448 | | /// * A read access |
449 | | /// |
450 | | /// A certain set of memory locations are read and may be used for internal |
451 | | /// calculations. |
452 | | /// |
453 | | /// * A must-write access |
454 | | /// |
455 | | /// A certain set of memory locations is definitely written. The old value is |
456 | | /// replaced by a newly calculated value. The old value is not read or used at |
457 | | /// all. |
458 | | /// |
459 | | /// * A may-write access |
460 | | /// |
461 | | /// A certain set of memory locations may be written. The memory location may |
462 | | /// contain a new value if there is actually a write or the old value may |
463 | | /// remain, if no write happens. |
464 | | enum AccessType { |
465 | | READ = 0x1, |
466 | | MUST_WRITE = 0x2, |
467 | | MAY_WRITE = 0x3, |
468 | | }; |
469 | | |
470 | | /// Reduction access type |
471 | | /// |
472 | | /// Commutative and associative binary operations suitable for reductions |
473 | | enum ReductionType { |
474 | | RT_NONE, ///< Indicate no reduction at all |
475 | | RT_ADD, ///< Addition |
476 | | RT_MUL, ///< Multiplication |
477 | | RT_BOR, ///< Bitwise Or |
478 | | RT_BXOR, ///< Bitwise XOr |
479 | | RT_BAND, ///< Bitwise And |
480 | | }; |
481 | | |
482 | | private: |
483 | | /// A unique identifier for this memory access. |
484 | | /// |
485 | | /// The identifier is unique between all memory accesses belonging to the same |
486 | | /// scop statement. |
487 | | isl::id Id; |
488 | | |
489 | | /// What is modeled by this MemoryAccess. |
490 | | /// @see MemoryKind |
491 | | MemoryKind Kind; |
492 | | |
493 | | /// Whether it a reading or writing access, and if writing, whether it |
494 | | /// is conditional (MAY_WRITE). |
495 | | enum AccessType AccType; |
496 | | |
497 | | /// Reduction type for reduction like accesses, RT_NONE otherwise |
498 | | /// |
499 | | /// An access is reduction like if it is part of a load-store chain in which |
500 | | /// both access the same memory location (use the same LLVM-IR value |
501 | | /// as pointer reference). Furthermore, between the load and the store there |
502 | | /// is exactly one binary operator which is known to be associative and |
503 | | /// commutative. |
504 | | /// |
505 | | /// TODO: |
506 | | /// |
507 | | /// We can later lift the constraint that the same LLVM-IR value defines the |
508 | | /// memory location to handle scops such as the following: |
509 | | /// |
510 | | /// for i |
511 | | /// for j |
512 | | /// sum[i+j] = sum[i] + 3; |
513 | | /// |
514 | | /// Here not all iterations access the same memory location, but iterations |
515 | | /// for which j = 0 holds do. After lifting the equality check in ScopBuilder, |
516 | | /// subsequent transformations do not only need check if a statement is |
517 | | /// reduction like, but they also need to verify that that the reduction |
518 | | /// property is only exploited for statement instances that load from and |
519 | | /// store to the same data location. Doing so at dependence analysis time |
520 | | /// could allow us to handle the above example. |
521 | | ReductionType RedType = RT_NONE; |
522 | | |
523 | | /// Parent ScopStmt of this access. |
524 | | ScopStmt *Statement; |
525 | | |
526 | | /// The domain under which this access is not modeled precisely. |
527 | | /// |
528 | | /// The invalid domain for an access describes all parameter combinations |
529 | | /// under which the statement looks to be executed but is in fact not because |
530 | | /// some assumption/restriction makes the access invalid. |
531 | | isl::set InvalidDomain; |
532 | | |
533 | | // Properties describing the accessed array. |
534 | | // TODO: It might be possible to move them to ScopArrayInfo. |
535 | | // @{ |
536 | | |
537 | | /// The base address (e.g., A for A[i+j]). |
538 | | /// |
539 | | /// The #BaseAddr of a memory access of kind MemoryKind::Array is the base |
540 | | /// pointer of the memory access. |
541 | | /// The #BaseAddr of a memory access of kind MemoryKind::PHI or |
542 | | /// MemoryKind::ExitPHI is the PHI node itself. |
543 | | /// The #BaseAddr of a memory access of kind MemoryKind::Value is the |
544 | | /// instruction defining the value. |
545 | | AssertingVH<Value> BaseAddr; |
546 | | |
547 | | /// Type a single array element wrt. this access. |
548 | | Type *ElementType; |
549 | | |
550 | | /// Size of each dimension of the accessed array. |
551 | | SmallVector<const SCEV *, 4> Sizes; |
552 | | // @} |
553 | | |
554 | | // Properties describing the accessed element. |
555 | | // @{ |
556 | | |
557 | | /// The access instruction of this memory access. |
558 | | /// |
559 | | /// For memory accesses of kind MemoryKind::Array the access instruction is |
560 | | /// the Load or Store instruction performing the access. |
561 | | /// |
562 | | /// For memory accesses of kind MemoryKind::PHI or MemoryKind::ExitPHI the |
563 | | /// access instruction of a load access is the PHI instruction. The access |
564 | | /// instruction of a PHI-store is the incoming's block's terminator |
565 | | /// instruction. |
566 | | /// |
567 | | /// For memory accesses of kind MemoryKind::Value the access instruction of a |
568 | | /// load access is nullptr because generally there can be multiple |
569 | | /// instructions in the statement using the same llvm::Value. The access |
570 | | /// instruction of a write access is the instruction that defines the |
571 | | /// llvm::Value. |
572 | | Instruction *AccessInstruction = nullptr; |
573 | | |
574 | | /// Incoming block and value of a PHINode. |
575 | | SmallVector<std::pair<BasicBlock *, Value *>, 4> Incoming; |
576 | | |
577 | | /// The value associated with this memory access. |
578 | | /// |
579 | | /// - For array memory accesses (MemoryKind::Array) it is the loaded result |
580 | | /// or the stored value. If the access instruction is a memory intrinsic it |
581 | | /// the access value is also the memory intrinsic. |
582 | | /// - For accesses of kind MemoryKind::Value it is the access instruction |
583 | | /// itself. |
584 | | /// - For accesses of kind MemoryKind::PHI or MemoryKind::ExitPHI it is the |
585 | | /// PHI node itself (for both, READ and WRITE accesses). |
586 | | /// |
587 | | AssertingVH<Value> AccessValue; |
588 | | |
589 | | /// Are all the subscripts affine expression? |
590 | | bool IsAffine = true; |
591 | | |
592 | | /// Subscript expression for each dimension. |
593 | | SmallVector<const SCEV *, 4> Subscripts; |
594 | | |
595 | | /// Relation from statement instances to the accessed array elements. |
596 | | /// |
597 | | /// In the common case this relation is a function that maps a set of loop |
598 | | /// indices to the memory address from which a value is loaded/stored: |
599 | | /// |
600 | | /// for i |
601 | | /// for j |
602 | | /// S: A[i + 3 j] = ... |
603 | | /// |
604 | | /// => { S[i,j] -> A[i + 3j] } |
605 | | /// |
606 | | /// In case the exact access function is not known, the access relation may |
607 | | /// also be a one to all mapping { S[i,j] -> A[o] } describing that any |
608 | | /// element accessible through A might be accessed. |
609 | | /// |
610 | | /// In case of an access to a larger element belonging to an array that also |
611 | | /// contains smaller elements, the access relation models the larger access |
612 | | /// with multiple smaller accesses of the size of the minimal array element |
613 | | /// type: |
614 | | /// |
615 | | /// short *A; |
616 | | /// |
617 | | /// for i |
618 | | /// S: A[i] = *((double*)&A[4 * i]); |
619 | | /// |
620 | | /// => { S[i] -> A[i]; S[i] -> A[o] : 4i <= o <= 4i + 3 } |
621 | | isl::map AccessRelation; |
622 | | |
623 | | /// Updated access relation read from JSCOP file. |
624 | | isl::map NewAccessRelation; |
625 | | |
626 | | /// Fortran arrays whose sizes are not statically known are stored in terms |
627 | | /// of a descriptor struct. This maintains a raw pointer to the memory, |
628 | | /// along with auxiliary fields with information such as dimensions. |
629 | | /// We hold a reference to the descriptor corresponding to a MemoryAccess |
630 | | /// into a Fortran array. FAD for "Fortran Array Descriptor" |
631 | | AssertingVH<Value> FAD; |
632 | | // @} |
633 | | |
634 | | isl::basic_map createBasicAccessMap(ScopStmt *Statement); |
635 | | |
636 | | void assumeNoOutOfBound(); |
637 | | |
638 | | /// Compute bounds on an over approximated access relation. |
639 | | /// |
640 | | /// @param ElementSize The size of one element accessed. |
641 | | void computeBoundsOnAccessRelation(unsigned ElementSize); |
642 | | |
643 | | /// Get the original access function as read from IR. |
644 | | isl::map getOriginalAccessRelation() const; |
645 | | |
646 | | /// Return the space in which the access relation lives in. |
647 | | isl::space getOriginalAccessRelationSpace() const; |
648 | | |
649 | | /// Get the new access function imported or set by a pass |
650 | | isl::map getNewAccessRelation() const; |
651 | | |
652 | | /// Fold the memory access to consider parametric offsets |
653 | | /// |
654 | | /// To recover memory accesses with array size parameters in the subscript |
655 | | /// expression we post-process the delinearization results. |
656 | | /// |
657 | | /// We would normally recover from an access A[exp0(i) * N + exp1(i)] into an |
658 | | /// array A[][N] the 2D access A[exp0(i)][exp1(i)]. However, another valid |
659 | | /// delinearization is A[exp0(i) - 1][exp1(i) + N] which - depending on the |
660 | | /// range of exp1(i) - may be preferable. Specifically, for cases where we |
661 | | /// know exp1(i) is negative, we want to choose the latter expression. |
662 | | /// |
663 | | /// As we commonly do not have any information about the range of exp1(i), |
664 | | /// we do not choose one of the two options, but instead create a piecewise |
665 | | /// access function that adds the (-1, N) offsets as soon as exp1(i) becomes |
666 | | /// negative. For a 2D array such an access function is created by applying |
667 | | /// the piecewise map: |
668 | | /// |
669 | | /// [i,j] -> [i, j] : j >= 0 |
670 | | /// [i,j] -> [i-1, j+N] : j < 0 |
671 | | /// |
672 | | /// We can generalize this mapping to arbitrary dimensions by applying this |
673 | | /// piecewise mapping pairwise from the rightmost to the leftmost access |
674 | | /// dimension. It would also be possible to cover a wider range by introducing |
675 | | /// more cases and adding multiple of Ns to these cases. However, this has |
676 | | /// not yet been necessary. |
677 | | /// The introduction of different cases necessarily complicates the memory |
678 | | /// access function, but cases that can be statically proven to not happen |
679 | | /// will be eliminated later on. |
680 | | void foldAccessRelation(); |
681 | | |
682 | | /// Create the access relation for the underlying memory intrinsic. |
683 | | void buildMemIntrinsicAccessRelation(); |
684 | | |
685 | | /// Assemble the access relation from all available information. |
686 | | /// |
687 | | /// In particular, used the information passes in the constructor and the |
688 | | /// parent ScopStmt set by setStatment(). |
689 | | /// |
690 | | /// @param SAI Info object for the accessed array. |
691 | | void buildAccessRelation(const ScopArrayInfo *SAI); |
692 | | |
693 | | /// Carry index overflows of dimensions with constant size to the next higher |
694 | | /// dimension. |
695 | | /// |
696 | | /// For dimensions that have constant size, modulo the index by the size and |
697 | | /// add up the carry (floored division) to the next higher dimension. This is |
698 | | /// how overflow is defined in row-major order. |
699 | | /// It happens e.g. when ScalarEvolution computes the offset to the base |
700 | | /// pointer and would algebraically sum up all lower dimensions' indices of |
701 | | /// constant size. |
702 | | /// |
703 | | /// Example: |
704 | | /// float (*A)[4]; |
705 | | /// A[1][6] -> A[2][2] |
706 | | void wrapConstantDimensions(); |
707 | | |
708 | | public: |
709 | | /// Create a new MemoryAccess. |
710 | | /// |
711 | | /// @param Stmt The parent statement. |
712 | | /// @param AccessInst The instruction doing the access. |
713 | | /// @param BaseAddr The accessed array's address. |
714 | | /// @param ElemType The type of the accessed array elements. |
715 | | /// @param AccType Whether read or write access. |
716 | | /// @param IsAffine Whether the subscripts are affine expressions. |
717 | | /// @param Kind The kind of memory accessed. |
718 | | /// @param Subscripts Subscript expressions |
719 | | /// @param Sizes Dimension lengths of the accessed array. |
720 | | MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst, AccessType AccType, |
721 | | Value *BaseAddress, Type *ElemType, bool Affine, |
722 | | ArrayRef<const SCEV *> Subscripts, ArrayRef<const SCEV *> Sizes, |
723 | | Value *AccessValue, MemoryKind Kind); |
724 | | |
725 | | /// Create a new MemoryAccess that corresponds to @p AccRel. |
726 | | /// |
727 | | /// Along with @p Stmt and @p AccType it uses information about dimension |
728 | | /// lengths of the accessed array, the type of the accessed array elements, |
729 | | /// the name of the accessed array that is derived from the object accessible |
730 | | /// via @p AccRel. |
731 | | /// |
732 | | /// @param Stmt The parent statement. |
733 | | /// @param AccType Whether read or write access. |
734 | | /// @param AccRel The access relation that describes the memory access. |
735 | | MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel); |
736 | | |
737 | | MemoryAccess(const MemoryAccess &) = delete; |
738 | | MemoryAccess &operator=(const MemoryAccess &) = delete; |
739 | | ~MemoryAccess(); |
740 | | |
741 | | /// Add a new incoming block/value pairs for this PHI/ExitPHI access. |
742 | | /// |
743 | | /// @param IncomingBlock The PHI's incoming block. |
744 | | /// @param IncomingValue The value when reaching the PHI from the @p |
745 | | /// IncomingBlock. |
746 | 514 | void addIncoming(BasicBlock *IncomingBlock, Value *IncomingValue) { |
747 | 514 | assert(!isRead()); |
748 | 514 | assert(isAnyPHIKind()); |
749 | 514 | Incoming.emplace_back(std::make_pair(IncomingBlock, IncomingValue)); |
750 | 514 | } |
751 | | |
752 | | /// Return the list of possible PHI/ExitPHI values. |
753 | | /// |
754 | | /// After code generation moves some PHIs around during region simplification, |
755 | | /// we cannot reliably locate the original PHI node and its incoming values |
756 | | /// anymore. For this reason we remember these explicitly for all PHI-kind |
757 | | /// accesses. |
758 | 256 | ArrayRef<std::pair<BasicBlock *, Value *>> getIncoming() const { |
759 | 256 | assert(isAnyPHIKind()); |
760 | 256 | return Incoming; |
761 | 256 | } |
762 | | |
763 | | /// Get the type of a memory access. |
764 | 0 | enum AccessType getType() { return AccType; } |
765 | | |
766 | | /// Is this a reduction like access? |
767 | 3.12k | bool isReductionLike() const { return RedType != RT_NONE; } |
768 | | |
769 | | /// Is this a read memory access? |
770 | 26.9k | bool isRead() const { return AccType == MemoryAccess::READ; } |
771 | | |
772 | | /// Is this a must-write memory access? |
773 | 13.3k | bool isMustWrite() const { return AccType == MemoryAccess::MUST_WRITE; } |
774 | | |
775 | | /// Is this a may-write memory access? |
776 | 7.78k | bool isMayWrite() const { return AccType == MemoryAccess::MAY_WRITE; } |
777 | | |
778 | | /// Is this a write memory access? |
779 | 12.2k | bool isWrite() const { return isMustWrite() || isMayWrite()6.38k ; } |
780 | | |
781 | | /// Is this a memory intrinsic access (memcpy, memset, memmove)? |
782 | 486 | bool isMemoryIntrinsic() const { |
783 | 486 | return isa<MemIntrinsic>(getAccessInstruction()); |
784 | 486 | } |
785 | | |
786 | | /// Check if a new access relation was imported or set by a pass. |
787 | 24.3k | bool hasNewAccessRelation() const { return !NewAccessRelation.is_null(); } |
788 | | |
789 | | /// Return the newest access relation of this access. |
790 | | /// |
791 | | /// There are two possibilities: |
792 | | /// 1) The original access relation read from the LLVM-IR. |
793 | | /// 2) A new access relation imported from a json file or set by another |
794 | | /// pass (e.g., for privatization). |
795 | | /// |
796 | | /// As 2) is by construction "newer" than 1) we return the new access |
797 | | /// relation if present. |
798 | | /// |
799 | 17.8k | isl::map getLatestAccessRelation() const { |
800 | 17.8k | return hasNewAccessRelation() ? getNewAccessRelation()539 |
801 | 17.8k | : getOriginalAccessRelation()17.3k ; |
802 | 17.8k | } |
803 | | |
804 | | /// Old name of getLatestAccessRelation(). |
805 | 16.9k | isl::map getAccessRelation() const { return getLatestAccessRelation(); } |
806 | | |
807 | | /// Get an isl map describing the memory address accessed. |
808 | | /// |
809 | | /// In most cases the memory address accessed is well described by the access |
810 | | /// relation obtained with getAccessRelation. However, in case of arrays |
811 | | /// accessed with types of different size the access relation maps one access |
812 | | /// to multiple smaller address locations. This method returns an isl map that |
813 | | /// relates each dynamic statement instance to the unique memory location |
814 | | /// that is loaded from / stored to. |
815 | | /// |
816 | | /// For an access relation { S[i] -> A[o] : 4i <= o <= 4i + 3 } this method |
817 | | /// will return the address function { S[i] -> A[4i] }. |
818 | | /// |
819 | | /// @returns The address function for this memory access. |
820 | | isl::map getAddressFunction() const; |
821 | | |
822 | | /// Return the access relation after the schedule was applied. |
823 | | isl::pw_multi_aff |
824 | | applyScheduleToAccessRelation(isl::union_map Schedule) const; |
825 | | |
826 | | /// Get an isl string representing the access function read from IR. |
827 | | std::string getOriginalAccessRelationStr() const; |
828 | | |
829 | | /// Get an isl string representing a new access function, if available. |
830 | | std::string getNewAccessRelationStr() const; |
831 | | |
832 | | /// Get an isl string representing the latest access relation. |
833 | | std::string getAccessRelationStr() const; |
834 | | |
835 | | /// Get the original base address of this access (e.g. A for A[i+j]) when |
836 | | /// detected. |
837 | | /// |
838 | | /// This address may differ from the base address referenced by the original |
839 | | /// ScopArrayInfo to which this array belongs, as this memory access may |
840 | | /// have been canonicalized to a ScopArrayInfo which has a different but |
841 | | /// identically-valued base pointer in case invariant load hoisting is |
842 | | /// enabled. |
843 | 6.64k | Value *getOriginalBaseAddr() const { return BaseAddr; } |
844 | | |
845 | | /// Get the detection-time base array isl::id for this access. |
846 | | isl::id getOriginalArrayId() const; |
847 | | |
848 | | /// Get the base array isl::id for this access, modifiable through |
849 | | /// setNewAccessRelation(). |
850 | | isl::id getLatestArrayId() const; |
851 | | |
852 | | /// Old name of getOriginalArrayId(). |
853 | 23.8k | isl::id getArrayId() const { return getOriginalArrayId(); } |
854 | | |
855 | | /// Get the detection-time ScopArrayInfo object for the base address. |
856 | | const ScopArrayInfo *getOriginalScopArrayInfo() const; |
857 | | |
858 | | /// Get the ScopArrayInfo object for the base address, or the one set |
859 | | /// by setNewAccessRelation(). |
860 | | const ScopArrayInfo *getLatestScopArrayInfo() const; |
861 | | |
862 | | /// Legacy name of getOriginalScopArrayInfo(). |
863 | 18.7k | const ScopArrayInfo *getScopArrayInfo() const { |
864 | 18.7k | return getOriginalScopArrayInfo(); |
865 | 18.7k | } |
866 | | |
867 | | /// Return a string representation of the access's reduction type. |
868 | | const std::string getReductionOperatorStr() const; |
869 | | |
870 | | /// Return a string representation of the reduction type @p RT. |
871 | | static const std::string getReductionOperatorStr(ReductionType RT); |
872 | | |
873 | | /// Return the element type of the accessed array wrt. this access. |
874 | 9.60k | Type *getElementType() const { return ElementType; } |
875 | | |
876 | | /// Return the access value of this memory access. |
877 | 3.65k | Value *getAccessValue() const { return AccessValue; } |
878 | | |
879 | | /// Return llvm::Value that is stored by this access, if available. |
880 | | /// |
881 | | /// PHI nodes may not have a unique value available that is stored, as in |
882 | | /// case of region statements one out of possibly several llvm::Values |
883 | | /// might be stored. In this case nullptr is returned. |
884 | 273 | Value *tryGetValueStored() { |
885 | 273 | assert(isWrite() && "Only write statement store values"); |
886 | 273 | if (isAnyPHIKind()) { |
887 | 16 | if (Incoming.size() == 1) |
888 | 14 | return Incoming[0].second; |
889 | 2 | return nullptr; |
890 | 2 | } |
891 | 257 | return AccessValue; |
892 | 257 | } |
893 | | |
894 | | /// Return the access instruction of this memory access. |
895 | 43.8k | Instruction *getAccessInstruction() const { return AccessInstruction; } |
896 | | |
897 | | /// Return the number of access function subscript. |
898 | 5 | unsigned getNumSubscripts() const { return Subscripts.size(); } |
899 | | |
900 | | /// Return the access function subscript in the dimension @p Dim. |
901 | 2.96k | const SCEV *getSubscript(unsigned Dim) const { return Subscripts[Dim]; } |
902 | | |
903 | | /// Compute the isl representation for the SCEV @p E wrt. this access. |
904 | | /// |
905 | | /// Note that this function will also adjust the invalid context accordingly. |
906 | | isl::pw_aff getPwAff(const SCEV *E); |
907 | | |
908 | | /// Get the invalid domain for this access. |
909 | 361 | isl::set getInvalidDomain() const { return InvalidDomain; } |
910 | | |
911 | | /// Get the invalid context for this access. |
912 | 361 | isl::set getInvalidContext() const { return getInvalidDomain().params(); } |
913 | | |
914 | | /// Get the stride of this memory access in the specified Schedule. Schedule |
915 | | /// is a map from the statement to a schedule where the innermost dimension is |
916 | | /// the dimension of the innermost loop containing the statement. |
917 | | isl::set getStride(isl::map Schedule) const; |
918 | | |
919 | | /// Get the FortranArrayDescriptor corresponding to this memory access if |
920 | | /// it exists, and nullptr otherwise. |
921 | 4.72k | Value *getFortranArrayDescriptor() const { return this->FAD; } |
922 | | |
923 | | /// Is the stride of the access equal to a certain width? Schedule is a map |
924 | | /// from the statement to a schedule where the innermost dimension is the |
925 | | /// dimension of the innermost loop containing the statement. |
926 | | bool isStrideX(isl::map Schedule, int StrideWidth) const; |
927 | | |
928 | | /// Is consecutive memory accessed for a given statement instance set? |
929 | | /// Schedule is a map from the statement to a schedule where the innermost |
930 | | /// dimension is the dimension of the innermost loop containing the |
931 | | /// statement. |
932 | | bool isStrideOne(isl::map Schedule) const; |
933 | | |
934 | | /// Is always the same memory accessed for a given statement instance set? |
935 | | /// Schedule is a map from the statement to a schedule where the innermost |
936 | | /// dimension is the dimension of the innermost loop containing the |
937 | | /// statement. |
938 | | bool isStrideZero(isl::map Schedule) const; |
939 | | |
940 | | /// Return the kind when this access was first detected. |
941 | 65.0k | MemoryKind getOriginalKind() const { |
942 | 65.0k | assert(!getOriginalScopArrayInfo() /* not yet initialized */ || |
943 | 65.0k | getOriginalScopArrayInfo()->getKind() == Kind); |
944 | 65.0k | return Kind; |
945 | 65.0k | } |
946 | | |
947 | | /// Return the kind considering a potential setNewAccessRelation. |
948 | 2.22k | MemoryKind getLatestKind() const { |
949 | 2.22k | return getLatestScopArrayInfo()->getKind(); |
950 | 2.22k | } |
951 | | |
952 | | /// Whether this is an access of an explicit load or store in the IR. |
953 | 16.3k | bool isOriginalArrayKind() const { |
954 | 16.3k | return getOriginalKind() == MemoryKind::Array; |
955 | 16.3k | } |
956 | | |
957 | | /// Whether storage memory is either an custom .s2a/.phiops alloca |
958 | | /// (false) or an existing pointer into an array (true). |
959 | 1.72k | bool isLatestArrayKind() const { |
960 | 1.72k | return getLatestKind() == MemoryKind::Array; |
961 | 1.72k | } |
962 | | |
963 | | /// Old name of isOriginalArrayKind. |
964 | 12.3k | bool isArrayKind() const { return isOriginalArrayKind(); } |
965 | | |
966 | | /// Whether this access is an array to a scalar memory object, without |
967 | | /// considering changes by setNewAccessRelation. |
968 | | /// |
969 | | /// Scalar accesses are accesses to MemoryKind::Value, MemoryKind::PHI or |
970 | | /// MemoryKind::ExitPHI. |
971 | 8.82k | bool isOriginalScalarKind() const { |
972 | 8.82k | return getOriginalKind() != MemoryKind::Array; |
973 | 8.82k | } |
974 | | |
975 | | /// Whether this access is an array to a scalar memory object, also |
976 | | /// considering changes by setNewAccessRelation. |
977 | 301 | bool isLatestScalarKind() const { |
978 | 301 | return getLatestKind() != MemoryKind::Array; |
979 | 301 | } |
980 | | |
981 | | /// Old name of isOriginalScalarKind. |
982 | 7.82k | bool isScalarKind() const { return isOriginalScalarKind(); } |
983 | | |
984 | | /// Was this MemoryAccess detected as a scalar dependences? |
985 | 15.7k | bool isOriginalValueKind() const { |
986 | 15.7k | return getOriginalKind() == MemoryKind::Value; |
987 | 15.7k | } |
988 | | |
989 | | /// Is this MemoryAccess currently modeling scalar dependences? |
990 | 73 | bool isLatestValueKind() const { |
991 | 73 | return getLatestKind() == MemoryKind::Value; |
992 | 73 | } |
993 | | |
994 | | /// Old name of isOriginalValueKind(). |
995 | 6.58k | bool isValueKind() const { return isOriginalValueKind(); } |
996 | | |
997 | | /// Was this MemoryAccess detected as a special PHI node access? |
998 | 14.6k | bool isOriginalPHIKind() const { |
999 | 14.6k | return getOriginalKind() == MemoryKind::PHI; |
1000 | 14.6k | } |
1001 | | |
1002 | | /// Is this MemoryAccess modeling special PHI node accesses, also |
1003 | | /// considering a potential change by setNewAccessRelation? |
1004 | 60 | bool isLatestPHIKind() const { return getLatestKind() == MemoryKind::PHI; } |
1005 | | |
1006 | | /// Old name of isOriginalPHIKind. |
1007 | 4.81k | bool isPHIKind() const { return isOriginalPHIKind(); } |
1008 | | |
1009 | | /// Was this MemoryAccess detected as the accesses of a PHI node in the |
1010 | | /// SCoP's exit block? |
1011 | 9.56k | bool isOriginalExitPHIKind() const { |
1012 | 9.56k | return getOriginalKind() == MemoryKind::ExitPHI; |
1013 | 9.56k | } |
1014 | | |
1015 | | /// Is this MemoryAccess modeling the accesses of a PHI node in the |
1016 | | /// SCoP's exit block? Can be changed to an array access using |
1017 | | /// setNewAccessRelation(). |
1018 | 62 | bool isLatestExitPHIKind() const { |
1019 | 62 | return getLatestKind() == MemoryKind::ExitPHI; |
1020 | 62 | } |
1021 | | |
1022 | | /// Old name of isOriginalExitPHIKind(). |
1023 | 4.19k | bool isExitPHIKind() const { return isOriginalExitPHIKind(); } |
1024 | | |
1025 | | /// Was this access detected as one of the two PHI types? |
1026 | 6.87k | bool isOriginalAnyPHIKind() const { |
1027 | 6.87k | return isOriginalPHIKind() || isOriginalExitPHIKind()5.36k ; |
1028 | 6.87k | } |
1029 | | |
1030 | | /// Does this access originate from one of the two PHI types? Can be |
1031 | | /// changed to an array access using setNewAccessRelation(). |
1032 | 60 | bool isLatestAnyPHIKind() const { |
1033 | 60 | return isLatestPHIKind() || isLatestExitPHIKind()58 ; |
1034 | 60 | } |
1035 | | |
1036 | | /// Old name of isOriginalAnyPHIKind(). |
1037 | 1.36k | bool isAnyPHIKind() const { return isOriginalAnyPHIKind(); } |
1038 | | |
1039 | | /// Get the statement that contains this memory access. |
1040 | 26.3k | ScopStmt *getStatement() const { return Statement; } |
1041 | | |
1042 | | /// Get the reduction type of this access |
1043 | 2.37k | ReductionType getReductionType() const { return RedType; } |
1044 | | |
1045 | | /// Set the array descriptor corresponding to the Array on which the |
1046 | | /// memory access is performed. |
1047 | | void setFortranArrayDescriptor(Value *FAD); |
1048 | | |
1049 | | /// Update the original access relation. |
1050 | | /// |
1051 | | /// We need to update the original access relation during scop construction, |
1052 | | /// when unifying the memory accesses that access the same scop array info |
1053 | | /// object. After the scop has been constructed, the original access relation |
1054 | | /// should not be changed any more. Instead setNewAccessRelation should |
1055 | | /// be called. |
1056 | | void setAccessRelation(isl::map AccessRelation); |
1057 | | |
1058 | | /// Set the updated access relation read from JSCOP file. |
1059 | | void setNewAccessRelation(isl::map NewAccessRelation); |
1060 | | |
1061 | | /// Return whether the MemoryyAccess is a partial access. That is, the access |
1062 | | /// is not executed in some instances of the parent statement's domain. |
1063 | | bool isLatestPartialAccess() const; |
1064 | | |
1065 | | /// Mark this a reduction like access |
1066 | 584 | void markAsReductionLike(ReductionType RT) { RedType = RT; } |
1067 | | |
1068 | | /// Align the parameters in the access relation to the scop context |
1069 | | void realignParams(); |
1070 | | |
1071 | | /// Update the dimensionality of the memory access. |
1072 | | /// |
1073 | | /// During scop construction some memory accesses may not be constructed with |
1074 | | /// their full dimensionality, but outer dimensions may have been omitted if |
1075 | | /// they took the value 'zero'. By updating the dimensionality of the |
1076 | | /// statement we add additional zero-valued dimensions to match the |
1077 | | /// dimensionality of the ScopArrayInfo object that belongs to this memory |
1078 | | /// access. |
1079 | | void updateDimensionality(); |
1080 | | |
1081 | | /// Get identifier for the memory access. |
1082 | | /// |
1083 | | /// This identifier is unique for all accesses that belong to the same scop |
1084 | | /// statement. |
1085 | | isl::id getId() const; |
1086 | | |
1087 | | /// Print the MemoryAccess. |
1088 | | /// |
1089 | | /// @param OS The output stream the MemoryAccess is printed to. |
1090 | | void print(raw_ostream &OS) const; |
1091 | | |
1092 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
1093 | | /// Print the MemoryAccess to stderr. |
1094 | | void dump() const; |
1095 | | #endif |
1096 | | |
1097 | | /// Is the memory access affine? |
1098 | 10.8k | bool isAffine() const { return IsAffine; } |
1099 | | }; |
1100 | | |
1101 | | raw_ostream &operator<<(raw_ostream &OS, MemoryAccess::ReductionType RT); |
1102 | | |
1103 | | /// Ordered list type to hold accesses. |
1104 | | using MemoryAccessList = std::forward_list<MemoryAccess *>; |
1105 | | |
1106 | | /// Helper structure for invariant memory accesses. |
1107 | | struct InvariantAccess { |
1108 | | /// The memory access that is (partially) invariant. |
1109 | | MemoryAccess *MA; |
1110 | | |
1111 | | /// The context under which the access is not invariant. |
1112 | | isl::set NonHoistableCtx; |
1113 | | }; |
1114 | | |
1115 | | /// Ordered container type to hold invariant accesses. |
1116 | | using InvariantAccessesTy = SmallVector<InvariantAccess, 8>; |
1117 | | |
1118 | | /// Type for equivalent invariant accesses and their domain context. |
1119 | | struct InvariantEquivClassTy { |
1120 | | /// The pointer that identifies this equivalence class |
1121 | | const SCEV *IdentifyingPointer; |
1122 | | |
1123 | | /// Memory accesses now treated invariant |
1124 | | /// |
1125 | | /// These memory accesses access the pointer location that identifies |
1126 | | /// this equivalence class. They are treated as invariant and hoisted during |
1127 | | /// code generation. |
1128 | | MemoryAccessList InvariantAccesses; |
1129 | | |
1130 | | /// The execution context under which the memory location is accessed |
1131 | | /// |
1132 | | /// It is the union of the execution domains of the memory accesses in the |
1133 | | /// InvariantAccesses list. |
1134 | | isl::set ExecutionContext; |
1135 | | |
1136 | | /// The type of the invariant access |
1137 | | /// |
1138 | | /// It is used to differentiate between differently typed invariant loads from |
1139 | | /// the same location. |
1140 | | Type *AccessType; |
1141 | | }; |
1142 | | |
1143 | | /// Type for invariant accesses equivalence classes. |
1144 | | using InvariantEquivClassesTy = SmallVector<InvariantEquivClassTy, 8>; |
1145 | | |
1146 | | /// Statement of the Scop |
1147 | | /// |
1148 | | /// A Scop statement represents an instruction in the Scop. |
1149 | | /// |
1150 | | /// It is further described by its iteration domain, its schedule and its data |
1151 | | /// accesses. |
1152 | | /// At the moment every statement represents a single basic block of LLVM-IR. |
1153 | | class ScopStmt { |
1154 | | friend class ScopBuilder; |
1155 | | |
1156 | | public: |
1157 | | /// Create the ScopStmt from a BasicBlock. |
1158 | | ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name, Loop *SurroundingLoop, |
1159 | | std::vector<Instruction *> Instructions); |
1160 | | |
1161 | | /// Create an overapproximating ScopStmt for the region @p R. |
1162 | | /// |
1163 | | /// @param EntryBlockInstructions The list of instructions that belong to the |
1164 | | /// entry block of the region statement. |
1165 | | /// Instructions are only tracked for entry |
1166 | | /// blocks for now. We currently do not allow |
1167 | | /// to modify the instructions of blocks later |
1168 | | /// in the region statement. |
1169 | | ScopStmt(Scop &parent, Region &R, StringRef Name, Loop *SurroundingLoop, |
1170 | | std::vector<Instruction *> EntryBlockInstructions); |
1171 | | |
1172 | | /// Create a copy statement. |
1173 | | /// |
1174 | | /// @param Stmt The parent statement. |
1175 | | /// @param SourceRel The source location. |
1176 | | /// @param TargetRel The target location. |
1177 | | /// @param Domain The original domain under which the copy statement would |
1178 | | /// be executed. |
1179 | | ScopStmt(Scop &parent, isl::map SourceRel, isl::map TargetRel, |
1180 | | isl::set Domain); |
1181 | | |
1182 | | ScopStmt(const ScopStmt &) = delete; |
1183 | | const ScopStmt &operator=(const ScopStmt &) = delete; |
1184 | | ~ScopStmt(); |
1185 | | |
1186 | | private: |
1187 | | /// Polyhedral description |
1188 | | //@{ |
1189 | | |
1190 | | /// The Scop containing this ScopStmt. |
1191 | | Scop &Parent; |
1192 | | |
1193 | | /// The domain under which this statement is not modeled precisely. |
1194 | | /// |
1195 | | /// The invalid domain for a statement describes all parameter combinations |
1196 | | /// under which the statement looks to be executed but is in fact not because |
1197 | | /// some assumption/restriction makes the statement/scop invalid. |
1198 | | isl::set InvalidDomain; |
1199 | | |
1200 | | /// The iteration domain describes the set of iterations for which this |
1201 | | /// statement is executed. |
1202 | | /// |
1203 | | /// Example: |
1204 | | /// for (i = 0; i < 100 + b; ++i) |
1205 | | /// for (j = 0; j < i; ++j) |
1206 | | /// S(i,j); |
1207 | | /// |
1208 | | /// 'S' is executed for different values of i and j. A vector of all |
1209 | | /// induction variables around S (i, j) is called iteration vector. |
1210 | | /// The domain describes the set of possible iteration vectors. |
1211 | | /// |
1212 | | /// In this case it is: |
1213 | | /// |
1214 | | /// Domain: 0 <= i <= 100 + b |
1215 | | /// 0 <= j <= i |
1216 | | /// |
1217 | | /// A pair of statement and iteration vector (S, (5,3)) is called statement |
1218 | | /// instance. |
1219 | | isl::set Domain; |
1220 | | |
1221 | | /// The memory accesses of this statement. |
1222 | | /// |
1223 | | /// The only side effects of a statement are its memory accesses. |
1224 | | using MemoryAccessVec = SmallVector<MemoryAccess *, 8>; |
1225 | | MemoryAccessVec MemAccs; |
1226 | | |
1227 | | /// Mapping from instructions to (scalar) memory accesses. |
1228 | | DenseMap<const Instruction *, MemoryAccessList> InstructionToAccess; |
1229 | | |
1230 | | /// The set of values defined elsewhere required in this ScopStmt and |
1231 | | /// their MemoryKind::Value READ MemoryAccesses. |
1232 | | DenseMap<Value *, MemoryAccess *> ValueReads; |
1233 | | |
1234 | | /// The set of values defined in this ScopStmt that are required |
1235 | | /// elsewhere, mapped to their MemoryKind::Value WRITE MemoryAccesses. |
1236 | | DenseMap<Instruction *, MemoryAccess *> ValueWrites; |
1237 | | |
1238 | | /// Map from PHI nodes to its incoming value when coming from this |
1239 | | /// statement. |
1240 | | /// |
1241 | | /// Non-affine subregions can have multiple exiting blocks that are incoming |
1242 | | /// blocks of the PHI nodes. This map ensures that there is only one write |
1243 | | /// operation for the complete subregion. A PHI selecting the relevant value |
1244 | | /// will be inserted. |
1245 | | DenseMap<PHINode *, MemoryAccess *> PHIWrites; |
1246 | | |
1247 | | /// Map from PHI nodes to its read access in this statement. |
1248 | | DenseMap<PHINode *, MemoryAccess *> PHIReads; |
1249 | | |
1250 | | //@} |
1251 | | |
1252 | | /// A SCoP statement represents either a basic block (affine/precise case) or |
1253 | | /// a whole region (non-affine case). |
1254 | | /// |
1255 | | /// Only one of the following two members will therefore be set and indicate |
1256 | | /// which kind of statement this is. |
1257 | | /// |
1258 | | ///{ |
1259 | | |
1260 | | /// The BasicBlock represented by this statement (in the affine case). |
1261 | | BasicBlock *BB = nullptr; |
1262 | | |
1263 | | /// The region represented by this statement (in the non-affine case). |
1264 | | Region *R = nullptr; |
1265 | | |
1266 | | ///} |
1267 | | |
1268 | | /// The isl AST build for the new generated AST. |
1269 | | isl::ast_build Build; |
1270 | | |
1271 | | SmallVector<Loop *, 4> NestLoops; |
1272 | | |
1273 | | std::string BaseName; |
1274 | | |
1275 | | /// The closest loop that contains this statement. |
1276 | | Loop *SurroundingLoop; |
1277 | | |
1278 | | /// Vector for Instructions in this statement. |
1279 | | std::vector<Instruction *> Instructions; |
1280 | | |
1281 | | /// Remove @p MA from dictionaries pointing to them. |
1282 | | void removeAccessData(MemoryAccess *MA); |
1283 | | |
1284 | | public: |
1285 | | /// Get an isl_ctx pointer. |
1286 | | isl::ctx getIslCtx() const; |
1287 | | |
1288 | | /// Get the iteration domain of this ScopStmt. |
1289 | | /// |
1290 | | /// @return The iteration domain of this ScopStmt. |
1291 | | isl::set getDomain() const; |
1292 | | |
1293 | | /// Get the space of the iteration domain |
1294 | | /// |
1295 | | /// @return The space of the iteration domain |
1296 | | isl::space getDomainSpace() const; |
1297 | | |
1298 | | /// Get the id of the iteration domain space |
1299 | | /// |
1300 | | /// @return The id of the iteration domain space |
1301 | | isl::id getDomainId() const; |
1302 | | |
1303 | | /// Get an isl string representing this domain. |
1304 | | std::string getDomainStr() const; |
1305 | | |
1306 | | /// Get the schedule function of this ScopStmt. |
1307 | | /// |
1308 | | /// @return The schedule function of this ScopStmt, if it does not contain |
1309 | | /// extension nodes, and nullptr, otherwise. |
1310 | | isl::map getSchedule() const; |
1311 | | |
1312 | | /// Get an isl string representing this schedule. |
1313 | | /// |
1314 | | /// @return An isl string representing this schedule, if it does not contain |
1315 | | /// extension nodes, and an empty string, otherwise. |
1316 | | std::string getScheduleStr() const; |
1317 | | |
1318 | | /// Get the invalid domain for this statement. |
1319 | 5.02k | isl::set getInvalidDomain() const { return InvalidDomain; } |
1320 | | |
1321 | | /// Get the invalid context for this statement. |
1322 | 247 | isl::set getInvalidContext() const { return getInvalidDomain().params(); } |
1323 | | |
1324 | | /// Set the invalid context for this statement to @p ID. |
1325 | | void setInvalidDomain(isl::set ID); |
1326 | | |
1327 | | /// Get the BasicBlock represented by this ScopStmt (if any). |
1328 | | /// |
1329 | | /// @return The BasicBlock represented by this ScopStmt, or null if the |
1330 | | /// statement represents a region. |
1331 | 61.5k | BasicBlock *getBasicBlock() const { return BB; } |
1332 | | |
1333 | | /// Return true if this statement represents a single basic block. |
1334 | 74.9k | bool isBlockStmt() const { return BB != nullptr; } |
1335 | | |
1336 | | /// Return true if this is a copy statement. |
1337 | 983 | bool isCopyStmt() const { return BB == nullptr && R == nullptr91 ; } |
1338 | | |
1339 | | /// Get the region represented by this ScopStmt (if any). |
1340 | | /// |
1341 | | /// @return The region represented by this ScopStmt, or null if the statement |
1342 | | /// represents a basic block. |
1343 | 3.35k | Region *getRegion() const { return R; } |
1344 | | |
1345 | | /// Return true if this statement represents a whole region. |
1346 | 24.0k | bool isRegionStmt() const { return R != nullptr; } |
1347 | | |
1348 | | /// Return a BasicBlock from this statement. |
1349 | | /// |
1350 | | /// For block statements, it returns the BasicBlock itself. For subregion |
1351 | | /// statements, return its entry block. |
1352 | | BasicBlock *getEntryBlock() const; |
1353 | | |
1354 | | /// Return whether @p L is boxed within this statement. |
1355 | 1.80k | bool contains(const Loop *L) const { |
1356 | 1.80k | // Block statements never contain loops. |
1357 | 1.80k | if (isBlockStmt()) |
1358 | 1.69k | return false; |
1359 | 107 | |
1360 | 107 | return getRegion()->contains(L); |
1361 | 107 | } |
1362 | | |
1363 | | /// Return whether this statement represents @p BB. |
1364 | 12 | bool represents(BasicBlock *BB) const { |
1365 | 12 | if (isCopyStmt()) |
1366 | 0 | return false; |
1367 | 12 | if (isBlockStmt()) |
1368 | 0 | return BB == getBasicBlock(); |
1369 | 12 | return getRegion()->contains(BB); |
1370 | 12 | } |
1371 | | |
1372 | | /// Return whether this statement contains @p Inst. |
1373 | 0 | bool contains(Instruction *Inst) const { |
1374 | 0 | if (!Inst) |
1375 | 0 | return false; |
1376 | 0 | if (isBlockStmt()) |
1377 | 0 | return std::find(Instructions.begin(), Instructions.end(), Inst) != |
1378 | 0 | Instructions.end(); |
1379 | 0 | return represents(Inst->getParent()); |
1380 | 0 | } |
1381 | | |
1382 | | /// Return the closest innermost loop that contains this statement, but is not |
1383 | | /// contained in it. |
1384 | | /// |
1385 | | /// For block statement, this is just the loop that contains the block. Region |
1386 | | /// statements can contain boxed loops, so getting the loop of one of the |
1387 | | /// region's BBs might return such an inner loop. For instance, the region's |
1388 | | /// entry could be a header of a loop, but the region might extend to BBs |
1389 | | /// after the loop exit. Similarly, the region might only contain parts of the |
1390 | | /// loop body and still include the loop header. |
1391 | | /// |
1392 | | /// Most of the time the surrounding loop is the top element of #NestLoops, |
1393 | | /// except when it is empty. In that case it return the loop that the whole |
1394 | | /// SCoP is contained in. That can be nullptr if there is no such loop. |
1395 | 20.9k | Loop *getSurroundingLoop() const { |
1396 | 20.9k | assert(!isCopyStmt() && |
1397 | 20.9k | "No surrounding loop for artificially created statements"); |
1398 | 20.9k | return SurroundingLoop; |
1399 | 20.9k | } |
1400 | | |
1401 | | /// Return true if this statement does not contain any accesses. |
1402 | 11.2k | bool isEmpty() const { return MemAccs.empty(); } |
1403 | | |
1404 | | /// Find all array accesses for @p Inst. |
1405 | | /// |
1406 | | /// @param Inst The instruction accessing an array. |
1407 | | /// |
1408 | | /// @return A list of array accesses (MemoryKind::Array) accessed by @p Inst. |
1409 | | /// If there is no such access, it returns nullptr. |
1410 | | const MemoryAccessList * |
1411 | 208 | lookupArrayAccessesFor(const Instruction *Inst) const { |
1412 | 208 | auto It = InstructionToAccess.find(Inst); |
1413 | 208 | if (It == InstructionToAccess.end()) |
1414 | 61 | return nullptr; |
1415 | 147 | if (It->second.empty()) |
1416 | 0 | return nullptr; |
1417 | 147 | return &It->second; |
1418 | 147 | } |
1419 | | |
1420 | | /// Return the only array access for @p Inst, if existing. |
1421 | | /// |
1422 | | /// @param Inst The instruction for which to look up the access. |
1423 | | /// @returns The unique array memory access related to Inst or nullptr if |
1424 | | /// no array access exists |
1425 | 3.03k | MemoryAccess *getArrayAccessOrNULLFor(const Instruction *Inst) const { |
1426 | 3.03k | auto It = InstructionToAccess.find(Inst); |
1427 | 3.03k | if (It == InstructionToAccess.end()) |
1428 | 920 | return nullptr; |
1429 | 2.11k | |
1430 | 2.11k | MemoryAccess *ArrayAccess = nullptr; |
1431 | 2.11k | |
1432 | 2.11k | for (auto Access : It->getSecond()) { |
1433 | 2.11k | if (!Access->isArrayKind()) |
1434 | 0 | continue; |
1435 | 2.11k | |
1436 | 2.11k | assert(!ArrayAccess && "More then one array access for instruction"); |
1437 | 2.11k | |
1438 | 2.11k | ArrayAccess = Access; |
1439 | 2.11k | } |
1440 | 2.11k | |
1441 | 2.11k | return ArrayAccess; |
1442 | 2.11k | } |
1443 | | |
1444 | | /// Return the only array access for @p Inst. |
1445 | | /// |
1446 | | /// @param Inst The instruction for which to look up the access. |
1447 | | /// @returns The unique array memory access related to Inst. |
1448 | 1.67k | MemoryAccess &getArrayAccessFor(const Instruction *Inst) const { |
1449 | 1.67k | MemoryAccess *ArrayAccess = getArrayAccessOrNULLFor(Inst); |
1450 | 1.67k | |
1451 | 1.67k | assert(ArrayAccess && "No array access found for instruction!"); |
1452 | 1.67k | return *ArrayAccess; |
1453 | 1.67k | } |
1454 | | |
1455 | | /// Return the MemoryAccess that writes the value of an instruction |
1456 | | /// defined in this statement, or nullptr if not existing, respectively |
1457 | | /// not yet added. |
1458 | 409 | MemoryAccess *lookupValueWriteOf(Instruction *Inst) const { |
1459 | 409 | assert((isRegionStmt() && R->contains(Inst)) || |
1460 | 409 | (!isRegionStmt() && Inst->getParent() == BB)); |
1461 | 409 | return ValueWrites.lookup(Inst); |
1462 | 409 | } |
1463 | | |
1464 | | /// Return the MemoryAccess that reloads a value, or nullptr if not |
1465 | | /// existing, respectively not yet added. |
1466 | 2.00k | MemoryAccess *lookupValueReadOf(Value *Inst) const { |
1467 | 2.00k | return ValueReads.lookup(Inst); |
1468 | 2.00k | } |
1469 | | |
1470 | | /// Return the MemoryAccess that loads a PHINode value, or nullptr if not |
1471 | | /// existing, respectively not yet added. |
1472 | 43 | MemoryAccess *lookupPHIReadOf(PHINode *PHI) const { |
1473 | 43 | return PHIReads.lookup(PHI); |
1474 | 43 | } |
1475 | | |
1476 | | /// Return the PHI write MemoryAccess for the incoming values from any |
1477 | | /// basic block in this ScopStmt, or nullptr if not existing, |
1478 | | /// respectively not yet added. |
1479 | 514 | MemoryAccess *lookupPHIWriteOf(PHINode *PHI) const { |
1480 | 514 | assert(isBlockStmt() || R->getExit() == PHI->getParent()); |
1481 | 514 | return PHIWrites.lookup(PHI); |
1482 | 514 | } |
1483 | | |
1484 | | /// Return the input access of the value, or null if no such MemoryAccess |
1485 | | /// exists. |
1486 | | /// |
1487 | | /// The input access is the MemoryAccess that makes an inter-statement value |
1488 | | /// available in this statement by reading it at the start of this statement. |
1489 | | /// This can be a MemoryKind::Value if defined in another statement or a |
1490 | | /// MemoryKind::PHI if the value is a PHINode in this statement. |
1491 | 137 | MemoryAccess *lookupInputAccessOf(Value *Val) const { |
1492 | 137 | if (isa<PHINode>(Val)) |
1493 | 36 | if (auto InputMA = lookupPHIReadOf(cast<PHINode>(Val))) { |
1494 | 18 | assert(!lookupValueReadOf(Val) && "input accesses must be unique; a " |
1495 | 18 | "statement cannot read a .s2a and " |
1496 | 18 | ".phiops simultaneously"); |
1497 | 18 | return InputMA; |
1498 | 18 | } |
1499 | 119 | |
1500 | 119 | if (auto *InputMA = lookupValueReadOf(Val)) |
1501 | 63 | return InputMA; |
1502 | 56 | |
1503 | 56 | return nullptr; |
1504 | 56 | } |
1505 | | |
1506 | | /// Add @p Access to this statement's list of accesses. |
1507 | | /// |
1508 | | /// @param Access The access to add. |
1509 | | /// @param Prepend If true, will add @p Access before all other instructions |
1510 | | /// (instead of appending it). |
1511 | | void addAccess(MemoryAccess *Access, bool Preprend = false); |
1512 | | |
1513 | | /// Remove a MemoryAccess from this statement. |
1514 | | /// |
1515 | | /// Note that scalar accesses that are caused by MA will |
1516 | | /// be eliminated too. |
1517 | | void removeMemoryAccess(MemoryAccess *MA); |
1518 | | |
1519 | | /// Remove @p MA from this statement. |
1520 | | /// |
1521 | | /// In contrast to removeMemoryAccess(), no other access will be eliminated. |
1522 | | /// |
1523 | | /// @param MA The MemoryAccess to be removed. |
1524 | | /// @param AfterHoisting If true, also remove from data access lists. |
1525 | | /// These lists are filled during |
1526 | | /// ScopBuilder::buildAccessRelations. Therefore, if this |
1527 | | /// method is called before buildAccessRelations, false |
1528 | | /// must be passed. |
1529 | | void removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting = true); |
1530 | | |
1531 | | using iterator = MemoryAccessVec::iterator; |
1532 | | using const_iterator = MemoryAccessVec::const_iterator; |
1533 | | |
1534 | 38.2k | iterator begin() { return MemAccs.begin(); } |
1535 | 38.2k | iterator end() { return MemAccs.end(); } |
1536 | 56 | const_iterator begin() const { return MemAccs.begin(); } |
1537 | 56 | const_iterator end() const { return MemAccs.end(); } |
1538 | 5.29k | size_t size() const { return MemAccs.size(); } |
1539 | | |
1540 | | unsigned getNumIterators() const; |
1541 | | |
1542 | 38.9k | Scop *getParent() { return &Parent; } |
1543 | 1.26k | const Scop *getParent() const { return &Parent; } |
1544 | | |
1545 | 23.7k | const std::vector<Instruction *> &getInstructions() const { |
1546 | 23.7k | return Instructions; |
1547 | 23.7k | } |
1548 | | |
1549 | | /// Set the list of instructions for this statement. It replaces the current |
1550 | | /// list. |
1551 | 98 | void setInstructions(ArrayRef<Instruction *> Range) { |
1552 | 98 | Instructions.assign(Range.begin(), Range.end()); |
1553 | 98 | } |
1554 | | |
1555 | 99 | std::vector<Instruction *>::const_iterator insts_begin() const { |
1556 | 99 | return Instructions.begin(); |
1557 | 99 | } |
1558 | | |
1559 | 99 | std::vector<Instruction *>::const_iterator insts_end() const { |
1560 | 99 | return Instructions.end(); |
1561 | 99 | } |
1562 | | |
1563 | | /// The range of instructions in this statement. |
1564 | 1 | iterator_range<std::vector<Instruction *>::const_iterator> insts() const { |
1565 | 1 | return {insts_begin(), insts_end()}; |
1566 | 1 | } |
1567 | | |
1568 | | /// Insert an instruction before all other instructions in this statement. |
1569 | 37 | void prependInstruction(Instruction *Inst) { |
1570 | 37 | Instructions.insert(Instructions.begin(), Inst); |
1571 | 37 | } |
1572 | | |
1573 | | const char *getBaseName() const; |
1574 | | |
1575 | | /// Set the isl AST build. |
1576 | 533 | void setAstBuild(isl::ast_build B) { Build = B; } |
1577 | | |
1578 | | /// Get the isl AST build. |
1579 | 12 | isl::ast_build getAstBuild() const { return Build; } |
1580 | | |
1581 | | /// Restrict the domain of the statement. |
1582 | | /// |
1583 | | /// @param NewDomain The new statement domain. |
1584 | | void restrictDomain(isl::set NewDomain); |
1585 | | |
1586 | | /// Get the loop for a dimension. |
1587 | | /// |
1588 | | /// @param Dimension The dimension of the induction variable |
1589 | | /// @return The loop at a certain dimension. |
1590 | | Loop *getLoopForDimension(unsigned Dimension) const; |
1591 | | |
1592 | | /// Align the parameters in the statement to the scop context |
1593 | | void realignParams(); |
1594 | | |
1595 | | /// Print the ScopStmt. |
1596 | | /// |
1597 | | /// @param OS The output stream the ScopStmt is printed to. |
1598 | | /// @param PrintInstructions Whether to print the statement's instructions as |
1599 | | /// well. |
1600 | | void print(raw_ostream &OS, bool PrintInstructions) const; |
1601 | | |
1602 | | /// Print the instructions in ScopStmt. |
1603 | | /// |
1604 | | void printInstructions(raw_ostream &OS) const; |
1605 | | |
1606 | | /// Check whether there is a value read access for @p V in this statement, and |
1607 | | /// if not, create one. |
1608 | | /// |
1609 | | /// This allows to add MemoryAccesses after the initial creation of the Scop |
1610 | | /// by ScopBuilder. |
1611 | | /// |
1612 | | /// @return The already existing or newly created MemoryKind::Value READ |
1613 | | /// MemoryAccess. |
1614 | | /// |
1615 | | /// @see ScopBuilder::ensureValueRead(Value*,ScopStmt*) |
1616 | | MemoryAccess *ensureValueRead(Value *V); |
1617 | | |
1618 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
1619 | | /// Print the ScopStmt to stderr. |
1620 | | void dump() const; |
1621 | | #endif |
1622 | | }; |
1623 | | |
1624 | | /// Print ScopStmt S to raw_ostream OS. |
1625 | | raw_ostream &operator<<(raw_ostream &OS, const ScopStmt &S); |
1626 | | |
1627 | | /// Helper struct to remember assumptions. |
1628 | | struct Assumption { |
1629 | | /// The kind of the assumption (e.g., WRAPPING). |
1630 | | AssumptionKind Kind; |
1631 | | |
1632 | | /// Flag to distinguish assumptions and restrictions. |
1633 | | AssumptionSign Sign; |
1634 | | |
1635 | | /// The valid/invalid context if this is an assumption/restriction. |
1636 | | isl::set Set; |
1637 | | |
1638 | | /// The location that caused this assumption. |
1639 | | DebugLoc Loc; |
1640 | | |
1641 | | /// An optional block whose domain can simplify the assumption. |
1642 | | BasicBlock *BB; |
1643 | | }; |
1644 | | |
1645 | | /// Static Control Part |
1646 | | /// |
1647 | | /// A Scop is the polyhedral representation of a control flow region detected |
1648 | | /// by the Scop detection. It is generated by translating the LLVM-IR and |
1649 | | /// abstracting its effects. |
1650 | | /// |
1651 | | /// A Scop consists of a set of: |
1652 | | /// |
1653 | | /// * A set of statements executed in the Scop. |
1654 | | /// |
1655 | | /// * A set of global parameters |
1656 | | /// Those parameters are scalar integer values, which are constant during |
1657 | | /// execution. |
1658 | | /// |
1659 | | /// * A context |
1660 | | /// This context contains information about the values the parameters |
1661 | | /// can take and relations between different parameters. |
1662 | | class Scop { |
1663 | | public: |
1664 | | /// Type to represent a pair of minimal/maximal access to an array. |
1665 | | using MinMaxAccessTy = std::pair<isl::pw_multi_aff, isl::pw_multi_aff>; |
1666 | | |
1667 | | /// Vector of minimal/maximal accesses to different arrays. |
1668 | | using MinMaxVectorTy = SmallVector<MinMaxAccessTy, 4>; |
1669 | | |
1670 | | /// Pair of minimal/maximal access vectors representing |
1671 | | /// read write and read only accesses |
1672 | | using MinMaxVectorPairTy = std::pair<MinMaxVectorTy, MinMaxVectorTy>; |
1673 | | |
1674 | | /// Vector of pair of minimal/maximal access vectors representing |
1675 | | /// non read only and read only accesses for each alias group. |
1676 | | using MinMaxVectorPairVectorTy = SmallVector<MinMaxVectorPairTy, 4>; |
1677 | | |
1678 | | private: |
1679 | | friend class ScopBuilder; |
1680 | | |
1681 | | /// Isl context. |
1682 | | /// |
1683 | | /// We need a shared_ptr with reference counter to delete the context when all |
1684 | | /// isl objects are deleted. We will distribute the shared_ptr to all objects |
1685 | | /// that use the context to create isl objects, and increase the reference |
1686 | | /// counter. By doing this, we guarantee that the context is deleted when we |
1687 | | /// delete the last object that creates isl objects with the context. This |
1688 | | /// declaration needs to be the first in class to gracefully destroy all isl |
1689 | | /// objects before the context. |
1690 | | std::shared_ptr<isl_ctx> IslCtx; |
1691 | | |
1692 | | ScalarEvolution *SE; |
1693 | | DominatorTree *DT; |
1694 | | |
1695 | | /// The underlying Region. |
1696 | | Region &R; |
1697 | | |
1698 | | /// The name of the SCoP (identical to the regions name) |
1699 | | Optional<std::string> name; |
1700 | | |
1701 | | /// The ID to be assigned to the next Scop in a function |
1702 | | static int NextScopID; |
1703 | | |
1704 | | /// The name of the function currently under consideration |
1705 | | static std::string CurrentFunc; |
1706 | | |
1707 | | // Access functions of the SCoP. |
1708 | | // |
1709 | | // This owns all the MemoryAccess objects of the Scop created in this pass. |
1710 | | AccFuncVector AccessFunctions; |
1711 | | |
1712 | | /// Flag to indicate that the scheduler actually optimized the SCoP. |
1713 | | bool IsOptimized = false; |
1714 | | |
1715 | | /// True if the underlying region has a single exiting block. |
1716 | | bool HasSingleExitEdge; |
1717 | | |
1718 | | /// Flag to remember if the SCoP contained an error block or not. |
1719 | | bool HasErrorBlock = false; |
1720 | | |
1721 | | /// Max loop depth. |
1722 | | unsigned MaxLoopDepth = 0; |
1723 | | |
1724 | | /// Number of copy statements. |
1725 | | unsigned CopyStmtsNum = 0; |
1726 | | |
1727 | | /// Flag to indicate if the Scop is to be skipped. |
1728 | | bool SkipScop = false; |
1729 | | |
1730 | | using StmtSet = std::list<ScopStmt>; |
1731 | | |
1732 | | /// The statements in this Scop. |
1733 | | StmtSet Stmts; |
1734 | | |
1735 | | /// Parameters of this Scop |
1736 | | ParameterSetTy Parameters; |
1737 | | |
1738 | | /// Mapping from parameters to their ids. |
1739 | | DenseMap<const SCEV *, isl::id> ParameterIds; |
1740 | | |
1741 | | /// The context of the SCoP created during SCoP detection. |
1742 | | ScopDetection::DetectionContext &DC; |
1743 | | |
1744 | | /// OptimizationRemarkEmitter object for displaying diagnostic remarks |
1745 | | OptimizationRemarkEmitter &ORE; |
1746 | | |
1747 | | /// A map from basic blocks to vector of SCoP statements. Currently this |
1748 | | /// vector comprises only of a single statement. |
1749 | | DenseMap<BasicBlock *, std::vector<ScopStmt *>> StmtMap; |
1750 | | |
1751 | | /// A map from instructions to SCoP statements. |
1752 | | DenseMap<Instruction *, ScopStmt *> InstStmtMap; |
1753 | | |
1754 | | /// A map from basic blocks to their domains. |
1755 | | DenseMap<BasicBlock *, isl::set> DomainMap; |
1756 | | |
1757 | | /// Constraints on parameters. |
1758 | | isl::set Context = nullptr; |
1759 | | |
1760 | | /// The affinator used to translate SCEVs to isl expressions. |
1761 | | SCEVAffinator Affinator; |
1762 | | |
1763 | | using ArrayInfoMapTy = |
1764 | | std::map<std::pair<AssertingVH<const Value>, MemoryKind>, |
1765 | | std::unique_ptr<ScopArrayInfo>>; |
1766 | | |
1767 | | using ArrayNameMapTy = StringMap<std::unique_ptr<ScopArrayInfo>>; |
1768 | | |
1769 | | using ArrayInfoSetTy = SetVector<ScopArrayInfo *>; |
1770 | | |
1771 | | /// A map to remember ScopArrayInfo objects for all base pointers. |
1772 | | /// |
1773 | | /// As PHI nodes may have two array info objects associated, we add a flag |
1774 | | /// that distinguishes between the PHI node specific ArrayInfo object |
1775 | | /// and the normal one. |
1776 | | ArrayInfoMapTy ScopArrayInfoMap; |
1777 | | |
1778 | | /// A map to remember ScopArrayInfo objects for all names of memory |
1779 | | /// references. |
1780 | | ArrayNameMapTy ScopArrayNameMap; |
1781 | | |
1782 | | /// A set to remember ScopArrayInfo objects. |
1783 | | /// @see Scop::ScopArrayInfoMap |
1784 | | ArrayInfoSetTy ScopArrayInfoSet; |
1785 | | |
1786 | | /// The assumptions under which this scop was built. |
1787 | | /// |
1788 | | /// When constructing a scop sometimes the exact representation of a statement |
1789 | | /// or condition would be very complex, but there is a common case which is a |
1790 | | /// lot simpler, but which is only valid under certain assumptions. The |
1791 | | /// assumed context records the assumptions taken during the construction of |
1792 | | /// this scop and that need to be code generated as a run-time test. |
1793 | | isl::set AssumedContext; |
1794 | | |
1795 | | /// The restrictions under which this SCoP was built. |
1796 | | /// |
1797 | | /// The invalid context is similar to the assumed context as it contains |
1798 | | /// constraints over the parameters. However, while we need the constraints |
1799 | | /// in the assumed context to be "true" the constraints in the invalid context |
1800 | | /// need to be "false". Otherwise they behave the same. |
1801 | | isl::set InvalidContext; |
1802 | | |
1803 | | using RecordedAssumptionsTy = SmallVector<Assumption, 8>; |
1804 | | /// Collection to hold taken assumptions. |
1805 | | /// |
1806 | | /// There are two reasons why we want to record assumptions first before we |
1807 | | /// add them to the assumed/invalid context: |
1808 | | /// 1) If the SCoP is not profitable or otherwise invalid without the |
1809 | | /// assumed/invalid context we do not have to compute it. |
1810 | | /// 2) Information about the context are gathered rather late in the SCoP |
1811 | | /// construction (basically after we know all parameters), thus the user |
1812 | | /// might see overly complicated assumptions to be taken while they will |
1813 | | /// only be simplified later on. |
1814 | | RecordedAssumptionsTy RecordedAssumptions; |
1815 | | |
1816 | | /// The schedule of the SCoP |
1817 | | /// |
1818 | | /// The schedule of the SCoP describes the execution order of the statements |
1819 | | /// in the scop by assigning each statement instance a possibly |
1820 | | /// multi-dimensional execution time. The schedule is stored as a tree of |
1821 | | /// schedule nodes. |
1822 | | /// |
1823 | | /// The most common nodes in a schedule tree are so-called band nodes. Band |
1824 | | /// nodes map statement instances into a multi dimensional schedule space. |
1825 | | /// This space can be seen as a multi-dimensional clock. |
1826 | | /// |
1827 | | /// Example: |
1828 | | /// |
1829 | | /// <S,(5,4)> may be mapped to (5,4) by this schedule: |
1830 | | /// |
1831 | | /// s0 = i (Year of execution) |
1832 | | /// s1 = j (Day of execution) |
1833 | | /// |
1834 | | /// or to (9, 20) by this schedule: |
1835 | | /// |
1836 | | /// s0 = i + j (Year of execution) |
1837 | | /// s1 = 20 (Day of execution) |
1838 | | /// |
1839 | | /// The order statement instances are executed is defined by the |
1840 | | /// schedule vectors they are mapped to. A statement instance |
1841 | | /// <A, (i, j, ..)> is executed before a statement instance <B, (i', ..)>, if |
1842 | | /// the schedule vector of A is lexicographic smaller than the schedule |
1843 | | /// vector of B. |
1844 | | /// |
1845 | | /// Besides band nodes, schedule trees contain additional nodes that specify |
1846 | | /// a textual ordering between two subtrees or filter nodes that filter the |
1847 | | /// set of statement instances that will be scheduled in a subtree. There |
1848 | | /// are also several other nodes. A full description of the different nodes |
1849 | | /// in a schedule tree is given in the isl manual. |
1850 | | isl::schedule Schedule = nullptr; |
1851 | | |
1852 | | /// Whether the schedule has been modified after derived from the CFG by |
1853 | | /// ScopBuilder. |
1854 | | bool ScheduleModified = false; |
1855 | | |
1856 | | /// The set of minimal/maximal accesses for each alias group. |
1857 | | /// |
1858 | | /// When building runtime alias checks we look at all memory instructions and |
1859 | | /// build so called alias groups. Each group contains a set of accesses to |
1860 | | /// different base arrays which might alias with each other. However, between |
1861 | | /// alias groups there is no aliasing possible. |
1862 | | /// |
1863 | | /// In a program with int and float pointers annotated with tbaa information |
1864 | | /// we would probably generate two alias groups, one for the int pointers and |
1865 | | /// one for the float pointers. |
1866 | | /// |
1867 | | /// During code generation we will create a runtime alias check for each alias |
1868 | | /// group to ensure the SCoP is executed in an alias free environment. |
1869 | | MinMaxVectorPairVectorTy MinMaxAliasGroups; |
1870 | | |
1871 | | /// Mapping from invariant loads to the representing invariant load of |
1872 | | /// their equivalence class. |
1873 | | ValueToValueMap InvEquivClassVMap; |
1874 | | |
1875 | | /// List of invariant accesses. |
1876 | | InvariantEquivClassesTy InvariantEquivClasses; |
1877 | | |
1878 | | /// The smallest array index not yet assigned. |
1879 | | long ArrayIdx = 0; |
1880 | | |
1881 | | /// The smallest statement index not yet assigned. |
1882 | | long StmtIdx = 0; |
1883 | | |
1884 | | /// A number that uniquely represents a Scop within its function |
1885 | | const int ID; |
1886 | | |
1887 | | /// Map of values to the MemoryAccess that writes its definition. |
1888 | | /// |
1889 | | /// There must be at most one definition per llvm::Instruction in a SCoP. |
1890 | | DenseMap<Value *, MemoryAccess *> ValueDefAccs; |
1891 | | |
1892 | | /// Map of values to the MemoryAccess that reads a PHI. |
1893 | | DenseMap<PHINode *, MemoryAccess *> PHIReadAccs; |
1894 | | |
1895 | | /// List of all uses (i.e. read MemoryAccesses) for a MemoryKind::Value |
1896 | | /// scalar. |
1897 | | DenseMap<const ScopArrayInfo *, SmallVector<MemoryAccess *, 4>> ValueUseAccs; |
1898 | | |
1899 | | /// List of all incoming values (write MemoryAccess) of a MemoryKind::PHI or |
1900 | | /// MemoryKind::ExitPHI scalar. |
1901 | | DenseMap<const ScopArrayInfo *, SmallVector<MemoryAccess *, 4>> |
1902 | | PHIIncomingAccs; |
1903 | | |
1904 | | /// Return the ID for a new Scop within a function |
1905 | | static int getNextID(std::string ParentFunc); |
1906 | | |
1907 | | /// Scop constructor; invoked from ScopBuilder::buildScop. |
1908 | | Scop(Region &R, ScalarEvolution &SE, LoopInfo &LI, DominatorTree &DT, |
1909 | | ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE); |
1910 | | |
1911 | | //@} |
1912 | | |
1913 | | /// Initialize this ScopBuilder. |
1914 | | void init(AliasAnalysis &AA, AssumptionCache &AC, DominatorTree &DT, |
1915 | | LoopInfo &LI); |
1916 | | |
1917 | | /// Propagate domains that are known due to graph properties. |
1918 | | /// |
1919 | | /// As a CFG is mostly structured we use the graph properties to propagate |
1920 | | /// domains without the need to compute all path conditions. In particular, if |
1921 | | /// a block A dominates a block B and B post-dominates A we know that the |
1922 | | /// domain of B is a superset of the domain of A. As we do not have |
1923 | | /// post-dominator information available here we use the less precise region |
1924 | | /// information. Given a region R, we know that the exit is always executed if |
1925 | | /// the entry was executed, thus the domain of the exit is a superset of the |
1926 | | /// domain of the entry. In case the exit can only be reached from within the |
1927 | | /// region the domains are in fact equal. This function will use this property |
1928 | | /// to avoid the generation of condition constraints that determine when a |
1929 | | /// branch is taken. If @p BB is a region entry block we will propagate its |
1930 | | /// domain to the region exit block. Additionally, we put the region exit |
1931 | | /// block in the @p FinishedExitBlocks set so we can later skip edges from |
1932 | | /// within the region to that block. |
1933 | | /// |
1934 | | /// @param BB The block for which the domain is currently |
1935 | | /// propagated. |
1936 | | /// @param BBLoop The innermost affine loop surrounding @p BB. |
1937 | | /// @param FinishedExitBlocks Set of region exits the domain was set for. |
1938 | | /// @param LI The LoopInfo for the current function. |
1939 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
1940 | | /// region. |
1941 | | void propagateDomainConstraintsToRegionExit( |
1942 | | BasicBlock *BB, Loop *BBLoop, |
1943 | | SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, LoopInfo &LI, |
1944 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
1945 | | |
1946 | | /// Compute the union of predecessor domains for @p BB. |
1947 | | /// |
1948 | | /// To compute the union of all domains of predecessors of @p BB this |
1949 | | /// function applies similar reasoning on the CFG structure as described for |
1950 | | /// @see propagateDomainConstraintsToRegionExit |
1951 | | /// |
1952 | | /// @param BB The block for which the predecessor domains are collected. |
1953 | | /// @param Domain The domain under which BB is executed. |
1954 | | /// @param DT The DominatorTree for the current function. |
1955 | | /// @param LI The LoopInfo for the current function. |
1956 | | /// |
1957 | | /// @returns The domain under which @p BB is executed. |
1958 | | isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain, |
1959 | | DominatorTree &DT, LoopInfo &LI); |
1960 | | |
1961 | | /// Add loop carried constraints to the header block of the loop @p L. |
1962 | | /// |
1963 | | /// @param L The loop to process. |
1964 | | /// @param LI The LoopInfo for the current function. |
1965 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
1966 | | /// region. |
1967 | | /// |
1968 | | /// @returns True if there was no problem and false otherwise. |
1969 | | bool addLoopBoundsToHeaderDomain( |
1970 | | Loop *L, LoopInfo &LI, |
1971 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
1972 | | |
1973 | | /// Compute the branching constraints for each basic block in @p R. |
1974 | | /// |
1975 | | /// @param R The region we currently build branching conditions |
1976 | | /// for. |
1977 | | /// @param DT The DominatorTree for the current function. |
1978 | | /// @param LI The LoopInfo for the current function. |
1979 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
1980 | | /// region. |
1981 | | /// |
1982 | | /// @returns True if there was no problem and false otherwise. |
1983 | | bool buildDomainsWithBranchConstraints( |
1984 | | Region *R, DominatorTree &DT, LoopInfo &LI, |
1985 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
1986 | | |
1987 | | /// Propagate the domain constraints through the region @p R. |
1988 | | /// |
1989 | | /// @param R The region we currently build branching conditions |
1990 | | /// for. |
1991 | | /// @param DT The DominatorTree for the current function. |
1992 | | /// @param LI The LoopInfo for the current function. |
1993 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
1994 | | /// region. |
1995 | | /// |
1996 | | /// @returns True if there was no problem and false otherwise. |
1997 | | bool propagateDomainConstraints( |
1998 | | Region *R, DominatorTree &DT, LoopInfo &LI, |
1999 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
2000 | | |
2001 | | /// Propagate invalid domains of statements through @p R. |
2002 | | /// |
2003 | | /// This method will propagate invalid statement domains through @p R and at |
2004 | | /// the same time add error block domains to them. Additionally, the domains |
2005 | | /// of error statements and those only reachable via error statements will be |
2006 | | /// replaced by an empty set. Later those will be removed completely. |
2007 | | /// |
2008 | | /// @param R The currently traversed region. |
2009 | | /// @param DT The DominatorTree for the current function. |
2010 | | /// @param LI The LoopInfo for the current function. |
2011 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
2012 | | /// region. |
2013 | | // |
2014 | | /// @returns True if there was no problem and false otherwise. |
2015 | | bool propagateInvalidStmtDomains( |
2016 | | Region *R, DominatorTree &DT, LoopInfo &LI, |
2017 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
2018 | | |
2019 | | /// Compute the domain for each basic block in @p R. |
2020 | | /// |
2021 | | /// @param R The region we currently traverse. |
2022 | | /// @param DT The DominatorTree for the current function. |
2023 | | /// @param LI The LoopInfo for the current function. |
2024 | | /// @param InvalidDomainMap BB to InvalidDomain map for the BB of current |
2025 | | /// region. |
2026 | | /// |
2027 | | /// @returns True if there was no problem and false otherwise. |
2028 | | bool buildDomains(Region *R, DominatorTree &DT, LoopInfo &LI, |
2029 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
2030 | | |
2031 | | /// Add parameter constraints to @p C that imply a non-empty domain. |
2032 | | isl::set addNonEmptyDomainConstraints(isl::set C) const; |
2033 | | |
2034 | | /// Return the access for the base ptr of @p MA if any. |
2035 | | MemoryAccess *lookupBasePtrAccess(MemoryAccess *MA); |
2036 | | |
2037 | | /// Create an id for @p Param and store it in the ParameterIds map. |
2038 | | void createParameterId(const SCEV *Param); |
2039 | | |
2040 | | /// Build the Context of the Scop. |
2041 | | void buildContext(); |
2042 | | |
2043 | | /// Add user provided parameter constraints to context (source code). |
2044 | | void addUserAssumptions(AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI, |
2045 | | DenseMap<BasicBlock *, isl::set> &InvalidDomainMap); |
2046 | | |
2047 | | /// Add the bounds of the parameters to the context. |
2048 | | void addParameterBounds(); |
2049 | | |
2050 | | /// Simplify the assumed and invalid context. |
2051 | | void simplifyContexts(); |
2052 | | |
2053 | | /// Get the representing SCEV for @p S if applicable, otherwise @p S. |
2054 | | /// |
2055 | | /// Invariant loads of the same location are put in an equivalence class and |
2056 | | /// only one of them is chosen as a representing element that will be |
2057 | | /// modeled as a parameter. The others have to be normalized, i.e., |
2058 | | /// replaced by the representing element of their equivalence class, in order |
2059 | | /// to get the correct parameter value, e.g., in the SCEVAffinator. |
2060 | | /// |
2061 | | /// @param S The SCEV to normalize. |
2062 | | /// |
2063 | | /// @return The representing SCEV for invariant loads or @p S if none. |
2064 | | const SCEV *getRepresentingInvariantLoadSCEV(const SCEV *S) const; |
2065 | | |
2066 | | /// Create a new SCoP statement for @p BB. |
2067 | | /// |
2068 | | /// A new statement for @p BB will be created and added to the statement |
2069 | | /// vector |
2070 | | /// and map. |
2071 | | /// |
2072 | | /// @param BB The basic block we build the statement for. |
2073 | | /// @param Name The name of the new statement. |
2074 | | /// @param SurroundingLoop The loop the created statement is contained in. |
2075 | | /// @param Instructions The instructions in the statement. |
2076 | | void addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop, |
2077 | | std::vector<Instruction *> Instructions); |
2078 | | |
2079 | | /// Create a new SCoP statement for @p R. |
2080 | | /// |
2081 | | /// A new statement for @p R will be created and added to the statement vector |
2082 | | /// and map. |
2083 | | /// |
2084 | | /// @param R The region we build the statement for. |
2085 | | /// @param Name The name of the new statement. |
2086 | | /// @param SurroundingLoop The loop the created statement is contained |
2087 | | /// in. |
2088 | | /// @param EntryBlockInstructions The (interesting) instructions in the |
2089 | | /// entry block of the region statement. |
2090 | | void addScopStmt(Region *R, StringRef Name, Loop *SurroundingLoop, |
2091 | | std::vector<Instruction *> EntryBlockInstructions); |
2092 | | |
2093 | | /// Remove statements from the list of scop statements. |
2094 | | /// |
2095 | | /// @param ShouldDelete A function that returns true if the statement passed |
2096 | | /// to it should be deleted. |
2097 | | /// @param AfterHoisting If true, also remove from data access lists. |
2098 | | /// These lists are filled during |
2099 | | /// ScopBuilder::buildAccessRelations. Therefore, if this |
2100 | | /// method is called before buildAccessRelations, false |
2101 | | /// must be passed. |
2102 | | void removeStmts(std::function<bool(ScopStmt &)> ShouldDelete, |
2103 | | bool AfterHoisting = true); |
2104 | | |
2105 | | /// Removes @p Stmt from the StmtMap. |
2106 | | void removeFromStmtMap(ScopStmt &Stmt); |
2107 | | |
2108 | | /// Removes all statements where the entry block of the statement does not |
2109 | | /// have a corresponding domain in the domain map (or it is empty). |
2110 | | void removeStmtNotInDomainMap(); |
2111 | | |
2112 | | /// Collect all memory access relations of a given type. |
2113 | | /// |
2114 | | /// @param Predicate A predicate function that returns true if an access is |
2115 | | /// of a given type. |
2116 | | /// |
2117 | | /// @returns The set of memory accesses in the scop that match the predicate. |
2118 | | isl::union_map |
2119 | | getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate); |
2120 | | |
2121 | | /// @name Helper functions for printing the Scop. |
2122 | | /// |
2123 | | //@{ |
2124 | | void printContext(raw_ostream &OS) const; |
2125 | | void printArrayInfo(raw_ostream &OS) const; |
2126 | | void printStatements(raw_ostream &OS, bool PrintInstructions) const; |
2127 | | void printAliasAssumptions(raw_ostream &OS) const; |
2128 | | //@} |
2129 | | |
2130 | | public: |
2131 | | Scop(const Scop &) = delete; |
2132 | | Scop &operator=(const Scop &) = delete; |
2133 | | ~Scop(); |
2134 | | |
2135 | | /// Increment actual number of aliasing assumptions taken |
2136 | | /// |
2137 | | /// @param Step Number of new aliasing assumptions which should be added to |
2138 | | /// the number of already taken assumptions. |
2139 | | static void incrementNumberOfAliasingAssumptions(unsigned Step); |
2140 | | |
2141 | | /// Get the count of copy statements added to this Scop. |
2142 | | /// |
2143 | | /// @return The count of copy statements added to this Scop. |
2144 | 24 | unsigned getCopyStmtsNum() { return CopyStmtsNum; } |
2145 | | |
2146 | | /// Create a new copy statement. |
2147 | | /// |
2148 | | /// A new statement will be created and added to the statement vector. |
2149 | | /// |
2150 | | /// @param Stmt The parent statement. |
2151 | | /// @param SourceRel The source location. |
2152 | | /// @param TargetRel The target location. |
2153 | | /// @param Domain The original domain under which the copy statement would |
2154 | | /// be executed. |
2155 | | ScopStmt *addScopStmt(isl::map SourceRel, isl::map TargetRel, |
2156 | | isl::set Domain); |
2157 | | |
2158 | | /// Add the access function to all MemoryAccess objects of the Scop |
2159 | | /// created in this pass. |
2160 | 5.15k | void addAccessFunction(MemoryAccess *Access) { |
2161 | 5.15k | AccessFunctions.emplace_back(Access); |
2162 | 5.15k | |
2163 | 5.15k | // Register value definitions. |
2164 | 5.15k | if (Access->isWrite() && Access->isOriginalValueKind()2.67k ) { |
2165 | 343 | assert(!ValueDefAccs.count(Access->getAccessValue()) && |
2166 | 343 | "there can be just one definition per value"); |
2167 | 343 | ValueDefAccs[Access->getAccessValue()] = Access; |
2168 | 4.81k | } else if (Access->isRead() && Access->isOriginalPHIKind()2.48k ) { |
2169 | 238 | PHINode *PHI = cast<PHINode>(Access->getAccessInstruction()); |
2170 | 238 | assert(!PHIReadAccs.count(PHI) && |
2171 | 238 | "there can be just one PHI read per PHINode"); |
2172 | 238 | PHIReadAccs[PHI] = Access; |
2173 | 238 | } |
2174 | 5.15k | } |
2175 | | |
2176 | | /// Add metadata for @p Access. |
2177 | | void addAccessData(MemoryAccess *Access); |
2178 | | |
2179 | | /// Add new invariant access equivalence class |
2180 | | void |
2181 | 382 | addInvariantEquivClass(const InvariantEquivClassTy &InvariantEquivClass) { |
2182 | 382 | InvariantEquivClasses.emplace_back(InvariantEquivClass); |
2183 | 382 | } |
2184 | | |
2185 | | /// Add mapping from invariant loads to the representing invariant load of |
2186 | | /// their equivalence class. |
2187 | 36 | void addInvariantLoadMapping(const Value *LoadInst, Value *ClassRep) { |
2188 | 36 | InvEquivClassVMap[LoadInst] = ClassRep; |
2189 | 36 | } |
2190 | | |
2191 | | /// Remove the metadata stored for @p Access. |
2192 | | void removeAccessData(MemoryAccess *Access); |
2193 | | |
2194 | | /// Return the scalar evolution. |
2195 | | ScalarEvolution *getSE() const; |
2196 | | |
2197 | | /// Return the dominator tree. |
2198 | 2.72k | DominatorTree *getDT() const { return DT; } |
2199 | | |
2200 | | /// Return the LoopInfo used for this Scop. |
2201 | 2.72k | LoopInfo *getLI() const { return Affinator.getLI(); } |
2202 | | |
2203 | | /// Get the count of parameters used in this Scop. |
2204 | | /// |
2205 | | /// @return The count of parameters used in this Scop. |
2206 | 1.27k | size_t getNumParams() const { return Parameters.size(); } |
2207 | | |
2208 | | /// Take a list of parameters and add the new ones to the scop. |
2209 | | void addParams(const ParameterSetTy &NewParameters); |
2210 | | |
2211 | | /// Return an iterator range containing the scop parameters. |
2212 | 638 | iterator_range<ParameterSetTy::iterator> parameters() const { |
2213 | 638 | return make_range(Parameters.begin(), Parameters.end()); |
2214 | 638 | } |
2215 | | |
2216 | | /// Return an iterator range containing invariant accesses. |
2217 | 361 | iterator_range<InvariantEquivClassesTy::iterator> invariantEquivClasses() { |
2218 | 361 | return make_range(InvariantEquivClasses.begin(), |
2219 | 361 | InvariantEquivClasses.end()); |
2220 | 361 | } |
2221 | | |
2222 | | /// Return an iterator range containing hold assumptions. |
2223 | | iterator_range<RecordedAssumptionsTy::const_iterator> |
2224 | 1.16k | recorded_assumptions() const { |
2225 | 1.16k | return make_range(RecordedAssumptions.begin(), RecordedAssumptions.end()); |
2226 | 1.16k | } |
2227 | | |
2228 | | /// Return an iterator range containing all the MemoryAccess objects of the |
2229 | | /// Scop. |
2230 | 4 | iterator_range<AccFuncVector::iterator> access_functions() { |
2231 | 4 | return make_range(AccessFunctions.begin(), AccessFunctions.end()); |
2232 | 4 | } |
2233 | | |
2234 | | /// Return whether this scop is empty, i.e. contains no statements that |
2235 | | /// could be executed. |
2236 | 1.19k | bool isEmpty() const { return Stmts.empty(); } |
2237 | | |
2238 | 0 | StringRef getName() { |
2239 | 0 | if (!name) |
2240 | 0 | name = R.getNameStr(); |
2241 | 0 | return *name; |
2242 | 0 | } |
2243 | | |
2244 | | using array_iterator = ArrayInfoSetTy::iterator; |
2245 | | using const_array_iterator = ArrayInfoSetTy::const_iterator; |
2246 | | using array_range = iterator_range<ArrayInfoSetTy::iterator>; |
2247 | | using const_array_range = iterator_range<ArrayInfoSetTy::const_iterator>; |
2248 | | |
2249 | 4.22k | inline array_iterator array_begin() { return ScopArrayInfoSet.begin(); } |
2250 | | |
2251 | 4.22k | inline array_iterator array_end() { return ScopArrayInfoSet.end(); } |
2252 | | |
2253 | 2.13k | inline const_array_iterator array_begin() const { |
2254 | 2.13k | return ScopArrayInfoSet.begin(); |
2255 | 2.13k | } |
2256 | | |
2257 | 2.13k | inline const_array_iterator array_end() const { |
2258 | 2.13k | return ScopArrayInfoSet.end(); |
2259 | 2.13k | } |
2260 | | |
2261 | 4.22k | inline array_range arrays() { |
2262 | 4.22k | return array_range(array_begin(), array_end()); |
2263 | 4.22k | } |
2264 | | |
2265 | 2.13k | inline const_array_range arrays() const { |
2266 | 2.13k | return const_array_range(array_begin(), array_end()); |
2267 | 2.13k | } |
2268 | | |
2269 | | /// Return the isl_id that represents a certain parameter. |
2270 | | /// |
2271 | | /// @param Parameter A SCEV that was recognized as a Parameter. |
2272 | | /// |
2273 | | /// @return The corresponding isl_id or NULL otherwise. |
2274 | | isl::id getIdForParam(const SCEV *Parameter) const; |
2275 | | |
2276 | | /// Get the maximum region of this static control part. |
2277 | | /// |
2278 | | /// @return The maximum region of this static control part. |
2279 | 31.3k | inline const Region &getRegion() const { return R; } |
2280 | 57.6k | inline Region &getRegion() { return R; } |
2281 | | |
2282 | | /// Return the function this SCoP is in. |
2283 | 6.55k | Function &getFunction() const { return *R.getEntry()->getParent(); } |
2284 | | |
2285 | | /// Check if @p L is contained in the SCoP. |
2286 | 12.1k | bool contains(const Loop *L) const { return R.contains(L); } |
2287 | | |
2288 | | /// Check if @p BB is contained in the SCoP. |
2289 | 30.2k | bool contains(const BasicBlock *BB) const { return R.contains(BB); } |
2290 | | |
2291 | | /// Check if @p I is contained in the SCoP. |
2292 | 6.17k | bool contains(const Instruction *I) const { return R.contains(I); } |
2293 | | |
2294 | | /// Return the unique exit block of the SCoP. |
2295 | 2.81k | BasicBlock *getExit() const { return R.getExit(); } |
2296 | | |
2297 | | /// Return the unique exiting block of the SCoP if any. |
2298 | 667 | BasicBlock *getExitingBlock() const { return R.getExitingBlock(); } |
2299 | | |
2300 | | /// Return the unique entry block of the SCoP. |
2301 | 4.78k | BasicBlock *getEntry() const { return R.getEntry(); } |
2302 | | |
2303 | | /// Return the unique entering block of the SCoP if any. |
2304 | 911 | BasicBlock *getEnteringBlock() const { return R.getEnteringBlock(); } |
2305 | | |
2306 | | /// Return true if @p BB is the exit block of the SCoP. |
2307 | 1.84k | bool isExit(BasicBlock *BB) const { return getExit() == BB; } |
2308 | | |
2309 | | /// Return a range of all basic blocks in the SCoP. |
2310 | 3.12k | Region::block_range blocks() const { return R.blocks(); } |
2311 | | |
2312 | | /// Return true if and only if @p BB dominates the SCoP. |
2313 | | bool isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const; |
2314 | | |
2315 | | /// Get the maximum depth of the loop. |
2316 | | /// |
2317 | | /// @return The maximum depth of the loop. |
2318 | 1.62k | inline unsigned getMaxLoopDepth() const { return MaxLoopDepth; } |
2319 | | |
2320 | | /// Return the invariant equivalence class for @p Val if any. |
2321 | | InvariantEquivClassTy *lookupInvariantEquivClass(Value *Val); |
2322 | | |
2323 | | /// Return the set of invariant accesses. |
2324 | 316 | InvariantEquivClassesTy &getInvariantAccesses() { |
2325 | 316 | return InvariantEquivClasses; |
2326 | 316 | } |
2327 | | |
2328 | | /// Check if the scop has any invariant access. |
2329 | 0 | bool hasInvariantAccesses() { return !InvariantEquivClasses.empty(); } |
2330 | | |
2331 | | /// Mark the SCoP as optimized by the scheduler. |
2332 | 36 | void markAsOptimized() { IsOptimized = true; } |
2333 | | |
2334 | | /// Check if the SCoP has been optimized by the scheduler. |
2335 | 0 | bool isOptimized() const { return IsOptimized; } |
2336 | | |
2337 | | /// Mark the SCoP to be skipped by ScopPass passes. |
2338 | 0 | void markAsToBeSkipped() { SkipScop = true; } |
2339 | | |
2340 | | /// Check if the SCoP is to be skipped by ScopPass passes. |
2341 | 805 | bool isToBeSkipped() const { return SkipScop; } |
2342 | | |
2343 | | /// Return the ID of the Scop |
2344 | 0 | int getID() const { return ID; } |
2345 | | |
2346 | | /// Get the name of the entry and exit blocks of this Scop. |
2347 | | /// |
2348 | | /// These along with the function name can uniquely identify a Scop. |
2349 | | /// |
2350 | | /// @return std::pair whose first element is the entry name & second element |
2351 | | /// is the exit name. |
2352 | | std::pair<std::string, std::string> getEntryExitStr() const; |
2353 | | |
2354 | | /// Get the name of this Scop. |
2355 | | std::string getNameStr() const; |
2356 | | |
2357 | | /// Get the constraint on parameter of this Scop. |
2358 | | /// |
2359 | | /// @return The constraint on parameter of this Scop. |
2360 | | isl::set getContext() const; |
2361 | | |
2362 | | /// Return space of isl context parameters. |
2363 | | /// |
2364 | | /// Returns the set of context parameters that are currently constrained. In |
2365 | | /// case the full set of parameters is needed, see @getFullParamSpace. |
2366 | | isl::space getParamSpace() const; |
2367 | | |
2368 | | /// Return the full space of parameters. |
2369 | | /// |
2370 | | /// getParamSpace will only return the parameters of the context that are |
2371 | | /// actually constrained, whereas getFullParamSpace will return all |
2372 | | // parameters. This is useful in cases, where we need to ensure all |
2373 | | // parameters are available, as certain isl functions will abort if this is |
2374 | | // not the case. |
2375 | | isl::space getFullParamSpace() const; |
2376 | | |
2377 | | /// Get the assumed context for this Scop. |
2378 | | /// |
2379 | | /// @return The assumed context of this Scop. |
2380 | | isl::set getAssumedContext() const; |
2381 | | |
2382 | | /// Return true if the optimized SCoP can be executed. |
2383 | | /// |
2384 | | /// In addition to the runtime check context this will also utilize the domain |
2385 | | /// constraints to decide it the optimized version can actually be executed. |
2386 | | /// |
2387 | | /// @returns True if the optimized SCoP can be executed. |
2388 | | bool hasFeasibleRuntimeContext() const; |
2389 | | |
2390 | | /// Clear assumptions which have been already processed. |
2391 | 1.16k | void clearRecordedAssumptions() { return RecordedAssumptions.clear(); } |
2392 | | |
2393 | | /// Check if the assumption in @p Set is trivial or not. |
2394 | | /// |
2395 | | /// @param Set The relations between parameters that are assumed to hold. |
2396 | | /// @param Sign Enum to indicate if the assumptions in @p Set are positive |
2397 | | /// (needed/assumptions) or negative (invalid/restrictions). |
2398 | | /// |
2399 | | /// @returns True if the assumption @p Set is not trivial. |
2400 | | bool isEffectiveAssumption(isl::set Set, AssumptionSign Sign); |
2401 | | |
2402 | | /// Track and report an assumption. |
2403 | | /// |
2404 | | /// Use 'clang -Rpass-analysis=polly-scops' or 'opt |
2405 | | /// -pass-remarks-analysis=polly-scops' to output the assumptions. |
2406 | | /// |
2407 | | /// @param Kind The assumption kind describing the underlying cause. |
2408 | | /// @param Set The relations between parameters that are assumed to hold. |
2409 | | /// @param Loc The location in the source that caused this assumption. |
2410 | | /// @param Sign Enum to indicate if the assumptions in @p Set are positive |
2411 | | /// (needed/assumptions) or negative (invalid/restrictions). |
2412 | | /// @param BB The block in which this assumption was taken. Used to |
2413 | | /// calculate hotness when emitting remark. |
2414 | | /// |
2415 | | /// @returns True if the assumption is not trivial. |
2416 | | bool trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, |
2417 | | AssumptionSign Sign, BasicBlock *BB); |
2418 | | |
2419 | | /// Add assumptions to assumed context. |
2420 | | /// |
2421 | | /// The assumptions added will be assumed to hold during the execution of the |
2422 | | /// scop. However, as they are generally not statically provable, at code |
2423 | | /// generation time run-time checks will be generated that ensure the |
2424 | | /// assumptions hold. |
2425 | | /// |
2426 | | /// WARNING: We currently exploit in simplifyAssumedContext the knowledge |
2427 | | /// that assumptions do not change the set of statement instances |
2428 | | /// executed. |
2429 | | /// |
2430 | | /// @param Kind The assumption kind describing the underlying cause. |
2431 | | /// @param Set The relations between parameters that are assumed to hold. |
2432 | | /// @param Loc The location in the source that caused this assumption. |
2433 | | /// @param Sign Enum to indicate if the assumptions in @p Set are positive |
2434 | | /// (needed/assumptions) or negative (invalid/restrictions). |
2435 | | /// @param BB The block in which this assumption was taken. Used to |
2436 | | /// calculate hotness when emitting remark. |
2437 | | void addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, |
2438 | | AssumptionSign Sign, BasicBlock *BB); |
2439 | | |
2440 | | /// Record an assumption for later addition to the assumed context. |
2441 | | /// |
2442 | | /// This function will add the assumption to the RecordedAssumptions. This |
2443 | | /// collection will be added (@see addAssumption) to the assumed context once |
2444 | | /// all paramaters are known and the context is fully built. |
2445 | | /// |
2446 | | /// @param Kind The assumption kind describing the underlying cause. |
2447 | | /// @param Set The relations between parameters that are assumed to hold. |
2448 | | /// @param Loc The location in the source that caused this assumption. |
2449 | | /// @param Sign Enum to indicate if the assumptions in @p Set are positive |
2450 | | /// (needed/assumptions) or negative (invalid/restrictions). |
2451 | | /// @param BB The block in which this assumption was taken. If it is |
2452 | | /// set, the domain of that block will be used to simplify the |
2453 | | /// actual assumption in @p Set once it is added. This is useful |
2454 | | /// if the assumption was created prior to the domain. |
2455 | | void recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc, |
2456 | | AssumptionSign Sign, BasicBlock *BB = nullptr); |
2457 | | |
2458 | | /// Mark the scop as invalid. |
2459 | | /// |
2460 | | /// This method adds an assumption to the scop that is always invalid. As a |
2461 | | /// result, the scop will not be optimized later on. This function is commonly |
2462 | | /// called when a condition makes it impossible (or too compile time |
2463 | | /// expensive) to process this scop any further. |
2464 | | /// |
2465 | | /// @param Kind The assumption kind describing the underlying cause. |
2466 | | /// @param Loc The location in the source that triggered . |
2467 | | /// @param BB The BasicBlock where it was triggered. |
2468 | | void invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB = nullptr); |
2469 | | |
2470 | | /// Get the invalid context for this Scop. |
2471 | | /// |
2472 | | /// @return The invalid context of this Scop. |
2473 | | isl::set getInvalidContext() const; |
2474 | | |
2475 | | /// Return true if and only if the InvalidContext is trivial (=empty). |
2476 | 458 | bool hasTrivialInvalidContext() const { return InvalidContext.is_empty(); } |
2477 | | |
2478 | | /// Return all alias groups for this SCoP. |
2479 | 1.59k | const MinMaxVectorPairVectorTy &getAliasGroups() const { |
2480 | 1.59k | return MinMaxAliasGroups; |
2481 | 1.59k | } |
2482 | | |
2483 | | void addAliasGroup(MinMaxVectorTy &MinMaxAccessesReadWrite, |
2484 | 214 | MinMaxVectorTy &MinMaxAccessesReadOnly) { |
2485 | 214 | MinMaxAliasGroups.emplace_back(); |
2486 | 214 | MinMaxAliasGroups.back().first = MinMaxAccessesReadWrite; |
2487 | 214 | MinMaxAliasGroups.back().second = MinMaxAccessesReadOnly; |
2488 | 214 | } |
2489 | | /// Get an isl string representing the context. |
2490 | | std::string getContextStr() const; |
2491 | | |
2492 | | /// Get an isl string representing the assumed context. |
2493 | | std::string getAssumedContextStr() const; |
2494 | | |
2495 | | /// Get an isl string representing the invalid context. |
2496 | | std::string getInvalidContextStr() const; |
2497 | | |
2498 | | /// Return the list of ScopStmts that represent the given @p BB. |
2499 | | ArrayRef<ScopStmt *> getStmtListFor(BasicBlock *BB) const; |
2500 | | |
2501 | | /// Get the statement to put a PHI WRITE into. |
2502 | | /// |
2503 | | /// @param U The operand of a PHINode. |
2504 | | ScopStmt *getIncomingStmtFor(const Use &U) const; |
2505 | | |
2506 | | /// Return the last statement representing @p BB. |
2507 | | /// |
2508 | | /// Of the sequence of statements that represent a @p BB, this is the last one |
2509 | | /// to be executed. It is typically used to determine which instruction to add |
2510 | | /// a MemoryKind::PHI WRITE to. For this purpose, it is not strictly required |
2511 | | /// to be executed last, only that the incoming value is available in it. |
2512 | | ScopStmt *getLastStmtFor(BasicBlock *BB) const; |
2513 | | |
2514 | | /// Return the ScopStmts that represents the Region @p R, or nullptr if |
2515 | | /// it is not represented by any statement in this Scop. |
2516 | | ArrayRef<ScopStmt *> getStmtListFor(Region *R) const; |
2517 | | |
2518 | | /// Return the ScopStmts that represents @p RN; can return nullptr if |
2519 | | /// the RegionNode is not within the SCoP or has been removed due to |
2520 | | /// simplifications. |
2521 | | ArrayRef<ScopStmt *> getStmtListFor(RegionNode *RN) const; |
2522 | | |
2523 | | /// Return the ScopStmt an instruction belongs to, or nullptr if it |
2524 | | /// does not belong to any statement in this Scop. |
2525 | 4.95k | ScopStmt *getStmtFor(Instruction *Inst) const { |
2526 | 4.95k | return InstStmtMap.lookup(Inst); |
2527 | 4.95k | } |
2528 | | |
2529 | | /// Return the number of statements in the SCoP. |
2530 | 306 | size_t getSize() const { return Stmts.size(); } |
2531 | | |
2532 | | /// @name Statements Iterators |
2533 | | /// |
2534 | | /// These iterators iterate over all statements of this Scop. |
2535 | | //@{ |
2536 | | using iterator = StmtSet::iterator; |
2537 | | using const_iterator = StmtSet::const_iterator; |
2538 | | |
2539 | 15.0k | iterator begin() { return Stmts.begin(); } |
2540 | 15.0k | iterator end() { return Stmts.end(); } |
2541 | 13.2k | const_iterator begin() const { return Stmts.begin(); } |
2542 | 13.2k | const_iterator end() const { return Stmts.end(); } |
2543 | | |
2544 | | using reverse_iterator = StmtSet::reverse_iterator; |
2545 | | using const_reverse_iterator = StmtSet::const_reverse_iterator; |
2546 | | |
2547 | 0 | reverse_iterator rbegin() { return Stmts.rbegin(); } |
2548 | 0 | reverse_iterator rend() { return Stmts.rend(); } |
2549 | 0 | const_reverse_iterator rbegin() const { return Stmts.rbegin(); } |
2550 | 0 | const_reverse_iterator rend() const { return Stmts.rend(); } |
2551 | | //@} |
2552 | | |
2553 | | /// Return the set of required invariant loads. |
2554 | 48.3k | const InvariantLoadsSetTy &getRequiredInvariantLoads() const { |
2555 | 48.3k | return DC.RequiredILS; |
2556 | 48.3k | } |
2557 | | |
2558 | | /// Add @p LI to the set of required invariant loads. |
2559 | 0 | void addRequiredInvariantLoad(LoadInst *LI) { DC.RequiredILS.insert(LI); } |
2560 | | |
2561 | | /// Return the set of boxed (thus overapproximated) loops. |
2562 | 14.4k | const BoxedLoopsSetTy &getBoxedLoops() const { return DC.BoxedLoopsSet; } |
2563 | | |
2564 | | /// Return true if and only if @p R is a non-affine subregion. |
2565 | 10.3k | bool isNonAffineSubRegion(const Region *R) { |
2566 | 10.3k | return DC.NonAffineSubRegionSet.count(R); |
2567 | 10.3k | } |
2568 | | |
2569 | 3.38k | const MapInsnToMemAcc &getInsnToMemAccMap() const { return DC.InsnToMemAcc; } |
2570 | | |
2571 | | /// Return the (possibly new) ScopArrayInfo object for @p Access. |
2572 | | /// |
2573 | | /// @param ElementType The type of the elements stored in this array. |
2574 | | /// @param Kind The kind of the array info object. |
2575 | | /// @param BaseName The optional name of this memory reference. |
2576 | | ScopArrayInfo *getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType, |
2577 | | ArrayRef<const SCEV *> Sizes, |
2578 | | MemoryKind Kind, |
2579 | | const char *BaseName = nullptr); |
2580 | | |
2581 | | /// Create an array and return the corresponding ScopArrayInfo object. |
2582 | | /// |
2583 | | /// @param ElementType The type of the elements stored in this array. |
2584 | | /// @param BaseName The name of this memory reference. |
2585 | | /// @param Sizes The sizes of dimensions. |
2586 | | ScopArrayInfo *createScopArrayInfo(Type *ElementType, |
2587 | | const std::string &BaseName, |
2588 | | const std::vector<unsigned> &Sizes); |
2589 | | |
2590 | | /// Return the cached ScopArrayInfo object for @p BasePtr. |
2591 | | /// |
2592 | | /// @param BasePtr The base pointer the object has been stored for. |
2593 | | /// @param Kind The kind of array info object. |
2594 | | /// |
2595 | | /// @returns The ScopArrayInfo pointer or NULL if no such pointer is |
2596 | | /// available. |
2597 | | const ScopArrayInfo *getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind); |
2598 | | |
2599 | | /// Return the cached ScopArrayInfo object for @p BasePtr. |
2600 | | /// |
2601 | | /// @param BasePtr The base pointer the object has been stored for. |
2602 | | /// @param Kind The kind of array info object. |
2603 | | /// |
2604 | | /// @returns The ScopArrayInfo pointer (may assert if no such pointer is |
2605 | | /// available). |
2606 | | const ScopArrayInfo *getScopArrayInfo(Value *BasePtr, MemoryKind Kind); |
2607 | | |
2608 | | /// Invalidate ScopArrayInfo object for base address. |
2609 | | /// |
2610 | | /// @param BasePtr The base pointer of the ScopArrayInfo object to invalidate. |
2611 | | /// @param Kind The Kind of the ScopArrayInfo object. |
2612 | 0 | void invalidateScopArrayInfo(Value *BasePtr, MemoryKind Kind) { |
2613 | 0 | auto It = ScopArrayInfoMap.find(std::make_pair(BasePtr, Kind)); |
2614 | 0 | if (It == ScopArrayInfoMap.end()) |
2615 | 0 | return; |
2616 | 0 | ScopArrayInfoSet.remove(It->second.get()); |
2617 | 0 | ScopArrayInfoMap.erase(It); |
2618 | 0 | } |
2619 | | |
2620 | | void setContext(isl::set NewContext); |
2621 | | |
2622 | | /// Align the parameters in the statement to the scop context |
2623 | | void realignParams(); |
2624 | | |
2625 | | /// Return true if this SCoP can be profitably optimized. |
2626 | | /// |
2627 | | /// @param ScalarsAreUnprofitable Never consider statements with scalar writes |
2628 | | /// as profitably optimizable. |
2629 | | /// |
2630 | | /// @return Whether this SCoP can be profitably optimized. |
2631 | | bool isProfitable(bool ScalarsAreUnprofitable) const; |
2632 | | |
2633 | | /// Return true if the SCoP contained at least one error block. |
2634 | 1.16k | bool hasErrorBlock() const { return HasErrorBlock; } |
2635 | | |
2636 | | /// Return true if the underlying region has a single exiting block. |
2637 | 20.6k | bool hasSingleExitEdge() const { return HasSingleExitEdge; } |
2638 | | |
2639 | | /// Print the static control part. |
2640 | | /// |
2641 | | /// @param OS The output stream the static control part is printed to. |
2642 | | /// @param PrintInstructions Whether to print the statement's instructions as |
2643 | | /// well. |
2644 | | void print(raw_ostream &OS, bool PrintInstructions) const; |
2645 | | |
2646 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
2647 | | /// Print the ScopStmt to stderr. |
2648 | | void dump() const; |
2649 | | #endif |
2650 | | |
2651 | | /// Get the isl context of this static control part. |
2652 | | /// |
2653 | | /// @return The isl context of this static control part. |
2654 | | isl::ctx getIslCtx() const; |
2655 | | |
2656 | | /// Directly return the shared_ptr of the context. |
2657 | 1.98k | const std::shared_ptr<isl_ctx> &getSharedIslCtx() const { return IslCtx; } |
2658 | | |
2659 | | /// Compute the isl representation for the SCEV @p E |
2660 | | /// |
2661 | | /// @param E The SCEV that should be translated. |
2662 | | /// @param BB An (optional) basic block in which the isl_pw_aff is computed. |
2663 | | /// SCEVs known to not reference any loops in the SCoP can be |
2664 | | /// passed without a @p BB. |
2665 | | /// @param NonNegative Flag to indicate the @p E has to be non-negative. |
2666 | | /// |
2667 | | /// Note that this function will always return a valid isl_pw_aff. However, if |
2668 | | /// the translation of @p E was deemed to complex the SCoP is invalidated and |
2669 | | /// a dummy value of appropriate dimension is returned. This allows to bail |
2670 | | /// for complex cases without "error handling code" needed on the users side. |
2671 | | PWACtx getPwAff(const SCEV *E, BasicBlock *BB = nullptr, |
2672 | | bool NonNegative = false); |
2673 | | |
2674 | | /// Compute the isl representation for the SCEV @p E |
2675 | | /// |
2676 | | /// This function is like @see Scop::getPwAff() but strips away the invalid |
2677 | | /// domain part associated with the piecewise affine function. |
2678 | | isl::pw_aff getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr); |
2679 | | |
2680 | | /// Return the domain of @p Stmt. |
2681 | | /// |
2682 | | /// @param Stmt The statement for which the conditions should be returned. |
2683 | | isl::set getDomainConditions(const ScopStmt *Stmt) const; |
2684 | | |
2685 | | /// Return the domain of @p BB. |
2686 | | /// |
2687 | | /// @param BB The block for which the conditions should be returned. |
2688 | | isl::set getDomainConditions(BasicBlock *BB) const; |
2689 | | |
2690 | | /// Get a union set containing the iteration domains of all statements. |
2691 | | isl::union_set getDomains() const; |
2692 | | |
2693 | | /// Get a union map of all may-writes performed in the SCoP. |
2694 | | isl::union_map getMayWrites(); |
2695 | | |
2696 | | /// Get a union map of all must-writes performed in the SCoP. |
2697 | | isl::union_map getMustWrites(); |
2698 | | |
2699 | | /// Get a union map of all writes performed in the SCoP. |
2700 | | isl::union_map getWrites(); |
2701 | | |
2702 | | /// Get a union map of all reads performed in the SCoP. |
2703 | | isl::union_map getReads(); |
2704 | | |
2705 | | /// Get a union map of all memory accesses performed in the SCoP. |
2706 | | isl::union_map getAccesses(); |
2707 | | |
2708 | | /// Get a union map of all memory accesses performed in the SCoP. |
2709 | | /// |
2710 | | /// @param Array The array to which the accesses should belong. |
2711 | | isl::union_map getAccesses(ScopArrayInfo *Array); |
2712 | | |
2713 | | /// Get the schedule of all the statements in the SCoP. |
2714 | | /// |
2715 | | /// @return The schedule of all the statements in the SCoP, if the schedule of |
2716 | | /// the Scop does not contain extension nodes, and nullptr, otherwise. |
2717 | | isl::union_map getSchedule() const; |
2718 | | |
2719 | | /// Get a schedule tree describing the schedule of all statements. |
2720 | | isl::schedule getScheduleTree() const; |
2721 | | |
2722 | | /// Update the current schedule |
2723 | | /// |
2724 | | /// NewSchedule The new schedule (given as a flat union-map). |
2725 | | void setSchedule(isl::union_map NewSchedule); |
2726 | | |
2727 | | /// Update the current schedule |
2728 | | /// |
2729 | | /// NewSchedule The new schedule (given as schedule tree). |
2730 | | void setScheduleTree(isl::schedule NewSchedule); |
2731 | | |
2732 | | /// Whether the schedule is the original schedule as derived from the CFG by |
2733 | | /// ScopBuilder. |
2734 | 89 | bool isOriginalSchedule() const { return !ScheduleModified; } |
2735 | | |
2736 | | /// Intersects the domains of all statements in the SCoP. |
2737 | | /// |
2738 | | /// @return true if a change was made |
2739 | | bool restrictDomains(isl::union_set Domain); |
2740 | | |
2741 | | /// Get the depth of a loop relative to the outermost loop in the Scop. |
2742 | | /// |
2743 | | /// This will return |
2744 | | /// 0 if @p L is an outermost loop in the SCoP |
2745 | | /// >0 for other loops in the SCoP |
2746 | | /// -1 if @p L is nullptr or there is no outermost loop in the SCoP |
2747 | | int getRelativeLoopDepth(const Loop *L) const; |
2748 | | |
2749 | | /// Find the ScopArrayInfo associated with an isl Id |
2750 | | /// that has name @p Name. |
2751 | | ScopArrayInfo *getArrayInfoByName(const std::string BaseName); |
2752 | | |
2753 | | /// Simplify the SCoP representation. |
2754 | | /// |
2755 | | /// @param AfterHoisting Whether it is called after invariant load hoisting. |
2756 | | /// When true, also removes statements without |
2757 | | /// side-effects. |
2758 | | void simplifySCoP(bool AfterHoisting); |
2759 | | |
2760 | | /// Get the next free array index. |
2761 | | /// |
2762 | | /// This function returns a unique index which can be used to identify an |
2763 | | /// array. |
2764 | 2.48k | long getNextArrayIdx() { return ArrayIdx++; } |
2765 | | |
2766 | | /// Get the next free statement index. |
2767 | | /// |
2768 | | /// This function returns a unique index which can be used to identify a |
2769 | | /// statement. |
2770 | 5.74k | long getNextStmtIdx() { return StmtIdx++; } |
2771 | | |
2772 | | /// Return the MemoryAccess that writes an llvm::Value, represented by a |
2773 | | /// ScopArrayInfo. |
2774 | | /// |
2775 | | /// There can be at most one such MemoryAccess per llvm::Value in the SCoP. |
2776 | | /// Zero is possible for read-only values. |
2777 | | MemoryAccess *getValueDef(const ScopArrayInfo *SAI) const; |
2778 | | |
2779 | | /// Return all MemoryAccesses that us an llvm::Value, represented by a |
2780 | | /// ScopArrayInfo. |
2781 | | ArrayRef<MemoryAccess *> getValueUses(const ScopArrayInfo *SAI) const; |
2782 | | |
2783 | | /// Return the MemoryAccess that represents an llvm::PHINode. |
2784 | | /// |
2785 | | /// ExitPHIs's PHINode is not within the SCoPs. This function returns nullptr |
2786 | | /// for them. |
2787 | | MemoryAccess *getPHIRead(const ScopArrayInfo *SAI) const; |
2788 | | |
2789 | | /// Return all MemoryAccesses for all incoming statements of a PHINode, |
2790 | | /// represented by a ScopArrayInfo. |
2791 | | ArrayRef<MemoryAccess *> getPHIIncomings(const ScopArrayInfo *SAI) const; |
2792 | | |
2793 | | /// Return whether @p Inst has a use outside of this SCoP. |
2794 | | bool isEscaping(Instruction *Inst); |
2795 | | |
2796 | | struct ScopStatistics { |
2797 | | int NumAffineLoops = 0; |
2798 | | int NumBoxedLoops = 0; |
2799 | | |
2800 | | int NumValueWrites = 0; |
2801 | | int NumValueWritesInLoops = 0; |
2802 | | int NumPHIWrites = 0; |
2803 | | int NumPHIWritesInLoops = 0; |
2804 | | int NumSingletonWrites = 0; |
2805 | | int NumSingletonWritesInLoops = 0; |
2806 | | }; |
2807 | | |
2808 | | /// Collect statistic about this SCoP. |
2809 | | /// |
2810 | | /// These are most commonly used for LLVM's static counters (Statistic.h) in |
2811 | | /// various places. If statistics are disabled, only zeros are returned to |
2812 | | /// avoid the overhead. |
2813 | | ScopStatistics getStatistics() const; |
2814 | | }; |
2815 | | |
2816 | | /// Print Scop scop to raw_ostream OS. |
2817 | | raw_ostream &operator<<(raw_ostream &OS, const Scop &scop); |
2818 | | |
2819 | | /// The legacy pass manager's analysis pass to compute scop information |
2820 | | /// for a region. |
2821 | | class ScopInfoRegionPass : public RegionPass { |
2822 | | /// The Scop pointer which is used to construct a Scop. |
2823 | | std::unique_ptr<Scop> S; |
2824 | | |
2825 | | public: |
2826 | | static char ID; // Pass identification, replacement for typeid |
2827 | | |
2828 | 1.13k | ScopInfoRegionPass() : RegionPass(ID) {} |
2829 | 1.11k | ~ScopInfoRegionPass() override = default; |
2830 | | |
2831 | | /// Build Scop object, the Polly IR of static control |
2832 | | /// part for the current SESE-Region. |
2833 | | /// |
2834 | | /// @return If the current region is a valid for a static control part, |
2835 | | /// return the Polly IR representing this static control part, |
2836 | | /// return null otherwise. |
2837 | 6.82k | Scop *getScop() { return S.get(); } |
2838 | 0 | const Scop *getScop() const { return S.get(); } |
2839 | | |
2840 | | /// Calculate the polyhedral scop information for a given Region. |
2841 | | bool runOnRegion(Region *R, RGPassManager &RGM) override; |
2842 | | |
2843 | 4.27k | void releaseMemory() override { S.reset(); } |
2844 | | |
2845 | | void print(raw_ostream &O, const Module *M = nullptr) const override; |
2846 | | |
2847 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
2848 | | }; |
2849 | | |
2850 | | class ScopInfo { |
2851 | | public: |
2852 | | using RegionToScopMapTy = MapVector<Region *, std::unique_ptr<Scop>>; |
2853 | | using reverse_iterator = RegionToScopMapTy::reverse_iterator; |
2854 | | using const_reverse_iterator = RegionToScopMapTy::const_reverse_iterator; |
2855 | | using iterator = RegionToScopMapTy::iterator; |
2856 | | using const_iterator = RegionToScopMapTy::const_iterator; |
2857 | | |
2858 | | private: |
2859 | | /// A map of Region to its Scop object containing |
2860 | | /// Polly IR of static control part. |
2861 | | RegionToScopMapTy RegionToScopMap; |
2862 | | const DataLayout &DL; |
2863 | | ScopDetection &SD; |
2864 | | ScalarEvolution &SE; |
2865 | | LoopInfo &LI; |
2866 | | AliasAnalysis &AA; |
2867 | | DominatorTree &DT; |
2868 | | AssumptionCache &AC; |
2869 | | OptimizationRemarkEmitter &ORE; |
2870 | | |
2871 | | public: |
2872 | | ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE, |
2873 | | LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT, |
2874 | | AssumptionCache &AC, OptimizationRemarkEmitter &ORE); |
2875 | | |
2876 | | /// Get the Scop object for the given Region. |
2877 | | /// |
2878 | | /// @return If the given region is the maximal region within a scop, return |
2879 | | /// the scop object. If the given region is a subregion, return a |
2880 | | /// nullptr. Top level region containing the entry block of a function |
2881 | | /// is not considered in the scop creation. |
2882 | 0 | Scop *getScop(Region *R) const { |
2883 | 0 | auto MapIt = RegionToScopMap.find(R); |
2884 | 0 | if (MapIt != RegionToScopMap.end()) |
2885 | 0 | return MapIt->second.get(); |
2886 | 0 | return nullptr; |
2887 | 0 | } |
2888 | | |
2889 | | /// Recompute the Scop-Information for a function. |
2890 | | /// |
2891 | | /// This invalidates any iterators. |
2892 | | void recompute(); |
2893 | | |
2894 | | /// Handle invalidation explicitly |
2895 | | bool invalidate(Function &F, const PreservedAnalyses &PA, |
2896 | | FunctionAnalysisManager::Invalidator &Inv); |
2897 | | |
2898 | 82 | iterator begin() { return RegionToScopMap.begin(); } |
2899 | 82 | iterator end() { return RegionToScopMap.end(); } |
2900 | 0 | const_iterator begin() const { return RegionToScopMap.begin(); } |
2901 | 0 | const_iterator end() const { return RegionToScopMap.end(); } |
2902 | 0 | reverse_iterator rbegin() { return RegionToScopMap.rbegin(); } |
2903 | 0 | reverse_iterator rend() { return RegionToScopMap.rend(); } |
2904 | 0 | const_reverse_iterator rbegin() const { return RegionToScopMap.rbegin(); } |
2905 | 0 | const_reverse_iterator rend() const { return RegionToScopMap.rend(); } |
2906 | 1 | bool empty() const { return RegionToScopMap.empty(); } |
2907 | | }; |
2908 | | |
2909 | | struct ScopInfoAnalysis : public AnalysisInfoMixin<ScopInfoAnalysis> { |
2910 | | static AnalysisKey Key; |
2911 | | |
2912 | | using Result = ScopInfo; |
2913 | | |
2914 | | Result run(Function &, FunctionAnalysisManager &); |
2915 | | }; |
2916 | | |
2917 | | struct ScopInfoPrinterPass : public PassInfoMixin<ScopInfoPrinterPass> { |
2918 | 1 | ScopInfoPrinterPass(raw_ostream &OS) : Stream(OS) {} |
2919 | | |
2920 | | PreservedAnalyses run(Function &, FunctionAnalysisManager &); |
2921 | | |
2922 | | raw_ostream &Stream; |
2923 | | }; |
2924 | | |
2925 | | //===----------------------------------------------------------------------===// |
2926 | | /// The legacy pass manager's analysis pass to compute scop information |
2927 | | /// for the whole function. |
2928 | | /// |
2929 | | /// This pass will maintain a map of the maximal region within a scop to its |
2930 | | /// scop object for all the feasible scops present in a function. |
2931 | | /// This pass is an alternative to the ScopInfoRegionPass in order to avoid a |
2932 | | /// region pass manager. |
2933 | | class ScopInfoWrapperPass : public FunctionPass { |
2934 | | std::unique_ptr<ScopInfo> Result; |
2935 | | |
2936 | | public: |
2937 | 44 | ScopInfoWrapperPass() : FunctionPass(ID) {} |
2938 | 44 | ~ScopInfoWrapperPass() override = default; |
2939 | | |
2940 | | static char ID; // Pass identification, replacement for typeid |
2941 | | |
2942 | 45 | ScopInfo *getSI() { return Result.get(); } |
2943 | 0 | const ScopInfo *getSI() const { return Result.get(); } |
2944 | | |
2945 | | /// Calculate all the polyhedral scops for a given function. |
2946 | | bool runOnFunction(Function &F) override; |
2947 | | |
2948 | 49 | void releaseMemory() override { Result.reset(); } |
2949 | | |
2950 | | void print(raw_ostream &O, const Module *M = nullptr) const override; |
2951 | | |
2952 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
2953 | | }; |
2954 | | } // end namespace polly |
2955 | | |
2956 | | #endif // POLLY_SCOPINFO_H |