Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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