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

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 2 19:29:20 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)
----------------
annamthomas wrote:

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

ah yes.

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

I'd tried using SCEV.willNotOverflow for the add at `SE.getAddExpr(PtrDiff, OffsetSCEV)` instead of the `uadd_ov`, but it hits on another limitation because the RHS is not a constant (it's OffsetSCEV: (16 + (4 * %iv.start)<nuw><nsw>)<nuw><nsw>).   

Maybe fixing that limitation looks like the way forward.

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


More information about the llvm-commits mailing list