[llvm] [LAA] Fix inverted bounds for negative-step AddRecs with unknown end. (PR #218388)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 05:26:52 PDT 2026


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/218388

Currently we use an conservative upper bound (-1) for runtime checks when evaluating the AddRec may wrap.

This does not properly account for negative steps. In that case, we need to use null as conservative lower bound.

One complication is that the null pointer may not be zero, so we need to check for that, and bail out completely if that's the case. We then must clean up any pointers partially added.

>From f51dda6b0792ad6ba5f5d1034254067f55fd9c64 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Sat, 22 Aug 2026 19:43:29 +0100
Subject: [PATCH] [LAA] Fix inverted bounds for negative-step AddRecs with
 unknown end.

Currently we use an conservative upper bound (-1) for runtime checks when
evaluating the AddRec may wrap.

This does not properly account for negative steps. In that case, we need
to use null as conservative lower bound.

One complication is that the null pointer may not be zero, so we need to
check for that, and bail out completely if that's the case. We then must
clean up any pointers partially added.
---
 .../llvm/Analysis/LoopAccessAnalysis.h        |  5 +-
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      | 99 +++++++++++--------
 .../all-ones-null-pointer.ll                  | 13 +--
 ...bolic-max-backedge-taken-count-may-wrap.ll | 22 +----
 .../negative-step-deref-off-by-eltsize.ll     |  4 +-
 ...ter-dependence-analysis-forked-pointers.ll | 11 +--
 .../LoopAccessAnalysis/symbolic-stride.ll     |  2 +-
 7 files changed, 75 insertions(+), 81 deletions(-)

diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index 392321448c895..c885adce7ac87 100644
--- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -556,8 +556,9 @@ class RuntimePointerChecking {
   /// We need \p PSE in order to compute the SCEV expression of the pointer
   /// according to the assumptions that we've made during the analysis.
   /// The method might also version the pointer stride according to \p Strides,
-  /// and add new predicates to \p PSE.
-  LLVM_ABI void insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
+  /// and add new predicates to \p PSE. Returns false without inserting anything
+  /// if the bounds of \p PtrExpr cannot be computed.
+  LLVM_ABI bool insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
                        Type *AccessTy, bool WritePtr, unsigned DepSetId,
                        unsigned ASId, PredicatedScalarEvolution &PSE,
                        bool NeedsFreeze);
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 9b407b1ca4729..0f7673816796e 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -330,6 +330,22 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
   return SE.isKnownPredicate(CmpInst::ICMP_ULE, MaxOffset, DerefBytesSCEV);
 }
 
+/// Return the lowest address of pointer type \p PtrTy, i.e. a null pointer.
+/// Returns nullptr if it cannot be used as a lower bound.
+static const SCEV *getLowestAddress(Type *PtrTy, ScalarEvolution &SE,
+                                    const DataLayout &DL) {
+  if (!DL.getNullPtrValue(PtrTy->getPointerAddressSpace()).isZero())
+    return nullptr;
+  return SE.getSCEV(Constant::getNullValue(PtrTy));
+}
+
+/// Return the highest address of pointer type \p PtrTy.
+static const SCEV *getHighestAddress(Type *PtrTy, ScalarEvolution &SE,
+                                     const DataLayout &DL) {
+  return SE.getSCEV(ConstantExpr::getIntToPtr(
+      Constant::getAllOnesValue(DL.getIndexType(PtrTy)), PtrTy));
+}
+
 std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
     const Loop *Lp, const SCEV *PtrExpr, Type *AccessTy, const SCEV *BTC,
     const SCEV *MaxBTC, ScalarEvolution *SE,
@@ -363,52 +379,51 @@ std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
     PtrBoundsPair = &Iter->second;
   }
 
