[llvm] [SCEV] Prove predicate via nuw AddRec value at max iteration (PR #210844)

Abhay Kanhere via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 14:47:43 PDT 2026


================
@@ -13255,6 +13258,50 @@ static bool isKnownPredicateExtendIdiom(CmpPredicate Pred, const SCEV *LHS,
   llvm_unreachable("unhandled case");
 }
 
+// Prove LHS Pred RHS by replacing an affine nuw AddRec LHS with its value at
+// the maximum iteration count and comparing that loop-invariant bound against
+// RHS. nuw makes the AddRec unsigned non-decreasing, so its max is at that
+// iteration regardless of the step's sign.
+bool ScalarEvolution::isKnownPredicateViaMaxValue(CmpPredicate Pred,
+                                                  SCEVUse LHS, SCEVUse RHS) {
+  if (Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_UGT) {
+    std::swap(LHS, RHS);
+    Pred = ICmpInst::getSwappedCmpPredicate(Pred);
+  }
+  if (Pred != ICmpInst::ICMP_ULE && Pred != ICmpInst::ICMP_ULT)
+    return false;
+  const auto *AR = dyn_cast<SCEVAddRecExpr>(LHS);
+  if (!AR || !AR->isAffine() || !AR->hasNoUnsignedWrap() ||
+      !AR->getType()->isIntegerTy())
+    return false;
+  const Loop *L = AR->getLoop();
+  if (!isLoopInvariant(RHS, L))
+    return false;
+
+  // The symbolic max BTC is only an upper bound on the trip count, so a nuw
+  // AddRec evaluated there can still unsigned-wrap. Widen and require
+  // start + BTC*step to provably not overflow.
+  const SCEV *BTC = getSymbolicMaxBackedgeTakenCount(L);
+  if (isa<SCEVCouldNotCompute>(BTC))
+    return false;
+  BTC = applyLoopGuards(BTC, L);
+
+  const SCEV *Start = AR->getStart();
+  const SCEV *Step = AR->getStepRecurrence(*this);
+  Type *WideTy = getWiderType(BTC->getType(), AR->getType());
----------------
AbhayKanhere wrote:

Changes to ensure we don't assume no-wrap - we compute in wider type ensuring no wrap - also check for overflow to ensure we dont wrap.

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


More information about the llvm-commits mailing list