[llvm] [IVDescriptors] Implement MonotonicDescriptor (PR #140720)

Benjamin Maxwell via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 11 05:27:14 PST 2025


================
@@ -1661,3 +1661,124 @@ bool InductionDescriptor::isInductionPHI(
   D = InductionDescriptor(StartValue, IK_PtrInduction, Step);
   return true;
 }
+
+bool MonotonicDescriptor::setSCEV(const SCEV *NewExpr) {
+  auto *AddRec = dyn_cast<SCEVAddRecExpr>(NewExpr);
+  if (!AddRec || !AddRec->isAffine())
+    return false;
+  Expr = AddRec;
+  return true;
+}
+
+// Recognize monotonic phi variable by matching the following pattern:
+// loop_header:
+//   %monotonic_phi = [%start, %preheader], [%chain_phi0, %latch]
+//
+// step_bb:
+//   %step = add/gep %monotonic_phi, %step_val
+//
+// bbN:
+//   %chain_phiN = [%monotonic_phi, ], [%step, ]
+//
+// ...
+//
+// bb1:
+//   %chain_phi1 = [%monotonic_phi, ], [%chain_phi2, ]
+//
+// latch:
+//   %chain_phi0 = [%monotonic_phi, %pred], [%chain_phi1, %pred]
+//
+// For this pattern, monotonic phi is described by {%start, +, %step} recurrence
+// and predicate is CFG edge %step_bb -> %bbN.
+bool MonotonicDescriptor::isMonotonicPHI(PHINode *PN, const Loop *L,
+                                         MonotonicDescriptor &Desc,
+                                         ScalarEvolution &SE) {
+  if (!PN->getType()->isIntOrPtrTy() || PN->getParent() != L->getHeader())
+    return false;
+  auto *BackEdgeInst =
+      dyn_cast<PHINode>(PN->getIncomingValueForBlock(L->getLoopLatch()));
+  if (!BackEdgeInst)
+    return false;
+  PHINode *PHIChain = BackEdgeInst;
+  std::optional<std::pair<Edge, Value *>> Inc;
+  while (PHIChain) {
+    Desc.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 false;
+      if (auto *IncomingPHI = dyn_cast<PHINode>(Incoming)) {
+        if (NextPHIChain)
+          return false;
+        NextPHIChain = IncomingPHI;
+        continue;
+      }
+      if (Inc)
+        return false;
----------------
MacDue wrote:

Just a thought: Should this be `if (Inc || NextPHIChain)` ? 

https://github.com/llvm/llvm-project/pull/140720


More information about the llvm-commits mailing list