+  // ScStart is the lowest accessed address; ScEnd is the highest one plus the
+  // size of the accessed element.
   const SCEV *ScStart;
   const SCEV *ScEnd;
 
   auto &DL = Lp->getHeader()->getDataLayout();
   if (SE->isLoopInvariant(PtrExpr, Lp)) {
-    ScStart = ScEnd = PtrExpr;
+    ScStart = PtrExpr;
+    ScEnd = SE->getAddExpr(PtrExpr, EltSizeSCEV);
   } else if (auto *AR = dyn_cast<SCEVAddRecExpr>(PtrExpr)) {
-    ScStart = AR->getStart();
-    if (!isa<SCEVCouldNotCompute>(BTC))
+    const SCEV *Step = AR->getStepRecurrence(*SE);
+    // The address of the last accessed element, if it can be computed
+    // precisely.
+    const SCEV *LastAddr = nullptr;
+    if (!isa<SCEVCouldNotCompute>(BTC)) {
       // Evaluating AR at an exact BTC is safe: LAA separately checks that
       // accesses cannot wrap in the loop. If evaluating AR at BTC wraps, then
       // the loop either triggers UB when executing a memory access with a
       // poison pointer or the wrapping/poisoned pointer is not used.
-      ScEnd = AR->evaluateAtIteration(BTC, *SE);
-    else {
-      // Evaluating AR at MaxBTC may wrap and create an expression that is less
-      // than the start of the AddRec due to wrapping (for example consider
-      // MaxBTC = -2). If that's the case, set ScEnd to -(EltSize + 1). ScEnd
-      // will get incremented by EltSize before returning, so this effectively
-      // sets ScEnd to the maximum unsigned value for the type. Note that LAA
-      // separately checks that accesses cannot not wrap, so unsigned max
-      // represents an upper bound.
-      if (evaluatePtrAddRecAtMaxBTCWillNotWrap(AR, MaxBTC, EltSizeSCEV, *SE, DL,
-                                               DT, AC, LoopGuards)) {
-        ScEnd = AR->evaluateAtIteration(MaxBTC, *SE);
-      } else {
-        ScEnd = SE->getAddExpr(
-            SE->getNegativeSCEV(EltSizeSCEV),
-            SE->getSCEV(ConstantExpr::getIntToPtr(
-                ConstantInt::getAllOnesValue(EltSizeSCEV->getType()),
-                AR->getType())));
-      }
+      LastAddr = AR->evaluateAtIteration(BTC, *SE);
+    } else if (evaluatePtrAddRecAtMaxBTCWillNotWrap(
+                   AR, MaxBTC, EltSizeSCEV, *SE, DL, DT, AC, LoopGuards)) {
+      LastAddr = AR->evaluateAtIteration(MaxBTC, *SE);
     }
-    const SCEV *Step = AR->getStepRecurrence(*SE);
-
-    // For expressions with negative step, the upper bound is ScStart and the
-    // lower bound is ScEnd.
-    if (const auto *CStep = dyn_cast<SCEVConstant>(Step)) {
-      if (CStep->getValue()->isNegative())
-        std::swap(ScStart, ScEnd);
+    const SCEV *Start = AR->getStart();
+    Type *PtrTy = AR->getType();
+    if (SE->isKnownNegative(Step)) {
+      ScStart = LastAddr ? LastAddr : getLowestAddress(PtrTy, *SE, DL);
+      if (!ScStart)
+        return {SE->getCouldNotCompute(), SE->getCouldNotCompute()};
+      ScEnd = SE->getAddExpr(Start, EltSizeSCEV);
+    } else if (SE->isKnownNonNegative(Step)) {
+      ScStart = Start;
+      // The highest address for the type saturates; adding EltSize to it would
+      // wrap to the start of the address space.
+      ScEnd = LastAddr ? SE->getAddExpr(LastAddr, EltSizeSCEV)
+                       : getHighestAddress(PtrTy, *SE, DL);
     } else {
+      if (!LastAddr)
+        return {SE->getCouldNotCompute(), SE->getCouldNotCompute()};
       // Fallback case: the step is not constant, but we can still
       // get the upper and lower bounds of the interval by using min/max
       // expressions.
-      ScStart = SE->getUMinExpr(ScStart, ScEnd);
-      ScEnd = SE->getUMaxExpr(AR->getStart(), ScEnd);
+      ScStart = SE->getUMinExpr(Start, LastAddr);
+      ScEnd = SE->getAddExpr(SE->getUMaxExpr(Start, LastAddr), EltSizeSCEV);
     }
   } else
     return {SE->getCouldNotCompute(), SE->getCouldNotCompute()};
@@ -416,9 +431,6 @@ std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
   assert(SE->isLoopInvariant(ScStart, Lp) && "ScStart needs to be invariant");
   assert(SE->isLoopInvariant(ScEnd, Lp) && "ScEnd needs to be invariant");
 
-  // Add the size of the pointed element to ScEnd.
-  ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV);
-
   std::pair<const SCEV *, const SCEV *> Res = {ScStart, ScEnd};
   if (PointerBounds)
     *PtrBoundsPair = Res;
@@ -427,7 +439,7 @@ std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
 
 /// Calculate Start and End points of memory access using
 /// getStartAndEndForAccess.
-void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
+bool RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
                                     Type *AccessTy, bool WritePtr,
                                     unsigned DepSetId, unsigned ASId,
                                     PredicatedScalarEvolution &PSE,
@@ -437,11 +449,11 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, const SCEV *PtrExpr,
   const auto &[ScStart, ScEnd] = getStartAndEndForAccess(
       Lp, PtrExpr, AccessTy, BTC, SymbolicMaxBTC, PSE.getSE(),
       &DC.getPointerBounds(), DC.getDT(), DC.getAC(), LoopGuards);
-  assert(!isa<SCEVCouldNotCompute>(ScStart) &&
-         !isa<SCEVCouldNotCompute>(ScEnd) &&
-         "must be able to compute both start and end expressions");
+  if (isa<SCEVCouldNotCompute>(ScStart) || isa<SCEVCouldNotCompute>(ScEnd))
+    return false;
   Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, PtrExpr,
                         NeedsFreeze);
