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 22 namespace llvm { 23 class LoopInfo; 24 class Loop; 25 class ScalarEvolution; 26 class SCEV; 27 class Region; 28 class Pass; 29 class DominatorTree; 30 class RegionInfo; 31 class RegionNode; 32 } // namespace llvm 33 34 namespace polly { 35 class Scop; 36 class ScopStmt; 37 38 /// Enumeration of assumptions Polly can take. 39 enum AssumptionKind { 40 ALIASING, 41 INBOUNDS, 42 WRAPPING, 43 UNSIGNED, 44 PROFITABLE, 45 ERRORBLOCK, 46 COMPLEXITY, 47 INFINITELOOP, 48 INVARIANTLOAD, 49 DELINEARIZATION, 50 }; 51 52 /// Enum to distinguish between assumptions and restrictions. 53 enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION }; 54 55 /// Helper struct to remember assumptions. 56 struct Assumption { 57 /// The kind of the assumption (e.g., WRAPPING). 58 AssumptionKind Kind; 59 60 /// Flag to distinguish assumptions and restrictions. 61 AssumptionSign Sign; 62 63 /// The valid/invalid context if this is an assumption/restriction. 64 isl::set Set; 65 66 /// The location that caused this assumption. 67 llvm::DebugLoc Loc; 68 69 /// An optional block whose domain can simplify the assumption. 70 llvm::BasicBlock *BB; 71 72 // Whether the assumption must be checked at runtime. 73 bool RequiresRTC; 74 }; 75 76 using RecordedAssumptionsTy = llvm::SmallVector<Assumption, 8>; 77 78 /// Record an assumption for later addition to the assumed context. 79 /// 80 /// This function will add the assumption to the RecordedAssumptions. This 81 /// collection will be added (@see addAssumption) to the assumed context once 82 /// all paramaters are known and the context is fully built. 83 /// 84 /// @param RecordedAssumption container which keeps all recorded assumptions. 85 /// @param Kind The assumption kind describing the underlying cause. 86 /// @param Set The relations between parameters that are assumed to hold. 87 /// @param Loc The location in the source that caused this assumption. 88 /// @param Sign Enum to indicate if the assumptions in @p Set are positive 89 /// (needed/assumptions) or negative (invalid/restrictions). 90 /// @param BB The block in which this assumption was taken. If it is 91 /// set, the domain of that block will be used to simplify the 92 /// actual assumption in @p Set once it is added. This is useful 93 /// if the assumption was created prior to the domain. 94 /// @param RTC Does the assumption require a runtime check? 95 void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions, 96 AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc, 97 AssumptionSign Sign, llvm::BasicBlock *BB = nullptr, 98 bool RTC = true); 99 100 /// Type to remap values. 101 using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>, 102 llvm::AssertingVH<llvm::Value>>; 103 104 /// Type for a set of invariant loads. 105 using InvariantLoadsSetTy = llvm::SetVector<llvm::AssertingVH<llvm::LoadInst>>; 106 107 /// Set type for parameters. 108 using ParameterSetTy = llvm::SetVector<const llvm::SCEV *>; 109 110 /// Set of loops (used to remember loops in non-affine subregions). 111 using BoxedLoopsSetTy = llvm::SetVector<const llvm::Loop *>; 112 113 /// Utility proxy to wrap the common members of LoadInst and StoreInst. 114 /// 115 /// This works like the LLVM utility class CallSite, ie. it forwards all calls 116 /// to either a LoadInst, StoreInst, MemIntrinsic or MemTransferInst. 117 /// It is similar to LLVM's utility classes IntrinsicInst, MemIntrinsic, 118 /// MemTransferInst, etc. in that it offers a common interface, but does not act 119 /// as a fake base class. 120 /// It is similar to StringRef and ArrayRef in that it holds a pointer to the 121 /// referenced object and should be passed by-value as it is small enough. 122 /// 123 /// This proxy can either represent a LoadInst instance, a StoreInst instance, 124 /// a MemIntrinsic instance (memset, memmove, memcpy), a CallInst instance or a 125 /// nullptr (only creatable using the default constructor); never an Instruction 126 /// that is neither of the above mentioned. When representing a nullptr, only 127 /// the following methods are defined: 128 /// isNull(), isInstruction(), isLoad(), isStore(), ..., isMemTransferInst(), 129 /// operator bool(), operator!() 130 /// 131 /// The functions isa, cast, cast_or_null, dyn_cast are modeled te resemble 132 /// those from llvm/Support/Casting.h. Partial template function specialization 133 /// is currently not supported in C++ such that those cannot be used directly. 134 /// (llvm::isa could, but then llvm:cast etc. would not have the expected 135 /// behavior) 136 class MemAccInst final { 137 private: 138 llvm::Instruction *I; 139 140 public: MemAccInst()141 MemAccInst() : I(nullptr) {} MemAccInst(const MemAccInst & Inst)142 MemAccInst(const MemAccInst &Inst) : I(Inst.I) {} MemAccInst(llvm::LoadInst & LI)143 /* implicit */ MemAccInst(llvm::LoadInst &LI) : I(&LI) {} MemAccInst(llvm::LoadInst * LI)144 /* implicit */ MemAccInst(llvm::LoadInst *LI) : I(LI) {} MemAccInst(llvm::StoreInst & SI)145 /* implicit */ MemAccInst(llvm::StoreInst &SI) : I(&SI) {} MemAccInst(llvm::StoreInst * SI)146 /* implicit */ MemAccInst(llvm::StoreInst *SI) : I(SI) {} MemAccInst(llvm::MemIntrinsic * MI)147 /* implicit */ MemAccInst(llvm::MemIntrinsic *MI) : I(MI) {} MemAccInst(llvm::CallInst * CI)148 /* implicit */ MemAccInst(llvm::CallInst *CI) : I(CI) {} MemAccInst(llvm::Instruction & I)149 explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); } MemAccInst(llvm::Instruction * I)150 explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); } 151 isa(const llvm::Value & V)152 static bool isa(const llvm::Value &V) { 153 return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) || 154 llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V); 155 } isa(const llvm::Value * V)156 static bool isa(const llvm::Value *V) { 157 return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) || 158 llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V); 159 } cast(llvm::Value & V)160 static MemAccInst cast(llvm::Value &V) { 161 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 162 } cast(llvm::Value * V)163 static MemAccInst cast(llvm::Value *V) { 164 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 165 } cast_or_null(llvm::Value & V)166 static MemAccInst cast_or_null(llvm::Value &V) { 167 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 168 } cast_or_null(llvm::Value * V)169 static MemAccInst cast_or_null(llvm::Value *V) { 170 if (!V) 171 return MemAccInst(); 172 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 173 } dyn_cast(llvm::Value & V)174 static MemAccInst dyn_cast(llvm::Value &V) { 175 if (isa(V)) 176 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 177 return MemAccInst(); 178 } dyn_cast(llvm::Value * V)179 static MemAccInst dyn_cast(llvm::Value *V) { 180 assert(V); 181 if (isa(V)) 182 return MemAccInst(llvm::cast<llvm::Instruction>(V)); 183 return MemAccInst(); 184 } 185 186 MemAccInst &operator=(const MemAccInst &Inst) { 187 I = Inst.I; 188 return *this; 189 } 190 MemAccInst &operator=(llvm::LoadInst &LI) { 191 I = &LI; 192 return *this; 193 } 194 MemAccInst &operator=(llvm::LoadInst *LI) { 195 I = LI; 196 return *this; 197 } 198 MemAccInst &operator=(llvm::StoreInst &SI) { 199 I = &SI; 200 return *this; 201 } 202 MemAccInst &operator=(llvm::StoreInst *SI) { 203 I = SI; 204 return *this; 205 } 206 MemAccInst &operator=(llvm::MemIntrinsic &MI) { 207 I = &MI; 208 return *this; 209 } 210 MemAccInst &operator=(llvm::MemIntrinsic *MI) { 211 I = MI; 212 return *this; 213 } 214 MemAccInst &operator=(llvm::CallInst &CI) { 215 I = &CI; 216 return *this; 217 } 218 MemAccInst &operator=(llvm::CallInst *CI) { 219 I = CI; 220 return *this; 221 } 222 get()223 llvm::Instruction *get() const { 224 assert(I && "Unexpected nullptr!"); 225 return I; 226 } 227 operator llvm::Instruction *() const { return asInstruction(); } 228 llvm::Instruction *operator->() const { return get(); } 229 230 explicit operator bool() const { return isInstruction(); } 231 bool operator!() const { return isNull(); } 232 getValueOperand()233 llvm::Value *getValueOperand() const { 234 if (isLoad()) 235 return asLoad(); 236 if (isStore()) 237 return asStore()->getValueOperand(); 238 if (isMemIntrinsic()) 239 return nullptr; 240 if (isCallInst()) 241 return nullptr; 242 llvm_unreachable("Operation not supported on nullptr"); 243 } getPointerOperand()244 llvm::Value *getPointerOperand() const { 245 if (isLoad()) 246 return asLoad()->getPointerOperand(); 247 if (isStore()) 248 return asStore()->getPointerOperand(); 249 if (isMemIntrinsic()) 250 return asMemIntrinsic()->getRawDest(); 251 if (isCallInst()) 252 return nullptr; 253 llvm_unreachable("Operation not supported on nullptr"); 254 } isVolatile()255 bool isVolatile() const { 256 if (isLoad()) 257 return asLoad()->isVolatile(); 258 if (isStore()) 259 return asStore()->isVolatile(); 260 if (isMemIntrinsic()) 261 return asMemIntrinsic()->isVolatile(); 262 if (isCallInst()) 263 return false; 264 llvm_unreachable("Operation not supported on nullptr"); 265 } isSimple()266 bool isSimple() const { 267 if (isLoad()) 268 return asLoad()->isSimple(); 269 if (isStore()) 270 return asStore()->isSimple(); 271 if (isMemIntrinsic()) 272 return !asMemIntrinsic()->isVolatile(); 273 if (isCallInst()) 274 return true; 275 llvm_unreachable("Operation not supported on nullptr"); 276 } getOrdering()277 llvm::AtomicOrdering getOrdering() const { 278 if (isLoad()) 279 return asLoad()->getOrdering(); 280 if (isStore()) 281 return asStore()->getOrdering(); 282 if (isMemIntrinsic()) 283 return llvm::AtomicOrdering::NotAtomic; 284 if (isCallInst()) 285 return llvm::AtomicOrdering::NotAtomic; 286 llvm_unreachable("Operation not supported on nullptr"); 287 } isUnordered()288 bool isUnordered() const { 289 if (isLoad()) 290 return asLoad()->isUnordered(); 291 if (isStore()) 292 return asStore()->isUnordered(); 293 // Copied from the Load/Store implementation of isUnordered: 294 if (isMemIntrinsic()) 295 return !asMemIntrinsic()->isVolatile(); 296 if (isCallInst()) 297 return true; 298 llvm_unreachable("Operation not supported on nullptr"); 299 } 300 isNull()301 bool isNull() const { return !I; } isInstruction()302 bool isInstruction() const { return I; } 303 asInstruction()304 llvm::Instruction *asInstruction() const { return I; } 305 306 private: 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, `None` is returned. 526 llvm::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 llvm::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