[llvm] [Loads] Support dereference for non-constant offset (PR #149551)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 2 12:32:00 PDT 2025


================
@@ -368,32 +368,26 @@ bool llvm::isDereferenceableAndAlignedInLoop(
     AccessSize = MaxPtrDiff;
     AccessSizeSCEV = PtrDiff;
   } else if (auto *MinAdd = dyn_cast<SCEVAddExpr>(AccessStart)) {
-    if (MinAdd->getNumOperands() != 2)
+    const auto *NewBase = dyn_cast<SCEVUnknown>(SE.getPointerBase(MinAdd));
+    if (!NewBase)
       return false;
 
-    const auto *Offset = dyn_cast<SCEVConstant>(MinAdd->getOperand(0));
-    const auto *NewBase = dyn_cast<SCEVUnknown>(MinAdd->getOperand(1));
-    if (!Offset || !NewBase)
-      return false;
-
-    // The following code below assumes the offset is unsigned, but GEP
-    // offsets are treated as signed so we can end up with a signed value
-    // here too. For example, suppose the initial PHI value is (i8 255),
-    // the offset will be treated as (i8 -1) and sign-extended to (i64 -1).
-    if (Offset->getAPInt().isNegative())
+    auto *OffsetSCEV = SE.removePointerBase(MinAdd);
+    if (!SE.isKnownNonNegative(OffsetSCEV))
       return false;
 
     // For the moment, restrict ourselves to the case where the offset is a
     // multiple of the requested alignment and the base is aligned.
     // TODO: generalize if a case found which warrants
-    if (Offset->getAPInt().urem(Alignment.value()) != 0)
+    if (SE.getMinTrailingZeros(OffsetSCEV) < Log2(Alignment))
       return false;
 
     bool Overflow = false;
-    AccessSize = MaxPtrDiff.uadd_ov(Offset->getAPInt(), Overflow);
+    AccessSize =
+        MaxPtrDiff.uadd_ov(SE.getUnsignedRangeMax(OffsetSCEV), Overflow);
     if (Overflow)
----------------
fhahn wrote:

Hmm, I think this may be a limitation down to reasoning with constant ranges

Say we have something like

`(1 umax %N)) umin %iv.start) + ((-1 + (1 umax %N)) umin %iv.start)`

` (1 umax %N)) umin %iv.start` = [0, 2000]
`(-1 * (1 umax %N)) umin %iv.start)` = [-2000, 0)

But the addition of those must assume that either side take any value of the range, so even 0 - 1.

I guess with going to the ranges, we lose the fact that %N and %iv.start on both sides are the same values.

Not sure if we would fare better if we kept things symbolicly


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


More information about the llvm-commits mailing list