[llvm] [SCEVDivision] Prevent propagation of incorrect no-wrap flags (PR #154745)

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 21 07:52:38 PDT 2025


================
@@ -141,10 +141,26 @@ void SCEVDivision::visitAddRecExpr(const SCEVAddRecExpr *Numerator) {
   if (Ty != StartQ->getType() || Ty != StartR->getType() ||
       Ty != StepQ->getType() || Ty != StepR->getType())
     return cannotDivide(Numerator);
+
+  // Infer no-wrap flags for Remainder.
+  // TODO: Catch more cases.
+  SCEV::NoWrapFlags NumFlags = Numerator->getNoWrapFlags();
+  SCEV::NoWrapFlags RemFlags = SCEV::NoWrapFlags::FlagAnyWrap;
+  const SCEV *StepNumAbs =
+      SE.getAbsExpr(Numerator->getStepRecurrence(SE), /*IsNSW=*/false);
+  const SCEV *StepRAbs = SE.getAbsExpr(StepR, /*IsNSW=*/false);
+  const Loop *L = Numerator->getLoop();
+
+  // If abs(StepR) <=u abs(StepNumAbs) and both are loop invariant, propagate
----------------
Meinersbur wrote:

<!--
(Start * i + Step) / Denom
=
i*(StartQ + StartR/Denom) + StepQ + StepR/Denom
=
i*StartQ + i*StartR/Denom + StepQ + StepR/Denom
-->

```suggestion
  // If abs(StepR) <=u abs(NumStep) and both are loop invariant, propagate
```
`StepNumAbs` already is the absolute

Add reasoning here? Such as "since the denominator cannot be zero, so abs(Denom) >= 1, the range of the SCEVAddRec can only shrink, i.e. if the range was not exceeding the size of the integer type's domain (i.e. not self-wrap) before, it will not self-wrap after division"

I think the deduction is more general, only needs that the nominator is NW and the denominator is loop-invariant.

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


More information about the llvm-commits mailing list