+  return true;
 }
 
 bool RuntimePointerChecking::tryToCreateDiffCheck(
@@ -1343,6 +1355,10 @@ bool AccessAnalysis::createCheckForAccess(
   }
   PSE.addPredicates(Predicates);
 
+  // Remember the number of pointers inserted so far, to remove the pointers of
+  // this access again if the bounds of any of them cannot be computed, to avoid
+  // partial inserts.
+  unsigned NumPointers = RtCheck.Pointers.size();
   for (const auto &[PtrExpr, NeedsFreeze] : RTCheckPtrs) {
     // The id of the dependence set.
     unsigned DepId;
@@ -1358,8 +1374,11 @@ bool AccessAnalysis::createCheckForAccess(
       DepId = RunningDepId++;
 
     bool IsWrite = Access.getInt();
-    RtCheck.insert(TheLoop, Ptr, PtrExpr, AccessTy, IsWrite, DepId, ASId, PSE,
-                   NeedsFreeze);
+    if (!RtCheck.insert(TheLoop, Ptr, PtrExpr, AccessTy, IsWrite, DepId, ASId,
+                        PSE, NeedsFreeze)) {
+      RtCheck.Pointers.truncate(NumPointers);
+      return false;
+    }
     LLVM_DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n');
   }
 
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll b/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
index f58c7cf587ff6..031c4c7a6c4d3 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
@@ -10,21 +10,10 @@ target datalayout = "po1:64:64"
 define void @negative_step_all_ones_null(ptr addrspace(1) %P, ptr addrspace(1) %S) {
 ; CHECK-LABEL: 'negative_step_all_ones_null'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Report: cannot identify array bounds
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:      Run-time memory checks:
-; CHECK-NEXT:      Check 0:
-; CHECK-NEXT:        Comparing group GRP0:
-; CHECK-NEXT:          %ptr.iv = phi ptr addrspace(1) [ %P, %entry ], [ %ptr.iv.next, %loop ]
-; CHECK-NEXT:        Against group GRP1:
-; CHECK-NEXT:        ptr addrspace(1) %S
 ; CHECK-NEXT:      Grouped accesses:
-; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: (-4 + inttoptr (i64 -1 to ptr addrspace(1)))<nsw> High: (4 + %P))
-; CHECK-NEXT:            Member: {%P,+,-4}<nw><%loop>
-; CHECK-NEXT:        Group GRP1:
-; CHECK-NEXT:          (Low: %S High: (4 + %S))
-; CHECK-NEXT:            Member: %S
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
 ; CHECK-NEXT:      SCEV assumptions:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/evaluate-at-symbolic-max-backedge-taken-count-may-wrap.ll b/llvm/test/Analysis/LoopAccessAnalysis/evaluate-at-symbolic-max-backedge-taken-count-may-wrap.ll
index ebbb435bc2264..232302dc922b2 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/evaluate-at-symbolic-max-backedge-taken-count-may-wrap.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/evaluate-at-symbolic-max-backedge-taken-count-may-wrap.ll
@@ -181,7 +181,6 @@ exit:
 ; The pointer AddRec has a negative step, so its start is the highest accessed
 ; address and it is the *lowest* accessed address that is unknown when
 ; evaluating at the symbolic max BTC may wrap.
-; FIXME: Currently the bounds are incorrect.
 define void @symbolic_max_btc_may_wrap_negative_step(ptr %P, ptr %S) {
 ; CHECK-LABEL: 'symbolic_max_btc_may_wrap_negative_step'
 ; CHECK-NEXT:    loop:
@@ -195,7 +194,7 @@ define void @symbolic_max_btc_may_wrap_negative_step(ptr %P, ptr %S) {
 ; CHECK-NEXT:        ptr %S
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: (-4 + inttoptr (i32 -1 to ptr))<nsw> High: (4 + %P))
+; CHECK-NEXT:          (Low: null High: (4 + %P))
 ; CHECK-NEXT:            Member: {%P,+,-4}<nw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %S High: (4 + %S))
@@ -225,7 +224,6 @@ exit:
 
 ; Same as @symbolic_max_btc_may_wrap_negative_step, but with a non-constant
 ; step that is known to be negative.
-; FIXME: Currently the bounds are incorrect.
 define void @symbolic_max_btc_may_wrap_non_constant_negative_step(ptr %P, ptr %S, i32 %step) {
 ; CHECK-LABEL: 'symbolic_max_btc_may_wrap_non_constant_negative_step'
 ; CHECK-NEXT:    loop:
@@ -239,7 +237,7 @@ define void @symbolic_max_btc_may_wrap_non_constant_negative_step(ptr %P, ptr %S
 ; CHECK-NEXT:        ptr %S
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: ((-4 + inttoptr (i32 -1 to ptr))<nsw> umin %P) High: (4 + ((-4 + inttoptr (i32 -1 to ptr))<nsw> umax %P))<nsw>)
+; CHECK-NEXT:          (Low: null High: (4 + %P))
 ; CHECK-NEXT:            Member: {%P,+,(-1 + (-1 * (zext i16 (trunc i32 %step to i16) to i32))<nsw>)<nsw>}<nw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %S High: (4 + %S))
@@ -272,7 +270,6 @@ exit:
 ; Same as @symbolic_max_btc_may_wrap_negative_step, but with a non-constant
 ; step that is known to be non-negative, so the start is the lowest accessed
 ; address and only the upper bound has to be widened.
-; FIXME: Currently the bounds are incorrect.
 define void @symbolic_max_btc_may_wrap_non_constant_non_negative_step(ptr %P, ptr %S, i32 %step) {
 ; CHECK-LABEL: 'symbolic_max_btc_may_wrap_non_constant_non_negative_step'
 ; CHECK-NEXT:    loop:
@@ -286,7 +283,7 @@ define void @symbolic_max_btc_may_wrap_non_constant_non_negative_step(ptr %P, pt
 ; CHECK-NEXT:        ptr %S
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: ((-4 + inttoptr (i32 -1 to ptr))<nsw> umin %P) High: (4 + ((-4 + inttoptr (i32 -1 to ptr))<nsw> umax %P))<nsw>)
+; CHECK-NEXT:          (Low: %P High: inttoptr (i32 -1 to ptr))
 ; CHECK-NEXT:            Member: {%P,+,(zext i16 (trunc i32 %step to i16) to i32)}<nuw><%loop>
 ; CHECK-NEXT:        Group GRP1:
 ; CHECK-NEXT:          (Low: %S High: (4 + %S))
@@ -321,21 +318,10 @@ exit:
 define void @symbolic_max_btc_may_wrap_unknown_step_direction(ptr %P, ptr %S, i32 %step.a, i32 %step.b) {
 ; CHECK-LABEL: 'symbolic_max_btc_may_wrap_unknown_step_direction'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with run-time checks
+; CHECK-NEXT:      Report: cannot identify array bounds
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:      Run-time memory checks:
-; CHECK-NEXT:      Check 0:
-; CHECK-NEXT:        Comparing group GRP0:
-; CHECK-NEXT:          %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
-; CHECK-NEXT:        Against group GRP1:
-; CHECK-NEXT:        ptr %S
 ; CHECK-NEXT:      Grouped accesses:
-; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: ((-4 + inttoptr (i32 -1 to ptr))<nsw> umin %P) High: (4 + ((-4 + inttoptr (i32 -1 to ptr))<nsw> umax %P))<nsw>)
-; CHECK-NEXT:            Member: {%P,+,(%step.a + %step.b)}<nw><%loop>
-; CHECK-NEXT:        Group GRP1:
-; CHECK-NEXT:          (Low: %S High: (4 + %S))
-; CHECK-NEXT:            Member: %S
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
 ; CHECK-NEXT:      SCEV assumptions:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/negative-step-deref-off-by-eltsize.ll b/llvm/test/Analysis/LoopAccessAnalysis/negative-step-deref-off-by-eltsize.ll
index 1a53fba949749..b9f1857e40137 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/negative-step-deref-off-by-eltsize.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/negative-step-deref-off-by-eltsize.ll
@@ -28,10 +28,10 @@ define void @reverse_reaches_base(ptr dereferenceable(16) %A, ptr dereferenceabl
 ; CHECK-NEXT:          %gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
 ; CHECK-NEXT:      Grouped accesses:
 ; CHECK-NEXT:        Group GRP0:
-; CHECK-NEXT:          (Low: (-4 + inttoptr (i64 -1 to ptr))<nsw> High: (16 + %B)<nuw>)
+; CHECK-NEXT:          (Low: null High: (16 + %B)<nuw>)
 ; CHECK-NEXT:            Member: {(12 + %B)<nuw>,+,-4}<nw><%loop>
 ; CHECK-NEXT:        Group GRP1:
-; CHECK-NEXT:          (Low: (-4 + inttoptr (i64 -1 to ptr))<nsw> High: (16 + %A)<nuw>)
+; CHECK-NEXT:          (Low: null High: (16 + %A)<nuw>)
 ; CHECK-NEXT:            Member: {(12 + %A)<nuw>,+,-4}<nw><%loop>
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
index ad0467fc6b734..19c52c7dfa88b 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
@@ -253,15 +253,14 @@ exit:
 define void @forked_ptr_with_uncomputable_bounds(ptr %P, ptr %S, i32 %step.a, i32 %step.b, i1 %c) {
 ; CHECK-LABEL: 'forked_ptr_with_uncomputable_bounds'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
-; CHECK-NEXT:  Unsafe indirect dependence.
+; CHECK-NEXT:      Report: cannot identify array bounds
 ; CHECK-NEXT:      Dependences:
-; CHECK-NEXT:        IndirectUnsafe:
-; CHECK-NEXT:            %l = load i32, ptr %S, align 4 ->
-; CHECK-NEXT:            store i32 %l, ptr %select, align 4
-; CHECK-EMPTY:
 ; CHECK-NEXT:      Run-time memory checks:
 ; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: %S High: (4 + %S))
+; CHECK-NEXT:            Member: %S
+; CHECK-NEXT:      Generated run-time checks are incomplete
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
 ; CHECK-NEXT:      SCEV assumptions:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll b/llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll
index c6ce3fbdf678f..f4aff75582c02 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll
@@ -521,7 +521,7 @@ define void @unknown_stride_equalto_zext_tc(i16 zeroext %N, ptr %A, ptr %B, i32
 ; CHECK-NEXT:          (Low: %A High: (4 + %A))
 ; CHECK-NEXT:            Member: %A
 ; CHECK-NEXT:        Group GRP1:
-; CHECK-NEXT:          (Low: (((2 * (sext i32 %j to i64))<nsw> + %B) umin ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (zext i16 %N to i32))<nsw> to i64) * (zext i16 %N to i64)) + %B)) High: (2 + (((2 * (sext i32 %j to i64))<nsw> + %B) umax ((2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (zext i16 %N to i32))<nsw> to i64) * (zext i16 %N to i64)) + %B))))
+; CHECK-NEXT:          (Low: ((2 * (sext i32 %j to i64))<nsw> + %B) High: (2 + (2 * (sext i32 %j to i64))<nsw> + (2 * (zext i32 (-1 + (zext i16 %N to i32))<nsw> to i64) * (zext i16 %N to i64)) + %B))
 ; CHECK-NEXT:            Member: {((2 * (sext i32 %j to i64))<nsw> + %B),+,(2 * (zext i16 %N to i64))<nuw><nsw>}<nw><%loop>
 ; CHECK-EMPTY:
 ; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.



More information about the llvm-commits mailing list