Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===------ Support/ScopHelper.h -- Some Helper Functions for Scop. -------===// |
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 | // Small functions that help with LLVM-IR. |
||
10 | // |
||
11 | //===----------------------------------------------------------------------===// |
||
12 | |||
13 | #ifndef POLLY_SUPPORT_IRHELPER_H |
||
14 | #define POLLY_SUPPORT_IRHELPER_H |
||
15 | |||
16 | #include "llvm/ADT/SetVector.h" |
||
17 | #include "llvm/IR/Instructions.h" |
||
18 | #include "llvm/IR/IntrinsicInst.h" |
||
19 | #include "llvm/IR/ValueHandle.h" |
||
20 | #include "isl/isl-noexceptions.h" |
||
21 | #include <optional> |
||
22 | |||
23 | namespace llvm { |
||
24 | class LoopInfo; |
||
25 | class Loop; |
||
26 | class ScalarEvolution; |
||
27 | class SCEV; |
||
28 | class Region; |
||
29 | class Pass; |
||
30 | class DominatorTree; |
||
31 | class RegionInfo; |
||
32 | class RegionNode; |
||
33 | } // namespace llvm |
||
34 | |||
35 | namespace polly { |
||
36 | class Scop; |
||
37 | class ScopStmt; |
||
38 | |||
39 | /// Enumeration of assumptions Polly can take. |
||
40 | enum AssumptionKind { |
||
41 | ALIASING, |
||
42 | INBOUNDS, |
||
43 | WRAPPING, |
||
44 | UNSIGNED, |
||
45 | PROFITABLE, |
||
46 | ERRORBLOCK, |
||
47 | COMPLEXITY, |
||
48 | INFINITELOOP, |
||
49 | INVARIANTLOAD, |
||
50 | DELINEARIZATION, |
||
51 | }; |
||
52 | |||
53 | /// Enum to distinguish between assumptions and restrictions. |
||
54 | enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION }; |
||
55 | |||
56 | /// Helper struct to remember assumptions. |
||
57 | struct Assumption { |
||
58 | /// The kind of the assumption (e.g., WRAPPING). |
||
59 | AssumptionKind Kind; |
||
60 | |||
61 | /// Flag to distinguish assumptions and restrictions. |
||
62 | AssumptionSign Sign; |
||
63 | |||
64 | /// The valid/invalid context if this is an assumption/restriction. |
||
65 | isl::set Set; |
||
66 | |||
67 | /// The location that caused this assumption. |
||
68 | llvm::DebugLoc Loc; |
||
69 | |||
70 | /// An optional block whose domain can simplify the assumption. |
||
71 | llvm::BasicBlock *BB; |
||
72 | |||
73 | // Whether the assumption must be checked at runtime. |
||
74 | bool RequiresRTC; |
||
75 | }; |
||
76 | |||
77 | using RecordedAssumptionsTy = llvm::SmallVector<Assumption, 8>; |
||
78 | |||
79 | /// Record an assumption for later addition to the assumed context. |
||
80 | /// |
||
81 | /// This function will add the assumption to the RecordedAssumptions. This |
||
82 | /// collection will be added (@see addAssumption) to the assumed context once |
||
83 | /// all paramaters are known and the context is fully built. |
||
84 | /// |
||
85 | /// @param RecordedAssumption container which keeps all recorded assumptions. |
||
86 | /// @param Kind The assumption kind describing the underlying cause. |
||
87 | /// @param Set The relations between parameters that are assumed to hold. |
||
88 | /// @param Loc The location in the source that caused this assumption. |
||
89 | /// @param Sign Enum to indicate if the assumptions in @p Set are positive |
||
90 | /// (needed/assumptions) or negative (invalid/restrictions). |
||
91 | /// @param BB The block in which this assumption was taken. If it is |
||
92 | /// set, the domain of that block will be used to simplify the |
||
93 | /// actual assumption in @p Set once it is added. This is useful |
||
94 | /// if the assumption was created prior to the domain. |
||
95 | /// @param RTC Does the assumption require a runtime check? |
||
96 | void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions, |
||
97 | AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc, |
||
98 | AssumptionSign Sign, llvm::BasicBlock *BB = nullptr, |
||
99 | bool RTC = true); |
||
100 | |||
101 | /// Type to remap values. |
||
102 | using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>, |
||
103 | llvm::AssertingVH<llvm::Value>>; |
||
104 | |||
105 | /// Type for a set of invariant loads. |
||
106 | using InvariantLoadsSetTy = llvm::SetVector<llvm::AssertingVH<llvm::LoadInst>>; |
||
107 | |||
108 | /// Set type for parameters. |
||
109 | using ParameterSetTy = llvm::SetVector<const llvm::SCEV *>; |
||
110 | |||
111 | /// Set of loops (used to remember loops in non-affine subregions). |
||
112 | using BoxedLoopsSetTy = llvm::SetVector<const llvm::Loop *>; |
||
113 | |||
114 | /// Utility proxy to wrap the common members of LoadInst and StoreInst. |
||
115 | /// |
||
116 | /// This works like the LLVM utility class CallSite, ie. it forwards all calls |
||
117 | /// to either a LoadInst, StoreInst, MemIntrinsic or MemTransferInst. |
||
118 | /// It is similar to LLVM's utility classes IntrinsicInst, MemIntrinsic, |
||
119 | /// MemTransferInst, etc. in that it offers a common interface, but does not act |
||
120 | /// as a fake base class. |
||
121 | /// It is similar to StringRef and ArrayRef in that it holds a pointer to the |
||
122 | /// referenced object and should be passed by-value as it is small enough. |
||
123 | /// |
||
124 | /// This proxy can either represent a LoadInst instance, a StoreInst instance, |
||
125 | /// a MemIntrinsic instance (memset, memmove, memcpy), a CallInst instance or a |
||
126 | /// nullptr (only creatable using the default constructor); never an Instruction |
||
127 | /// that is neither of the above mentioned. When representing a nullptr, only |
||
128 | /// the following methods are defined: |
||
129 | /// isNull(), isInstruction(), isLoad(), isStore(), ..., isMemTransferInst(), |
||
130 | /// operator bool(), operator!() |
||
131 | /// |
||
132 | /// The functions isa, cast, cast_or_null, dyn_cast are modeled te resemble |
||
133 | /// those from llvm/Support/Casting.h. Partial template function specialization |
||
134 | /// is currently not supported in C++ such that those cannot be used directly. |
||
135 | /// (llvm::isa could, but then llvm:cast etc. would not have the expected |
||
136 | /// behavior) |
||
137 | class MemAccInst final { |
||
138 | private: |
||
139 | llvm::Instruction *I; |
||
140 | |||
141 | public: |
||
142 | MemAccInst() : I(nullptr) {} |
||
143 | MemAccInst(const MemAccInst &Inst) : I(Inst.I) {} |
||
144 | /* implicit */ MemAccInst(llvm::LoadInst &LI) : I(&LI) {} |
||
145 | /* implicit */ MemAccInst(llvm::LoadInst *LI) : I(LI) {} |
||
146 | /* implicit */ MemAccInst(llvm::StoreInst &SI) : I(&SI) {} |
||
147 | /* implicit */ MemAccInst(llvm::StoreInst *SI) : I(SI) {} |
||
148 | /* implicit */ MemAccInst(llvm::MemIntrinsic *MI) : I(MI) {} |
||
149 | /* implicit */ MemAccInst(llvm::CallInst *CI) : I(CI) {} |
||
150 | explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); } |
||
151 | explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); } |
||
152 | |||
153 | static bool isa(const llvm::Value &V) { |
||
154 | return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) || |
||
155 | llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V); |
||
156 | } |
||
157 | static bool isa(const llvm::Value *V) { |
||
158 | return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) || |
||
159 | llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V); |
||
160 | } |
||
161 | static MemAccInst cast(llvm::Value &V) { |
||
162 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
163 | } |
||
164 | static MemAccInst cast(llvm::Value *V) { |
||
165 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
166 | } |
||
167 | static MemAccInst cast_or_null(llvm::Value &V) { |
||
168 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
169 | } |
||
170 | static MemAccInst cast_or_null(llvm::Value *V) { |
||
171 | if (!V) |
||
172 | return MemAccInst(); |
||
173 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
174 | } |
||
175 | static MemAccInst dyn_cast(llvm::Value &V) { |
||
176 | if (isa(V)) |
||
177 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
178 | return MemAccInst(); |
||
179 | } |
||
180 | static MemAccInst dyn_cast(llvm::Value *V) { |
||
181 | assert(V); |
||
182 | if (isa(V)) |
||
183 | return MemAccInst(llvm::cast<llvm::Instruction>(V)); |
||
184 | return MemAccInst(); |
||
185 | } |
||
186 | |||
187 | MemAccInst &operator=(const MemAccInst &Inst) { |
||
188 | I = Inst.I; |
||
189 | return *this; |
||
190 | } |
||
191 | MemAccInst &operator=(llvm::LoadInst &LI) { |
||
192 | I = &LI; |
||
193 | return *this; |
||
194 | } |
||
195 | MemAccInst &operator=(llvm::LoadInst *LI) { |
||
196 | I = LI; |
||
197 | return *this; |
||
198 | } |
||
199 | MemAccInst &operator=(llvm::StoreInst &SI) { |
||
200 | I = &SI; |
||
201 | return *this; |
||
202 | } |
||
203 | MemAccInst &operator=(llvm::StoreInst *SI) { |
||
204 | I = SI; |
||
205 | return *this; |
||
206 | } |
||
207 | MemAccInst &operator=(llvm::MemIntrinsic &MI) { |
||
208 | I = &MI; |
||
209 | return *this; |
||
210 | } |
||
211 | MemAccInst &operator=(llvm::MemIntrinsic *MI) { |
||
212 | I = MI; |
||
213 | return *this; |
||
214 | } |
||
215 | MemAccInst &operator=(llvm::CallInst &CI) { |
||
216 | I = &CI; |
||
217 | return *this; |
||
218 | } |
||
219 | MemAccInst &operator=(llvm::CallInst *CI) { |
||
220 | I = CI; |
||
221 | return *this; |
||
222 | } |
||
223 | |||
224 | llvm::Instruction *get() const { |
||
225 | assert(I && "Unexpected nullptr!"); |
||
226 | return I; |
||
227 | } |
||
228 | operator llvm::Instruction *() const { return asInstruction(); } |
||
229 | llvm::Instruction *operator->() const { return get(); } |
||
230 | |||
231 | explicit operator bool() const { return isInstruction(); } |
||
232 | bool operator!() const { return isNull(); } |
||
233 | |||
234 | llvm::Value *getValueOperand() const { |
||
235 | if (isLoad()) |
||
236 | return asLoad(); |
||
237 | if (isStore()) |
||
238 | return asStore()->getValueOperand(); |
||
239 | if (isMemIntrinsic()) |
||
240 | return nullptr; |
||
241 | if (isCallInst()) |
||
242 | return nullptr; |
||
243 | llvm_unreachable("Operation not supported on nullptr"); |
||
244 | } |
||
245 | llvm::Value *getPointerOperand() const { |
||
246 | if (isLoad()) |
||
247 | return asLoad()->getPointerOperand(); |
||
248 | if (isStore()) |
||
249 | return asStore()->getPointerOperand(); |
||
250 | if (isMemIntrinsic()) |
||
251 | return asMemIntrinsic()->getRawDest(); |
||
252 | if (isCallInst()) |
||
253 | return nullptr; |
||
254 | llvm_unreachable("Operation not supported on nullptr"); |
||
255 | } |
||
256 | bool isVolatile() const { |
||
257 | if (isLoad()) |
||
258 | return asLoad()->isVolatile(); |
||
259 | if (isStore()) |
||
260 | return asStore()->isVolatile(); |
||
261 | if (isMemIntrinsic()) |
||
262 | return asMemIntrinsic()->isVolatile(); |
||
263 | if (isCallInst()) |
||
264 | return false; |
||
265 | llvm_unreachable("Operation not supported on nullptr"); |
||
266 | } |
||
267 | bool isSimple() const { |
||
268 | if (isLoad()) |
||
269 | return asLoad()->isSimple(); |
||
270 | if (isStore()) |
||
271 | return asStore()->isSimple(); |
||
272 | if (isMemIntrinsic()) |
||
273 | return !asMemIntrinsic()->isVolatile(); |
||
274 | if (isCallInst()) |
||
275 | return true; |
||
276 | llvm_unreachable("Operation not supported on nullptr"); |
||
277 | } |
||
278 | llvm::AtomicOrdering getOrdering() const { |
||
279 | if (isLoad()) |
||
280 | return asLoad()->getOrdering(); |
||
281 | if (isStore()) |
||
282 | return asStore()->getOrdering(); |
||
283 | if (isMemIntrinsic()) |
||
284 | return llvm::AtomicOrdering::NotAtomic; |
||
285 | if (isCallInst()) |
||
286 | return llvm::AtomicOrdering::NotAtomic; |
||
287 | llvm_unreachable("Operation not supported on nullptr"); |
||
288 | } |
||
289 | bool isUnordered() const { |
||
290 | if (isLoad()) |
||
291 | return asLoad()->isUnordered(); |
||
292 | if (isStore()) |
||
293 | return asStore()->isUnordered(); |
||
294 | // Copied from the Load/Store implementation of isUnordered: |
||
295 | if (isMemIntrinsic()) |
||
296 | return !asMemIntrinsic()->isVolatile(); |
||
297 | if (isCallInst()) |
||
298 | return true; |
||
299 | llvm_unreachable("Operation not supported on nullptr"); |
||
300 | } |
||
301 | |||
302 | bool isNull() const { return !I; } |
||
303 | bool isInstruction() const { return I; } |
||
304 | |||
305 | llvm::Instruction *asInstruction() const { return I; } |
||
306 | |||
307 | bool isLoad() const { return I && llvm::isa<llvm::LoadInst>(I); } |
||
308 | bool isStore() const { return I && llvm::isa<llvm::StoreInst>(I); } |
||
309 | bool isCallInst() const { return I && llvm::isa<llvm::CallInst>(I); } |
||
310 | bool isMemIntrinsic() const { return I && llvm::isa<llvm::MemIntrinsic>(I); } |
||
311 | bool isMemSetInst() const { return I && llvm::isa<llvm::MemSetInst>(I); } |
||
312 | bool isMemTransferInst() const { |
||
313 | return I && llvm::isa<llvm::MemTransferInst>(I); |
||
314 | } |
||
315 | |||
316 | llvm::LoadInst *asLoad() const { return llvm::cast<llvm::LoadInst>(I); } |
||
317 | llvm::StoreInst *asStore() const { return llvm::cast<llvm::StoreInst>(I); } |
||
318 | llvm::CallInst *asCallInst() const { return llvm::cast<llvm::CallInst>(I); } |
||
319 | llvm::MemIntrinsic *asMemIntrinsic() const { |
||
320 | return llvm::cast<llvm::MemIntrinsic>(I); |
||
321 | } |
||
322 | llvm::MemSetInst *asMemSetInst() const { |
||
323 | return llvm::cast<llvm::MemSetInst>(I); |
||
324 | } |
||
325 | llvm::MemTransferInst *asMemTransferInst() const { |
||
326 | return llvm::cast<llvm::MemTransferInst>(I); |
||
327 | } |
||
328 | }; |
||
329 | } // namespace polly |
||
330 | |||
331 | namespace llvm { |
||
332 | /// Specialize simplify_type for MemAccInst to enable dyn_cast and cast |
||
333 | /// from a MemAccInst object. |
||
334 | template <> struct simplify_type<polly::MemAccInst> { |
||
335 | typedef Instruction *SimpleType; |
||
336 | static SimpleType getSimplifiedValue(polly::MemAccInst &I) { |
||
337 | return I.asInstruction(); |
||
338 | } |
||
339 | }; |
||
340 | } // namespace llvm |
||
341 | |||
342 | namespace polly { |
||
343 | |||
344 | /// Simplify the region to have a single unconditional entry edge and a |
||
345 | /// single exit edge. |
||
346 | /// |
||
347 | /// Although this function allows DT and RI to be null, regions only work |
||
348 | /// properly if the DominatorTree (for Region::contains) and RegionInfo are kept |
||
349 | /// up-to-date. |
||
350 | /// |
||
351 | /// @param R The region to be simplified |
||
352 | /// @param DT DominatorTree to be updated. |
||
353 | /// @param LI LoopInfo to be updated. |
||
354 | /// @param RI RegionInfo to be updated. |
||
355 | void simplifyRegion(llvm::Region *R, llvm::DominatorTree *DT, |
||
356 | llvm::LoopInfo *LI, llvm::RegionInfo *RI); |
||
357 | |||
358 | /// Split the entry block of a function to store the newly inserted |
||
359 | /// allocations outside of all Scops. |
||
360 | /// |
||
361 | /// @param EntryBlock The entry block of the current function. |
||
362 | /// @param P The pass that currently running. |
||
363 | /// |
||
364 | void splitEntryBlockForAlloca(llvm::BasicBlock *EntryBlock, llvm::Pass *P); |
||
365 | |||
366 | /// Split the entry block of a function to store the newly inserted |
||
367 | /// allocations outside of all Scops. |
||
368 | /// |
||
369 | /// @param DT DominatorTree to be updated. |
||
370 | /// @param LI LoopInfo to be updated. |
||
371 | /// @param RI RegionInfo to be updated. |
||
372 | void splitEntryBlockForAlloca(llvm::BasicBlock *EntryBlock, |
||
373 | llvm::DominatorTree *DT, llvm::LoopInfo *LI, |
||
374 | llvm::RegionInfo *RI); |
||
375 | |||
376 | /// Wrapper for SCEVExpander extended to all Polly features. |
||
377 | /// |
||
378 | /// This wrapper will internally call the SCEVExpander but also makes sure that |
||
379 | /// all additional features not represented in SCEV (e.g., SDiv/SRem are not |
||
380 | /// black boxes but can be part of the function) will be expanded correctly. |
||
381 | /// |
||
382 | /// The parameters are the same as for the creation of a SCEVExpander as well |
||
383 | /// as the call to SCEVExpander::expandCodeFor: |
||
384 | /// |
||
385 | /// @param S The current Scop. |
||
386 | /// @param SE The Scalar Evolution pass. |
||
387 | /// @param DL The module data layout. |
||
388 | /// @param Name The suffix added to the new instruction names. |
||
389 | /// @param E The expression for which code is actually generated. |
||
390 | /// @param Ty The type of the resulting code. |
||
391 | /// @param IP The insertion point for the new code. |
||
392 | /// @param VMap A remapping of values used in @p E. |
||
393 | /// @param RTCBB The last block of the RTC. Used to insert loop-invariant |
||
394 | /// instructions in rare cases. |
||
395 | llvm::Value *expandCodeFor(Scop &S, llvm::ScalarEvolution &SE, |
||
396 | const llvm::DataLayout &DL, const char *Name, |
||
397 | const llvm::SCEV *E, llvm::Type *Ty, |
||
398 | llvm::Instruction *IP, ValueMapT *VMap, |
||
399 | llvm::BasicBlock *RTCBB); |
||
400 | |||
401 | /// Return the condition for the terminator @p TI. |
||
402 | /// |
||
403 | /// For unconditional branches the "i1 true" condition will be returned. |
||
404 | /// |
||
405 | /// @param TI The terminator to get the condition from. |
||
406 | /// |
||
407 | /// @return The condition of @p TI and nullptr if none could be extracted. |
||
408 | llvm::Value *getConditionFromTerminator(llvm::Instruction *TI); |
||
409 | |||
410 | /// Get the smallest loop that contains @p S but is not in @p S. |
||
411 | llvm::Loop *getLoopSurroundingScop(Scop &S, llvm::LoopInfo &LI); |
||
412 | |||
413 | /// Get the number of blocks in @p L. |
||
414 | /// |
||
415 | /// The number of blocks in a loop are the number of basic blocks actually |
||
416 | /// belonging to the loop, as well as all single basic blocks that the loop |
||
417 | /// exits to and which terminate in an unreachable instruction. We do not |
||
418 | /// allow such basic blocks in the exit of a scop, hence they belong to the |
||
419 | /// scop and represent run-time conditions which we want to model and |
||
420 | /// subsequently speculate away. |
||
421 | /// |
||
422 | /// @see getRegionNodeLoop for additional details. |
||
423 | unsigned getNumBlocksInLoop(llvm::Loop *L); |
||
424 | |||
425 | /// Get the number of blocks in @p RN. |
||
426 | unsigned getNumBlocksInRegionNode(llvm::RegionNode *RN); |
||
427 | |||
428 | /// Return the smallest loop surrounding @p RN. |
||
429 | llvm::Loop *getRegionNodeLoop(llvm::RegionNode *RN, llvm::LoopInfo &LI); |
||
430 | |||
431 | /// Check if @p LInst can be hoisted in @p R. |
||
432 | /// |
||
433 | /// @param LInst The load to check. |
||
434 | /// @param R The analyzed region. |
||
435 | /// @param LI The loop info. |
||
436 | /// @param SE The scalar evolution analysis. |
||
437 | /// @param DT The dominator tree of the function. |
||
438 | /// @param KnownInvariantLoads The invariant load set. |
||
439 | /// |
||
440 | /// @return True if @p LInst can be hoisted in @p R. |
||
441 | bool isHoistableLoad(llvm::LoadInst *LInst, llvm::Region &R, llvm::LoopInfo &LI, |
||
442 | llvm::ScalarEvolution &SE, const llvm::DominatorTree &DT, |
||
443 | const InvariantLoadsSetTy &KnownInvariantLoads); |
||
444 | |||
445 | /// Return true iff @p V is an intrinsic that we ignore during code |
||
446 | /// generation. |
||
447 | bool isIgnoredIntrinsic(const llvm::Value *V); |
||
448 | |||
449 | /// Check whether a value an be synthesized by the code generator. |
||
450 | /// |
||
451 | /// Some value will be recalculated only from information that is code generated |
||
452 | /// from the polyhedral representation. For such instructions we do not need to |
||
453 | /// ensure that their operands are available during code generation. |
||
454 | /// |
||
455 | /// @param V The value to check. |
||
456 | /// @param S The current SCoP. |
||
457 | /// @param SE The scalar evolution database. |
||
458 | /// @param Scope Location where the value would by synthesized. |
||
459 | /// @return If the instruction I can be regenerated from its |
||
460 | /// scalar evolution representation, return true, |
||
461 | /// otherwise return false. |
||
462 | bool canSynthesize(const llvm::Value *V, const Scop &S, |
||
463 | llvm::ScalarEvolution *SE, llvm::Loop *Scope); |
||
464 | |||
465 | /// Return the block in which a value is used. |
||
466 | /// |
||
467 | /// For normal instructions, this is the instruction's parent block. For PHI |
||
468 | /// nodes, this is the incoming block of that use, because this is where the |
||
469 | /// operand must be defined (i.e. its definition dominates this block). |
||
470 | /// Non-instructions do not use operands at a specific point such that in this |
||
471 | /// case this function returns nullptr. |
||
472 | llvm::BasicBlock *getUseBlock(const llvm::Use &U); |
||
473 | |||
474 | // If the loop is nonaffine/boxed, return the first non-boxed surrounding loop |
||
475 | // for Polly. If the loop is affine, return the loop itself. |
||
476 | // |
||
477 | // @param L Pointer to the Loop object to analyze. |
||
478 | // @param LI Reference to the LoopInfo. |
||
479 | // @param BoxedLoops Set of Boxed Loops we get from the SCoP. |
||
480 | llvm::Loop *getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI, |
||
481 | const BoxedLoopsSetTy &BoxedLoops); |
||
482 | |||
483 | // If the Basic Block belongs to a loop that is nonaffine/boxed, return the |
||
484 | // first non-boxed surrounding loop for Polly. If the loop is affine, return |
||
485 | // the loop itself. |
||
486 | // |
||
487 | // @param BB Pointer to the Basic Block to analyze. |
||
488 | // @param LI Reference to the LoopInfo. |
||
489 | // @param BoxedLoops Set of Boxed Loops we get from the SCoP. |
||
490 | llvm::Loop *getFirstNonBoxedLoopFor(llvm::BasicBlock *BB, llvm::LoopInfo &LI, |
||
491 | const BoxedLoopsSetTy &BoxedLoops); |
||
492 | |||
493 | /// Is the given instruction a call to a debug function? |
||
494 | /// |
||
495 | /// A debug function can be used to insert output in Polly-optimized code which |
||
496 | /// normally does not allow function calls with side-effects. For instance, a |
||
497 | /// printf can be inserted to check whether a value still has the expected value |
||
498 | /// after Polly generated code: |
||
499 | /// |
||
500 | /// int sum = 0; |
||
501 | /// for (int i = 0; i < 16; i+=1) { |
||
502 | /// sum += i; |
||
503 | /// printf("The value of sum at i=%d is %d\n", sum, i); |
||
504 | /// } |
||
505 | bool isDebugCall(llvm::Instruction *Inst); |
||
506 | |||
507 | /// Does the statement contain a call to a debug function? |
||
508 | /// |
||
509 | /// Such a statement must not be removed, even if has no side-effects. |
||
510 | bool hasDebugCall(ScopStmt *Stmt); |
||
511 | |||
512 | /// Find a property value in a LoopID. |
||
513 | /// |
||
514 | /// Generally, a property MDNode has the format |
||
515 | /// |
||
516 | /// !{ !"Name", value } |
||
517 | /// |
||
518 | /// In which case the value is returned. |
||
519 | /// |
||
520 | /// If the property is just |
||
521 | /// |
||
522 | /// !{ !"Name" } |
||
523 | /// |
||
524 | /// Then `nullptr` is set to mark the property is existing, but does not carry |
||
525 | /// any value. If the property does not exist, `None` is returned. |
||
526 | std::optional<llvm::Metadata *> findMetadataOperand(llvm::MDNode *LoopMD, |
||
527 | llvm::StringRef Name); |
||
528 | |||
529 | /// Find a boolean property value in a LoopID. The value not being defined is |
||
530 | /// interpreted as a false value. |
||
531 | bool getBooleanLoopAttribute(llvm::MDNode *LoopID, llvm::StringRef Name); |
||
532 | |||
533 | /// Find an integers property value in a LoopID. |
||
534 | std::optional<int> getOptionalIntLoopAttribute(llvm::MDNode *LoopID, |
||
535 | llvm::StringRef Name); |
||
536 | |||
537 | /// Does the loop's LoopID contain a 'llvm.loop.disable_heuristics' property? |
||
538 | /// |
||
539 | /// This is equivalent to llvm::hasDisableAllTransformsHint(Loop*), but |
||
540 | /// including the LoopUtils.h header indirectly also declares llvm::MemoryAccess |
||
541 | /// which clashes with polly::MemoryAccess. Declaring this alias here avoid |
||
542 | /// having to include LoopUtils.h in other files. |
||
543 | bool hasDisableAllTransformsHint(llvm::Loop *L); |
||
544 | bool hasDisableAllTransformsHint(llvm::MDNode *LoopID); |
||
545 | |||
546 | /// Represent the attributes of a loop. |
||
547 | struct BandAttr { |
||
548 | /// LoopID which stores the properties of the loop, such as transformations to |
||
549 | /// apply and the metadata of followup-loops. |
||
550 | /// |
||
551 | /// Cannot be used to identify a loop. Two different loops can have the same |
||
552 | /// metadata. |
||
553 | llvm::MDNode *Metadata = nullptr; |
||
554 | |||
555 | /// The LoopInfo reference for this loop. |
||
556 | /// |
||
557 | /// Only loops from the original IR are represented by LoopInfo. Loops that |
||
558 | /// were generated by Polly are not tracked by LoopInfo. |
||
559 | llvm::Loop *OriginalLoop = nullptr; |
||
560 | }; |
||
561 | |||
562 | /// Get an isl::id representing a loop. |
||
563 | /// |
||
564 | /// This takes the ownership of the BandAttr and will be free'd when the |
||
565 | /// returned isl::Id is free'd. |
||
566 | isl::id getIslLoopAttr(isl::ctx Ctx, BandAttr *Attr); |
||
567 | |||
568 | /// Create an isl::id that identifies an original loop. |
||
569 | /// |
||
570 | /// Return nullptr if the loop does not need a BandAttr (i.e. has no |
||
571 | /// properties); |
||
572 | /// |
||
573 | /// This creates a BandAttr which must be unique per loop and therefore this |
||
574 | /// must not be called multiple times on the same loop as their id would be |
||
575 | /// different. |
||
576 | isl::id createIslLoopAttr(isl::ctx Ctx, llvm::Loop *L); |
||
577 | |||
578 | /// Is @p Id representing a loop? |
||
579 | /// |
||
580 | /// Such ids contain a polly::BandAttr as its user pointer. |
||
581 | bool isLoopAttr(const isl::id &Id); |
||
582 | |||
583 | /// Return the BandAttr of a loop's isl::id. |
||
584 | BandAttr *getLoopAttr(const isl::id &Id); |
||
585 | |||
586 | } // namespace polly |
||
587 | #endif |