[llvm] [LAA] Allow vectorizing `A[NonZeroNonConstantStride*I] += 1` (PR #186262)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 04:12:14 PDT 2026


================
@@ -969,54 +969,56 @@ class AccessAnalysis {
 
 } // end anonymous namespace
 
-std::optional<int64_t>
-llvm::getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp,
-                          Type *AccessTy, Value *Ptr,
-                          PredicatedScalarEvolution &PSE) {
+const SCEV *llvm::getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp,
+                                      Type *AccessTy, Value *Ptr,
+                                      PredicatedScalarEvolution &PSE) {
   if (isa<ScalableVectorType>(AccessTy)) {
     LLVM_DEBUG(dbgs() << "LAA: Bad stride - Scalable object: " << *AccessTy
                       << "\n");
-    return std::nullopt;
+    return nullptr;
   }
 
-  // The access function must stride over the innermost loop.
-  if (Lp != AR->getLoop()) {
+  auto BadStride = [&](auto Str) {
     LLVM_DEBUG({
-      dbgs() << "LAA: Bad stride - Not striding over innermost loop ";
+      dbgs() << "LAA: Bad stride - " << Str << " ";
       if (Ptr)
         dbgs() << *Ptr << " ";
 
       dbgs() << "SCEV: " << *AR << "\n";
     });
-    return std::nullopt;
-  }
+    return nullptr;
+  };
+
+  // The access function must stride over the innermost loop.
+  if (Lp != AR->getLoop())
+    return BadStride("Not striding over innermost loop");
+
+  // Check the step is loop invariant.
+  if (!AR->isAffine())
+    return BadStride("Step is varying");
 
-  // Check the step is constant.
   const SCEV *Step = AR->getStepRecurrence(*PSE.getSE());
 
-  // Calculate the pointer stride and check if it is constant.
-  const APInt *APStepVal;
-  if (!match(Step, m_scev_APInt(APStepVal))) {
-    LLVM_DEBUG({
-      dbgs() << "LAA: Bad stride - Not a constant strided ";
-      if (Ptr)
-        dbgs() << *Ptr << " ";
-      dbgs() << "SCEV: " << *AR << "\n";
-    });
-    return std::nullopt;
-  }
+  auto *SE = PSE.getSE();
+  const SCEV *AbsStep = SE->getAbsExpr(Step, false);
 
-  const auto &DL = Lp->getHeader()->getDataLayout();
-  TypeSize AllocSize = DL.getTypeAllocSize(AccessTy);
-  int64_t Size = AllocSize.getFixedValue();
+  const SCEV *TypeSizeScev = SE->getSizeOfExpr(
+      Step->getType(), SE->getDataLayout().getTypeAllocSize(AccessTy));
 
-  // Huge step value - give up.
-  std::optional<int64_t> StepVal = APStepVal->trySExtValue();
-  if (!StepVal)
-    return std::nullopt;
+  if (!SE->getURemExpr(AbsStep, TypeSizeScev)->isZero())
----------------
artagnon wrote:

I think we're allowed to add predicates to PSE here, which this function would facilitate:

```cpp
  LLVM_ABI bool
  isKnownMultipleOf(const SCEV *S, uint64_t M,
                    SmallVectorImpl<const SCEVPredicate *> &Assumptions);
```

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


More information about the llvm-commits mailing list