[llvm] [IVDescriptors] Implement MonotonicDescriptor (PR #214490)
Andrei Elovikov via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 17 10:55:21 PDT 2026
================
@@ -1696,3 +1696,222 @@ bool InductionDescriptor::isInductionPHI(
/*InductionBinOp=*/nullptr, /*Casts=*/nullptr, Preds);
return true;
}
+
+static bool hasUniqueLoopVariantOperand(Value *Cur, Instruction *I,
+ const Loop *L) {
+ auto LoopVariantOp = [&](Value *V, bool /*AllowRepeats*/) -> Value * {
+ return L->isLoopInvariant(V) ? nullptr : V;
+ };
+ return find_singleton<Value>(I->operands(), LoopVariantOp) == Cur;
+}
+
+// Recognize monotonic phi variable by matching the following pattern:
+// loop_header:
+// %monotonic_phi = phi [ %start, %preheader ], [ %chain_phi0, %latch ]
+// br i1 %do_step, label %step_bb, label %bbN
+//
+// step_bb:
+// %step = add/gep %monotonic_phi, %step_val
+// br label %bbN
+//
+// bbN:
+// %chain_phiN = phi [ %monotonic_phi, %loop_header ], [ %step, %step_bb ]
+// br label %bb(N-1)
+//
+// ...
+//
+// bb2:
+// %chain_phi2 = phi [ %monotonic_phi, %pred2 ], [ %chain_phi3, %bb3 ]
+// br label %bb1
+//
+// bb1:
+// %chain_phi1 = phi [ %monotonic_phi, %pred1 ], [ %chain_phi2, %bb2 ]
+// br label %latch
+//
+// latch:
+// %chain_phi0 = phi [ %monotonic_phi, %pred0 ], [ %chain_phi1, %bb1 ]
+// br label %loop_header
+//
+// For this pattern, monotonic phi is described by {%start, +, %step}
+// recurrence and predicate is CFG edge %step_bb -> %bbN.
+std::pair<Instruction *, const SCEV *>
+MonotonicDescriptor::CollectMonotonicPHIChain(PHINode *PN, const Loop *L,
+ PHINode *BackEdgeInst,
+ SmallPtrSetImpl<PHINode *> &Chain,
+ Edge &PredEdge,
+ ScalarEvolution &SE) {
+ Value *StepOp = nullptr;
+ PHINode *PHIChain = BackEdgeInst;
+
+ while (PHIChain) {
+ Chain.insert(PHIChain);
+ PHINode *NextPHIChain = nullptr;
+ for (auto [Block, Incoming] :
+ zip_equal(PHIChain->blocks(), PHIChain->incoming_values())) {
+ if (Incoming == PN)
+ continue;
+ if (!Incoming->hasOneUse())
+ return {};
+ if (auto *IncomingPHI = dyn_cast<PHINode>(Incoming)) {
+ if (NextPHIChain)
+ return {};
+ NextPHIChain = IncomingPHI;
+ continue;
+ }
+ // Only one update/step is allowed. The unmodified value must be PN.
+ if (StepOp || NextPHIChain)
+ return {};
+ PredEdge = Edge{Block, PHIChain->getParent()};
----------------
eas wrote:
Do we have a test like
```
header:
%m = phi ... ; monotonic header phi
...
UpdateBlock ; has %update = add %m, 1
| \
| bb
\ | /
%phi = phi [ %m, ...], [ %m, ...], [%update, %bb ]
```
? Or, in other words, `PredEdge` seems to be under documented/hard to reason about.
https://github.com/llvm/llvm-project/pull/214490
More information about the llvm-commits
mailing list