File indexing completed on 2026-05-10 08:48:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef POLLY_SUPPORT_IRHELPER_H
0014 #define POLLY_SUPPORT_IRHELPER_H
0015
0016 #include "llvm/ADT/SetVector.h"
0017 #include "llvm/IR/Instructions.h"
0018 #include "llvm/IR/IntrinsicInst.h"
0019 #include "llvm/IR/ValueHandle.h"
0020 #include "isl/isl-noexceptions.h"
0021 #include <optional>
0022
0023 namespace llvm {
0024 class LoopInfo;
0025 class Loop;
0026 class ScalarEvolution;
0027 class SCEV;
0028 class Region;
0029 class Pass;
0030 class DominatorTree;
0031 class RegionInfo;
0032 class RegionNode;
0033 }
0034
0035 namespace polly {
0036 class Scop;
0037 class ScopStmt;
0038
0039
0040 using LoopToScevMapT = llvm::DenseMap<const llvm::Loop *, const llvm::SCEV *>;
0041
0042
0043 enum AssumptionKind {
0044 ALIASING,
0045 INBOUNDS,
0046 WRAPPING,
0047 UNSIGNED,
0048 PROFITABLE,
0049 ERRORBLOCK,
0050 COMPLEXITY,
0051 INFINITELOOP,
0052 INVARIANTLOAD,
0053 DELINEARIZATION,
0054 };
0055
0056
0057 enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION };
0058
0059
0060 struct Assumption {
0061
0062 AssumptionKind Kind;
0063
0064
0065 AssumptionSign Sign;
0066
0067
0068 isl::set Set;
0069
0070
0071 llvm::DebugLoc Loc;
0072
0073
0074 llvm::BasicBlock *BB;
0075
0076
0077 bool RequiresRTC;
0078 };
0079
0080 using RecordedAssumptionsTy = llvm::SmallVector<Assumption, 8>;
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions,
0100 AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc,
0101 AssumptionSign Sign, llvm::BasicBlock *BB = nullptr,
0102 bool RTC = true);
0103
0104
0105 using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>,
0106 llvm::AssertingVH<llvm::Value>>;
0107
0108
0109 using InvariantLoadsSetTy = llvm::SetVector<llvm::AssertingVH<llvm::LoadInst>>;
0110
0111
0112 using ParameterSetTy = llvm::SetVector<const llvm::SCEV *>;
0113
0114
0115 using BoxedLoopsSetTy = llvm::SetVector<const llvm::Loop *>;
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 class MemAccInst final {
0141 private:
0142 llvm::Instruction *I;
0143
0144 public:
0145 MemAccInst() : I(nullptr) {}
0146 MemAccInst(const MemAccInst &Inst) : I(Inst.I) {}
0147 MemAccInst(llvm::LoadInst &LI) : I(&LI) {}
0148 MemAccInst(llvm::LoadInst *LI) : I(LI) {}
0149 MemAccInst(llvm::StoreInst &SI) : I(&SI) {}
0150 MemAccInst(llvm::StoreInst *SI) : I(SI) {}
0151 MemAccInst(llvm::MemIntrinsic *MI) : I(MI) {}
0152 MemAccInst(llvm::CallInst *CI) : I(CI) {}
0153 explicit MemAccInst(llvm::Instruction &I) : I(&I) { assert(isa(I)); }
0154 explicit MemAccInst(llvm::Instruction *I) : I(I) { assert(isa(I)); }
0155
0156 static bool isa(const llvm::Value &V) {
0157 return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) ||
0158 llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V);
0159 }
0160 static bool isa(const llvm::Value *V) {
0161 return llvm::isa<llvm::LoadInst>(V) || llvm::isa<llvm::StoreInst>(V) ||
0162 llvm::isa<llvm::CallInst>(V) || llvm::isa<llvm::MemIntrinsic>(V);
0163 }
0164 static MemAccInst cast(llvm::Value &V) {
0165 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0166 }
0167 static MemAccInst cast(llvm::Value *V) {
0168 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0169 }
0170 static MemAccInst cast_or_null(llvm::Value &V) {
0171 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0172 }
0173 static MemAccInst cast_or_null(llvm::Value *V) {
0174 if (!V)
0175 return MemAccInst();
0176 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0177 }
0178 static MemAccInst dyn_cast(llvm::Value &V) {
0179 if (isa(V))
0180 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0181 return MemAccInst();
0182 }
0183 static MemAccInst dyn_cast(llvm::Value *V) {
0184 assert(V);
0185 if (isa(V))
0186 return MemAccInst(llvm::cast<llvm::Instruction>(V));
0187 return MemAccInst();
0188 }
0189
0190 MemAccInst &operator=(const MemAccInst &Inst) {
0191 I = Inst.I;
0192 return *this;
0193 }
0194 MemAccInst &operator=(llvm::LoadInst &LI) {
0195 I = &LI;
0196 return *this;
0197 }
0198 MemAccInst &operator=(llvm::LoadInst *LI) {
0199 I = LI;
0200 return *this;
0201 }
0202 MemAccInst &operator=(llvm::StoreInst &SI) {
0203 I = &SI;
0204 return *this;
0205 }
0206 MemAccInst &operator=(llvm::StoreInst *SI) {
0207 I = SI;
0208 return *this;
0209 }
0210 MemAccInst &operator=(llvm::MemIntrinsic &MI) {
0211 I = &MI;
0212 return *this;
0213 }
0214 MemAccInst &operator=(llvm::MemIntrinsic *MI) {
0215 I = MI;
0216 return *this;
0217 }
0218 MemAccInst &operator=(llvm::CallInst &CI) {
0219 I = &CI;
0220 return *this;
0221 }
0222 MemAccInst &operator=(llvm::CallInst *CI) {
0223 I = CI;
0224 return *this;
0225 }
0226
0227 llvm::Instruction *get() const {
0228 assert(I && "Unexpected nullptr!");
0229 return I;
0230 }
0231 operator llvm::Instruction *() const { return asInstruction(); }
0232 llvm::Instruction *operator->() const { return get(); }
0233
0234 explicit operator bool() const { return isInstruction(); }
0235 bool operator!() const { return isNull(); }
0236
0237 llvm::Value *getValueOperand() const {
0238 if (isLoad())
0239 return asLoad();
0240 if (isStore())
0241 return asStore()->getValueOperand();
0242 if (isMemIntrinsic())
0243 return nullptr;
0244 if (isCallInst())
0245 return nullptr;
0246 llvm_unreachable("Operation not supported on nullptr");
0247 }
0248 llvm::Value *getPointerOperand() const {
0249 if (isLoad())
0250 return asLoad()->getPointerOperand();
0251 if (isStore())
0252 return asStore()->getPointerOperand();
0253 if (isMemIntrinsic())
0254 return asMemIntrinsic()->getRawDest();
0255 if (isCallInst())
0256 return nullptr;
0257 llvm_unreachable("Operation not supported on nullptr");
0258 }
0259 bool isVolatile() const {
0260 if (isLoad())
0261 return asLoad()->isVolatile();
0262 if (isStore())
0263 return asStore()->isVolatile();
0264 if (isMemIntrinsic())
0265 return asMemIntrinsic()->isVolatile();
0266 if (isCallInst())
0267 return false;
0268 llvm_unreachable("Operation not supported on nullptr");
0269 }
0270 bool isSimple() const {
0271 if (isLoad())
0272 return asLoad()->isSimple();
0273 if (isStore())
0274 return asStore()->isSimple();
0275 if (isMemIntrinsic())
0276 return !asMemIntrinsic()->isVolatile();
0277 if (isCallInst())
0278 return true;
0279 llvm_unreachable("Operation not supported on nullptr");
0280 }
0281 llvm::AtomicOrdering getOrdering() const {
0282 if (isLoad())
0283 return asLoad()->getOrdering();
0284 if (isStore())
0285 return asStore()->getOrdering();
0286 if (isMemIntrinsic())
0287 return llvm::AtomicOrdering::NotAtomic;
0288 if (isCallInst())
0289 return llvm::AtomicOrdering::NotAtomic;
0290 llvm_unreachable("Operation not supported on nullptr");
0291 }
0292 bool isUnordered() const {
0293 if (isLoad())
0294 return asLoad()->isUnordered();
0295 if (isStore())
0296 return asStore()->isUnordered();
0297
0298 if (isMemIntrinsic())
0299 return !asMemIntrinsic()->isVolatile();
0300 if (isCallInst())
0301 return true;
0302 llvm_unreachable("Operation not supported on nullptr");
0303 }
0304
0305 bool isNull() const { return !I; }
0306 bool isInstruction() const { return I; }
0307
0308 llvm::Instruction *asInstruction() const { return I; }
0309
0310 bool isLoad() const { return I && llvm::isa<llvm::LoadInst>(I); }
0311 bool isStore() const { return I && llvm::isa<llvm::StoreInst>(I); }
0312 bool isCallInst() const { return I && llvm::isa<llvm::CallInst>(I); }
0313 bool isMemIntrinsic() const { return I && llvm::isa<llvm::MemIntrinsic>(I); }
0314 bool isMemSetInst() const { return I && llvm::isa<llvm::MemSetInst>(I); }
0315 bool isMemTransferInst() const {
0316 return I && llvm::isa<llvm::MemTransferInst>(I);
0317 }
0318
0319 llvm::LoadInst *asLoad() const { return llvm::cast<llvm::LoadInst>(I); }
0320 llvm::StoreInst *asStore() const { return llvm::cast<llvm::StoreInst>(I); }
0321 llvm::CallInst *asCallInst() const { return llvm::cast<llvm::CallInst>(I); }
0322 llvm::MemIntrinsic *asMemIntrinsic() const {
0323 return llvm::cast<llvm::MemIntrinsic>(I);
0324 }
0325 llvm::MemSetInst *asMemSetInst() const {
0326 return llvm::cast<llvm::MemSetInst>(I);
0327 }
0328 llvm::MemTransferInst *asMemTransferInst() const {
0329 return llvm::cast<llvm::MemTransferInst>(I);
0330 }
0331 };
0332 }
0333
0334 namespace llvm {
0335
0336
0337 template <> struct simplify_type<polly::MemAccInst> {
0338 typedef Instruction *SimpleType;
0339 static SimpleType getSimplifiedValue(polly::MemAccInst &I) {
0340 return I.asInstruction();
0341 }
0342 };
0343 }
0344
0345 namespace polly {
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 void simplifyRegion(llvm::Region *R, llvm::DominatorTree *DT,
0359 llvm::LoopInfo *LI, llvm::RegionInfo *RI);
0360
0361
0362
0363
0364
0365
0366
0367 void splitEntryBlockForAlloca(llvm::BasicBlock *EntryBlock, llvm::Pass *P);
0368
0369
0370
0371
0372
0373
0374
0375 void splitEntryBlockForAlloca(llvm::BasicBlock *EntryBlock,
0376 llvm::DominatorTree *DT, llvm::LoopInfo *LI,
0377 llvm::RegionInfo *RI);
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 llvm::Value *expandCodeFor(Scop &S, llvm::ScalarEvolution &SE,
0402 llvm::Function *GenFn, llvm::ScalarEvolution &GenSE,
0403 const llvm::DataLayout &DL, const char *Name,
0404 const llvm::SCEV *E, llvm::Type *Ty,
0405 llvm::Instruction *IP, ValueMapT *VMap,
0406 LoopToScevMapT *LoopMap, llvm::BasicBlock *RTCBB);
0407
0408
0409
0410
0411
0412
0413
0414
0415 llvm::Value *getConditionFromTerminator(llvm::Instruction *TI);
0416
0417
0418 llvm::Loop *getLoopSurroundingScop(Scop &S, llvm::LoopInfo &LI);
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 unsigned getNumBlocksInLoop(llvm::Loop *L);
0431
0432
0433 unsigned getNumBlocksInRegionNode(llvm::RegionNode *RN);
0434
0435
0436 llvm::Loop *getRegionNodeLoop(llvm::RegionNode *RN, llvm::LoopInfo &LI);
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 bool isHoistableLoad(llvm::LoadInst *LInst, llvm::Region &R, llvm::LoopInfo &LI,
0449 llvm::ScalarEvolution &SE, const llvm::DominatorTree &DT,
0450 const InvariantLoadsSetTy &KnownInvariantLoads);
0451
0452
0453
0454 bool isIgnoredIntrinsic(const llvm::Value *V);
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 bool canSynthesize(const llvm::Value *V, const Scop &S,
0470 llvm::ScalarEvolution *SE, llvm::Loop *Scope);
0471
0472
0473
0474
0475
0476
0477
0478
0479 llvm::BasicBlock *getUseBlock(const llvm::Use &U);
0480
0481
0482
0483
0484
0485
0486
0487 llvm::Loop *getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI,
0488 const BoxedLoopsSetTy &BoxedLoops);
0489
0490
0491
0492
0493
0494
0495
0496
0497 llvm::Loop *getFirstNonBoxedLoopFor(llvm::BasicBlock *BB, llvm::LoopInfo &LI,
0498 const BoxedLoopsSetTy &BoxedLoops);
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512 bool isDebugCall(llvm::Instruction *Inst);
0513
0514
0515
0516
0517 bool hasDebugCall(ScopStmt *Stmt);
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 std::optional<llvm::Metadata *> findMetadataOperand(llvm::MDNode *LoopMD,
0534 llvm::StringRef Name);
0535
0536
0537
0538 bool getBooleanLoopAttribute(llvm::MDNode *LoopID, llvm::StringRef Name);
0539
0540
0541 std::optional<int> getOptionalIntLoopAttribute(llvm::MDNode *LoopID,
0542 llvm::StringRef Name);
0543
0544
0545
0546
0547
0548
0549
0550 bool hasDisableAllTransformsHint(llvm::Loop *L);
0551 bool hasDisableAllTransformsHint(llvm::MDNode *LoopID);
0552
0553
0554 struct BandAttr {
0555
0556
0557
0558
0559
0560 llvm::MDNode *Metadata = nullptr;
0561
0562
0563
0564
0565
0566 llvm::Loop *OriginalLoop = nullptr;
0567 };
0568
0569
0570
0571
0572
0573 isl::id getIslLoopAttr(isl::ctx Ctx, BandAttr *Attr);
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583 isl::id createIslLoopAttr(isl::ctx Ctx, llvm::Loop *L);
0584
0585
0586
0587
0588 bool isLoopAttr(const isl::id &Id);
0589
0590
0591 BandAttr *getLoopAttr(const isl::id &Id);
0592
0593 }
0594 #endif