File indexing completed on 2026-05-10 08:44:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_TRANSFORMS_UTILS_SCALAREVOLUTIONEXPANDER_H
0014 #define LLVM_TRANSFORMS_UTILS_SCALAREVOLUTIONEXPANDER_H
0015
0016 #include "llvm/ADT/DenseMap.h"
0017 #include "llvm/ADT/DenseSet.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/Analysis/InstSimplifyFolder.h"
0020 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
0021 #include "llvm/Analysis/ScalarEvolutionNormalization.h"
0022 #include "llvm/Analysis/TargetTransformInfo.h"
0023 #include "llvm/IR/IRBuilder.h"
0024 #include "llvm/IR/ValueHandle.h"
0025 #include "llvm/Support/CommandLine.h"
0026 #include "llvm/Support/InstructionCost.h"
0027
0028 namespace llvm {
0029 extern cl::opt<unsigned> SCEVCheapExpansionBudget;
0030
0031
0032
0033 struct SCEVOperand {
0034 explicit SCEVOperand(unsigned Opc, int Idx, const SCEV *S) :
0035 ParentOpcode(Opc), OperandIdx(Idx), S(S) { }
0036
0037 unsigned ParentOpcode;
0038
0039 int OperandIdx;
0040
0041 const SCEV* S;
0042 };
0043
0044 struct PoisonFlags {
0045 unsigned NUW : 1;
0046 unsigned NSW : 1;
0047 unsigned Exact : 1;
0048 unsigned Disjoint : 1;
0049 unsigned NNeg : 1;
0050 unsigned SameSign : 1;
0051 GEPNoWrapFlags GEPNW;
0052
0053 PoisonFlags(const Instruction *I);
0054 void apply(Instruction *I);
0055 };
0056
0057
0058
0059
0060
0061
0062
0063 class SCEVExpander : public SCEVVisitor<SCEVExpander, Value *> {
0064 friend class SCEVExpanderCleaner;
0065
0066 ScalarEvolution &SE;
0067 const DataLayout &DL;
0068
0069
0070 const char *IVName;
0071
0072
0073 bool PreserveLCSSA;
0074
0075
0076 DenseMap<std::pair<const SCEV *, Instruction *>, TrackingVH<Value>>
0077 InsertedExpressions;
0078
0079
0080 DenseSet<AssertingVH<Value>> InsertedValues;
0081 DenseSet<AssertingVH<Value>> InsertedPostIncValues;
0082
0083
0084
0085
0086 SmallPtrSet<Value *, 16> ReusedValues;
0087
0088
0089
0090 DenseMap<PoisoningVH<Instruction>, PoisonFlags> OrigFlags;
0091
0092
0093 SmallVector<WeakVH, 2> InsertedIVs;
0094
0095
0096 DenseMap<const SCEV *, const Loop *> RelevantLoops;
0097
0098
0099
0100
0101
0102 PostIncLoopSet PostIncLoops;
0103
0104
0105
0106 const Loop *IVIncInsertLoop;
0107
0108
0109
0110 Instruction *IVIncInsertPos;
0111
0112
0113 DenseSet<AssertingVH<PHINode>> ChainedPhis;
0114
0115
0116
0117
0118
0119
0120
0121
0122 bool CanonicalMode;
0123
0124
0125
0126
0127 bool LSRMode;
0128
0129
0130
0131
0132 bool SafeUDivMode = false;
0133
0134 typedef IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> BuilderType;
0135 BuilderType Builder;
0136
0137
0138
0139
0140
0141
0142 class SCEVInsertPointGuard {
0143 IRBuilderBase &Builder;
0144 AssertingVH<BasicBlock> Block;
0145 BasicBlock::iterator Point;
0146 DebugLoc DbgLoc;
0147 SCEVExpander *SE;
0148
0149 SCEVInsertPointGuard(const SCEVInsertPointGuard &) = delete;
0150 SCEVInsertPointGuard &operator=(const SCEVInsertPointGuard &) = delete;
0151
0152 public:
0153 SCEVInsertPointGuard(IRBuilderBase &B, SCEVExpander *SE)
0154 : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()),
0155 DbgLoc(B.getCurrentDebugLocation()), SE(SE) {
0156 SE->InsertPointGuards.push_back(this);
0157 }
0158
0159 ~SCEVInsertPointGuard() {
0160
0161
0162
0163 assert(SE->InsertPointGuards.back() == this);
0164 SE->InsertPointGuards.pop_back();
0165 Builder.restoreIP(IRBuilderBase::InsertPoint(Block, Point));
0166 Builder.SetCurrentDebugLocation(DbgLoc);
0167 }
0168
0169 BasicBlock::iterator GetInsertPoint() const { return Point; }
0170 void SetInsertPoint(BasicBlock::iterator I) { Point = I; }
0171 };
0172
0173
0174
0175 SmallVector<SCEVInsertPointGuard *, 8> InsertPointGuards;
0176
0177 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0178 const char *DebugType;
0179 #endif
0180
0181 friend struct SCEVVisitor<SCEVExpander, Value *>;
0182
0183 public:
0184
0185 explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL,
0186 const char *name, bool PreserveLCSSA = true)
0187 : SE(se), DL(DL), IVName(name), PreserveLCSSA(PreserveLCSSA),
0188 IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr), CanonicalMode(true),
0189 LSRMode(false),
0190 Builder(se.getContext(), InstSimplifyFolder(DL),
0191 IRBuilderCallbackInserter(
0192 [this](Instruction *I) { rememberInstruction(I); })) {
0193 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0194 DebugType = "";
0195 #endif
0196 }
0197
0198 ~SCEVExpander() {
0199
0200 assert(InsertPointGuards.empty());
0201 }
0202
0203 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0204 void setDebugType(const char *s) { DebugType = s; }
0205 #endif
0206
0207
0208
0209
0210 void clear() {
0211 InsertedExpressions.clear();
0212 InsertedValues.clear();
0213 InsertedPostIncValues.clear();
0214 ReusedValues.clear();
0215 OrigFlags.clear();
0216 ChainedPhis.clear();
0217 InsertedIVs.clear();
0218 }
0219
0220 ScalarEvolution *getSE() { return &SE; }
0221 const SmallVectorImpl<WeakVH> &getInsertedIVs() const { return InsertedIVs; }
0222
0223
0224 SmallVector<Instruction *, 32> getAllInsertedInstructions() const {
0225 SmallVector<Instruction *, 32> Result;
0226 for (const auto &VH : InsertedValues) {
0227 Value *V = VH;
0228 if (ReusedValues.contains(V))
0229 continue;
0230 if (auto *Inst = dyn_cast<Instruction>(V))
0231 Result.push_back(Inst);
0232 }
0233 for (const auto &VH : InsertedPostIncValues) {
0234 Value *V = VH;
0235 if (ReusedValues.contains(V))
0236 continue;
0237 if (auto *Inst = dyn_cast<Instruction>(V))
0238 Result.push_back(Inst);
0239 }
0240
0241 return Result;
0242 }
0243
0244
0245
0246
0247
0248
0249
0250 bool isHighCostExpansion(ArrayRef<const SCEV *> Exprs, Loop *L,
0251 unsigned Budget, const TargetTransformInfo *TTI,
0252 const Instruction *At) {
0253 assert(TTI && "This function requires TTI to be provided.");
0254 assert(At && "This function requires At instruction to be provided.");
0255 if (!TTI)
0256 return true;
0257 SmallVector<SCEVOperand, 8> Worklist;
0258 SmallPtrSet<const SCEV *, 8> Processed;
0259 InstructionCost Cost = 0;
0260 unsigned ScaledBudget = Budget * TargetTransformInfo::TCC_Basic;
0261 for (auto *Expr : Exprs)
0262 Worklist.emplace_back(-1, -1, Expr);
0263 while (!Worklist.empty()) {
0264 const SCEVOperand WorkItem = Worklist.pop_back_val();
0265 if (isHighCostExpansionHelper(WorkItem, L, *At, Cost, ScaledBudget, *TTI,
0266 Processed, Worklist))
0267 return true;
0268 }
0269 assert(Cost <= ScaledBudget && "Should have returned from inner loop.");
0270 return false;
0271 }
0272
0273
0274 Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos,
0275 bool allowScale);
0276
0277
0278
0279
0280
0281
0282
0283 bool hoistIVInc(Instruction *IncV, Instruction *InsertPos,
0284 bool RecomputePoisonFlags = false);
0285
0286
0287
0288
0289
0290 static bool canReuseFlagsFromOriginalIVInc(PHINode *OrigPhi, PHINode *WidePhi,
0291 Instruction *OrigInc,
0292 Instruction *WideInc);
0293
0294
0295
0296 unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
0297 SmallVectorImpl<WeakTrackingVH> &DeadInsts,
0298 const TargetTransformInfo *TTI = nullptr);
0299
0300
0301
0302
0303 bool isSafeToExpand(const SCEV *S) const;
0304
0305
0306
0307
0308 bool isSafeToExpandAt(const SCEV *S, const Instruction *InsertionPoint) const;
0309
0310
0311
0312 Value *expandCodeFor(const SCEV *SH, Type *Ty, BasicBlock::iterator I);
0313 Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I) {
0314 return expandCodeFor(SH, Ty, I->getIterator());
0315 }
0316
0317
0318
0319
0320
0321 Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr);
0322
0323
0324
0325
0326 Value *expandCodeForPredicate(const SCEVPredicate *Pred, Instruction *Loc);
0327
0328
0329
0330 Value *expandComparePredicate(const SCEVComparePredicate *Pred,
0331 Instruction *Loc);
0332
0333
0334 Value *generateOverflowCheck(const SCEVAddRecExpr *AR, Instruction *Loc,
0335 bool Signed);
0336
0337
0338
0339 Value *expandWrapPredicate(const SCEVWrapPredicate *P, Instruction *Loc);
0340
0341
0342
0343 Value *expandUnionPredicate(const SCEVUnionPredicate *Pred, Instruction *Loc);
0344
0345
0346 void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
0347 assert(!CanonicalMode &&
0348 "IV increment positions are not supported in CanonicalMode");
0349 IVIncInsertLoop = L;
0350 IVIncInsertPos = Pos;
0351 }
0352
0353
0354
0355 void setPostInc(const PostIncLoopSet &L) {
0356 assert(!CanonicalMode &&
0357 "Post-inc expansion is not supported in CanonicalMode");
0358 PostIncLoops = L;
0359 }
0360
0361
0362 void clearPostInc() {
0363 PostIncLoops.clear();
0364
0365
0366
0367 InsertedPostIncValues.clear();
0368 }
0369
0370
0371
0372
0373 void disableCanonicalMode() { CanonicalMode = false; }
0374
0375 void enableLSRMode() { LSRMode = true; }
0376
0377
0378
0379
0380
0381 void setInsertPoint(Instruction *IP) {
0382 assert(IP);
0383 Builder.SetInsertPoint(IP);
0384 }
0385
0386 void setInsertPoint(BasicBlock::iterator IP) {
0387 Builder.SetInsertPoint(IP->getParent(), IP);
0388 }
0389
0390
0391
0392 void clearInsertPoint() { Builder.ClearInsertionPoint(); }
0393
0394
0395 void SetCurrentDebugLocation(DebugLoc L) {
0396 Builder.SetCurrentDebugLocation(std::move(L));
0397 }
0398
0399
0400 DebugLoc getCurrentDebugLocation() const {
0401 return Builder.getCurrentDebugLocation();
0402 }
0403
0404
0405
0406
0407 bool isInsertedInstruction(Instruction *I) const {
0408 return InsertedValues.count(I) || InsertedPostIncValues.count(I);
0409 }
0410
0411 void setChainedPhi(PHINode *PN) { ChainedPhis.insert(PN); }
0412
0413
0414
0415
0416
0417
0418
0419
0420 bool hasRelatedExistingExpansion(const SCEV *S, const Instruction *At,
0421 Loop *L);
0422
0423
0424
0425 BasicBlock::iterator findInsertPointAfter(Instruction *I,
0426 Instruction *MustDominate) const;
0427
0428 private:
0429 LLVMContext &getContext() const { return SE.getContext(); }
0430
0431
0432 bool isHighCostExpansionHelper(const SCEVOperand &WorkItem, Loop *L,
0433 const Instruction &At, InstructionCost &Cost,
0434 unsigned Budget,
0435 const TargetTransformInfo &TTI,
0436 SmallPtrSetImpl<const SCEV *> &Processed,
0437 SmallVectorImpl<SCEVOperand> &Worklist);
0438
0439
0440
0441
0442 Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS,
0443 SCEV::NoWrapFlags Flags, bool IsSafeToHoist);
0444
0445
0446 BasicBlock::iterator GetOptimalInsertionPointForCastOf(Value *V) const;
0447
0448
0449
0450
0451 Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op,
0452 BasicBlock::iterator IP);
0453
0454
0455
0456 Value *InsertNoopCastOfTo(Value *V, Type *Ty);
0457
0458
0459
0460 Value *expandAddToGEP(const SCEV *Op, Value *V, SCEV::NoWrapFlags Flags);
0461
0462
0463
0464
0465 Value *FindValueInExprValueMap(
0466 const SCEV *S, const Instruction *InsertPt,
0467 SmallVectorImpl<Instruction *> &DropPoisonGeneratingInsts);
0468
0469 Value *expand(const SCEV *S);
0470 Value *expand(const SCEV *S, BasicBlock::iterator I) {
0471 setInsertPoint(I);
0472 return expand(S);
0473 }
0474 Value *expand(const SCEV *S, Instruction *I) {
0475 setInsertPoint(I);
0476 return expand(S);
0477 }
0478
0479
0480 const Loop *getRelevantLoop(const SCEV *);
0481
0482 Value *expandMinMaxExpr(const SCEVNAryExpr *S, Intrinsic::ID IntrinID,
0483 Twine Name, bool IsSequential = false);
0484
0485 Value *visitConstant(const SCEVConstant *S) { return S->getValue(); }
0486
0487 Value *visitVScale(const SCEVVScale *S);
0488
0489 Value *visitPtrToIntExpr(const SCEVPtrToIntExpr *S);
0490
0491 Value *visitTruncateExpr(const SCEVTruncateExpr *S);
0492
0493 Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S);
0494
0495 Value *visitSignExtendExpr(const SCEVSignExtendExpr *S);
0496
0497 Value *visitAddExpr(const SCEVAddExpr *S);
0498
0499 Value *visitMulExpr(const SCEVMulExpr *S);
0500
0501 Value *visitUDivExpr(const SCEVUDivExpr *S);
0502
0503 Value *visitAddRecExpr(const SCEVAddRecExpr *S);
0504
0505 Value *visitSMaxExpr(const SCEVSMaxExpr *S);
0506
0507 Value *visitUMaxExpr(const SCEVUMaxExpr *S);
0508
0509 Value *visitSMinExpr(const SCEVSMinExpr *S);
0510
0511 Value *visitUMinExpr(const SCEVUMinExpr *S);
0512
0513 Value *visitSequentialUMinExpr(const SCEVSequentialUMinExpr *S);
0514
0515 Value *visitUnknown(const SCEVUnknown *S) { return S->getValue(); }
0516
0517 void rememberInstruction(Value *I);
0518
0519 void rememberFlags(Instruction *I);
0520
0521 bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
0522
0523 bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
0524
0525 Value *expandAddRecExprLiterally(const SCEVAddRecExpr *);
0526 PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
0527 const Loop *L, Type *&TruncTy,
0528 bool &InvertStep);
0529 Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
0530 bool useSubtract);
0531
0532 void fixupInsertPoints(Instruction *I);
0533
0534
0535
0536 Value *fixupLCSSAFormFor(Value *V);
0537
0538
0539
0540
0541 void replaceCongruentIVInc(PHINode *&Phi, PHINode *&OrigPhi, Loop *L,
0542 const DominatorTree *DT,
0543 SmallVectorImpl<WeakTrackingVH> &DeadInsts);
0544 };
0545
0546
0547
0548 class SCEVExpanderCleaner {
0549 SCEVExpander &Expander;
0550
0551
0552
0553 bool ResultUsed;
0554
0555 public:
0556 SCEVExpanderCleaner(SCEVExpander &Expander)
0557 : Expander(Expander), ResultUsed(false) {}
0558
0559 ~SCEVExpanderCleaner() { cleanup(); }
0560
0561
0562 void markResultUsed() { ResultUsed = true; }
0563
0564 void cleanup();
0565 };
0566 }
0567
0568 #endif