• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MemAccInst()142   MemAccInst() : I(nullptr) {}
MemAccInst(const MemAccInst & Inst)143   MemAccInst(const MemAccInst &Inst) : I(Inst.I) {}
MemAccInst(llvm::LoadInst & LI)144   /* implicit */ MemAccInst(llvm::LoadInst &LI) : I(&LI) {}
MemAccInst(llvm::LoadInst * LI)145   /* implicit */ MemAccInst(llvm::LoadInst *LI) : I(LI) {}
MemAccInst(llvm::StoreInst & SI)146   /* implicit */ MemAccInst(llvm::StoreInst &SI) : I(&SI) {}
MemAccInst(llvm::StoreInst * SI)147   /* implicit */ MemAccInst(llvm::StoreInst *SI) : I(SI) {}
MemAccInst(llvm::MemIntrinsic * MI)148   /* implicit */ MemAccInst(llvm::MemIntrinsic *MI) : I(MI) {}
MemAccInst(llvm::CallInst * CI)149   /* implicit */ MemAccInst(llvm::CallInst *CI) : I(CI) {}
MemAccInst(llvm::Instruction & I)150   explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); }
MemAccInst(llvm::Instruction * I)151   explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); }
152 
isa(const llvm::Value & V)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   }
isa(const llvm::Value * V)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   }
cast(llvm::Value & V)161   static MemAccInst cast(llvm::Value &V) {
162     return MemAccInst(llvm::cast<llvm::Instruction>(V));
163   }
cast(llvm::Value * V)164   static MemAccInst cast(llvm::Value *V) {
165     return MemAccInst(llvm::cast<llvm::Instruction>(V));
166   }
cast_or_null(llvm::Value & V)167   static MemAccInst cast_or_null(llvm::Value &V) {
168     return MemAccInst(llvm::cast<llvm::Instruction>(V));
169   }
cast_or_null(llvm::Value * V)170   static MemAccInst cast_or_null(llvm::Value *V) {
171     if (!V)
172       return MemAccInst();
173     return MemAccInst(llvm::cast<llvm::Instruction>(V));
174   }
dyn_cast(llvm::Value & V)175   static MemAccInst dyn_cast(llvm::Value &V) {
176     if (isa(V))
177       return MemAccInst(llvm::cast<llvm::Instruction>(V));
178     return MemAccInst();
179   }
dyn_cast(llvm::Value * V)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 
get()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 
getValueOperand()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   }
getPointerOperand()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   }
isVolatile()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   }
isSimple()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   }
getOrdering()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   }
isUnordered()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 
isNull()302   bool isNull() const { return !I; }
isInstruction()303   bool isInstruction() const { return I; }
304 
asInstruction()305   llvm::Instruction *asInstruction() const { return I; }
306 
isLoad()307   bool isLoad() const { return I && llvm::isa<llvm::LoadInst>(I); }
isStore()308   bool isStore() const { return I && llvm::isa<llvm::StoreInst>(I); }
isCallInst()309   bool isCallInst() const { return I && llvm::isa<llvm::CallInst>(I); }
isMemIntrinsic()310   bool isMemIntrinsic() const { return I && llvm::isa<llvm::MemIntrinsic>(I); }
isMemSetInst()311   bool isMemSetInst() const { return I && llvm::isa<llvm::MemSetInst>(I); }
isMemTransferInst()312   bool isMemTransferInst() const {
313     return I && llvm::isa<llvm::MemTransferInst>(I);
314   }
315 
asLoad()316   llvm::LoadInst *asLoad() const { return llvm::cast<llvm::LoadInst>(I); }
asStore()317   llvm::StoreInst *asStore() const { return llvm::cast<llvm::StoreInst>(I); }
asCallInst()318   llvm::CallInst *asCallInst() const { return llvm::cast<llvm::CallInst>(I); }
asMemIntrinsic()319   llvm::MemIntrinsic *asMemIntrinsic() const {
320     return llvm::cast<llvm::MemIntrinsic>(I);
321   }
asMemSetInst()322   llvm::MemSetInst *asMemSetInst() const {
323     return llvm::cast<llvm::MemSetInst>(I);
324   }
asMemTransferInst()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, `std::nullopt` 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
588