[llvm] [LAA] Switch safe-distance APIs to operate in elements instead of bits, NFCI'ish (PR #191867)

Andrei Elovikov via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 13:47:37 PDT 2026


https://github.com/eas updated https://github.com/llvm/llvm-project/pull/191867

>From b8ef9ca386740503d99685cdd9c4bb8fdf3a2c77 Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Fri, 10 Jul 2026 07:24:43 -0700
Subject: [PATCH 1/4] Add test

---
 .../safe-with-dep-distance-non-power-of-2.ll  | 62 +++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
index 79dcfd2c4c08d..e697d4ac1b496 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
@@ -258,3 +258,65 @@ loop:
 exit:
   ret void
 }
+
+; FIXME: "maximum safe store-load forward width of 32 bits" for i32 access means
+; there is no safe VF, need to be reported properly.
+define void @two_store_load_forward_deps(ptr %A, ptr %B) {
+; CHECK-LABEL: 'two_store_load_forward_deps'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 96 bits, with a maximum safe store-load forward width of 32 bits with run-time checks
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:            %vb = load i32, ptr %b.ld, align 4 ->
+; CHECK-NEXT:            store i32 %vb, ptr %b.st, align 4
+; CHECK-EMPTY:
+; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:            %va = load i32, ptr %a.ld, align 4 ->
+; CHECK-NEXT:            store i32 %va, ptr %a.st, align 4
+; CHECK-EMPTY:
+; CHECK-NEXT:      Run-time memory checks:
+; CHECK-NEXT:      Check 0:
+; CHECK-NEXT:        Comparing group GRP0:
+; CHECK-NEXT:          %a.ld = getelementptr i32, ptr %A, i64 %iv
+; CHECK-NEXT:          %a.st = getelementptr i32, ptr %A, i64 %a.off
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %b.ld = getelementptr i32, ptr %B, i64 %ib
+; CHECK-NEXT:          %b.st = getelementptr i32, ptr %B, i64 %b.off
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: %A High: (4132 + %A))
+; CHECK-NEXT:            Member: {%A,+,4}<nw><%loop>
+; CHECK-NEXT:            Member: {(32 + %A),+,4}<nw><%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: %B High: (8220 + %B))
+; CHECK-NEXT:            Member: {%B,+,8}<nw><%loop>
+; CHECK-NEXT:            Member: {(24 + %B),+,8}<nw><%loop>
+; CHECK-EMPTY:
+; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
+; CHECK-NEXT:      SCEV assumptions:
+; CHECK-EMPTY:
+; CHECK-NEXT:      Expressions re-written:
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %a.ld = getelementptr i32, ptr %A, i64 %iv
+  %va = load i32, ptr %a.ld, align 4
+  %a.off = add i64 %iv, 8
+  %a.st = getelementptr i32, ptr %A, i64 %a.off
+  store i32 %va, ptr %a.st, align 4
+  %ib = shl i64 %iv, 1
+  %b.ld = getelementptr i32, ptr %B, i64 %ib
+  %vb = load i32, ptr %b.ld, align 4
+  %b.off = add i64 %ib, 6
+  %b.st = getelementptr i32, ptr %B, i64 %b.off
+  store i32 %vb, ptr %b.st, align 4
+  %iv.next = add i64 %iv, 1
+  %cmp = icmp ne i64 %iv, 1024
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}

>From dca9b619a64a69f475796b3e2dd80cc23c30ac79 Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Fri, 10 Jul 2026 10:37:16 -0700
Subject: [PATCH 2/4] [LAA] Properly report strided access preventing
 store-to-load forwarding

Test by @fhahn in https://github.com/llvm/llvm-project/pull/191867.
Before this change LAA results in

> maximum safe store-load forward width of 32 bits

for i32 accesses, effectively meaning that only `VF == 1` is safe, yet
not explicitly returning `false` from `couldPreventStoreLoadForward`.
This PR fixes that.
---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp                   | 7 +++++++
 .../safe-with-dep-distance-non-power-of-2.ll               | 7 +++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index ff1032e669265..3c2d65da94b3c 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1958,6 +1958,13 @@ bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
     uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
     MaxStoreLoadForwardSafeDistanceInBits =
         std::min(MaxStoreLoadForwardSafeDistanceInBits, MaxVFInBits);
+
+    if (MaxVF == 1) {
+      LLVM_DEBUG(
+          dbgs() << "LAA: strided access with Distance " << Distance
+                 << " that could cause a store-load forwarding conflict\n");
+      return true;
+    }
   }
   return false;
 }
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
index e697d4ac1b496..0ad4d1b7bf3b9 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
@@ -259,14 +259,13 @@ exit:
   ret void
 }
 
-; FIXME: "maximum safe store-load forward width of 32 bits" for i32 access means
-; there is no safe VF, need to be reported properly.
 define void @two_store_load_forward_deps(ptr %A, ptr %B) {
 ; CHECK-LABEL: 'two_store_load_forward_deps'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 96 bits, with a maximum safe store-load forward width of 32 bits with run-time checks
+; 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:  Backward loop carried data dependence that prevents store-to-load forwarding.
 ; CHECK-NEXT:      Dependences:
-; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:        BackwardVectorizableButPreventsForwarding:
 ; CHECK-NEXT:            %vb = load i32, ptr %b.ld, align 4 ->
 ; CHECK-NEXT:            store i32 %vb, ptr %b.st, align 4
 ; CHECK-EMPTY:

>From 1fe01f44b555ecd5c49d99fd3932a7dc06daef7f Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Mon, 13 Apr 2026 11:07:18 -0700
Subject: [PATCH 3/4] [LAA] Switch safe-distance APIs to operate in elements
 instead of bits

The only client (LoopVectorizer) immediately converts the returned
values to operate in number of elements instead of bits, so it makes
sense to just operate in elements directly to simplify logic.

While doing this refactoring I've faced a multiplication by eight in
`couldPreventStoreLoadForward` that I couldn't explain. From what I see
it just "cancels out" with the same in an `if` later and is unnecessary.
I'm dropping it in this PR, but I'm splitting it into two commits to
ease review of that part.
---
 .../llvm/Analysis/LoopAccessAnalysis.h        | 30 ++++++--------
 .../Vectorize/LoopVectorizationLegality.h     |  8 ++--
 llvm/lib/Analysis/LoopAccessAnalysis.cpp      | 41 +++++++++----------
 .../Vectorize/LoopVectorizationPlanner.cpp    |  7 ++--
 .../accesses-completely-before-or-after.ll    |  2 +-
 .../LoopAccessAnalysis/depend_diff_types.ll   |  2 +-
 ...es-safe-dep-due-to-backedge-taken-count.ll |  2 +-
 .../max_safe_dep_dist_non_unit_stride.ll      |  2 +-
 .../multiple-strides-rt-memory-checks.ll      |  2 +-
 .../non-constant-distance-backward.ll         |  8 ++--
 .../non-constant-strides-backward.ll          |  2 +-
 .../safe-with-dep-distance-non-power-of-2.ll  |  6 +--
 .../safe-with-dep-distance.ll                 |  2 +-
 .../stride-access-dependence.ll               |  8 ++--
 14 files changed, 57 insertions(+), 65 deletions(-)

diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index 392321448c895..a50cfde8cd4c7 100644
--- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -220,28 +220,25 @@ class MemoryDepChecker {
   /// Return true if the number of elements that are safe to operate on
   /// simultaneously is not bounded.
   bool isSafeForAnyVectorWidth() const {
-    return MaxSafeVectorWidthInBits == UINT_MAX;
+    return MaxSafeNumElements == UINT_MAX;
   }
 
   /// Return the number of elements that are safe to operate on
-  /// simultaneously, multiplied by the size of the element in bits.
-  uint64_t getMaxSafeVectorWidthInBits() const {
-    return MaxSafeVectorWidthInBits;
-  }
+  /// simultaneously.
+  uint64_t getMaxSafeNumElements() const { return MaxSafeNumElements; }
 
   /// Return true if there are no store-load forwarding dependencies.
   bool isSafeForAnyStoreLoadForwardDistances() const {
-    return MaxStoreLoadForwardSafeDistanceInBits ==
-           std::numeric_limits<uint64_t>::max();
+    return MaxStoreLoadForwardSafeNumElements == UINT_MAX;
   }
 
   /// Return safe power-of-2 number of elements, which do not prevent store-load
-  /// forwarding, multiplied by the size of the elements in bits.
-  uint64_t getStoreLoadForwardSafeDistanceInBits() const {
+  /// forwarding.
+  uint64_t getStoreLoadForwardSafeNumElements() const {
     assert(!isSafeForAnyStoreLoadForwardDistances() &&
            "Expected the distance, that prevent store-load forwarding, to be "
            "set.");
-    return MaxStoreLoadForwardSafeDistanceInBits;
+    return MaxStoreLoadForwardSafeNumElements;
   }
 
   /// In same cases when the dependency check fails we can still
@@ -339,16 +336,13 @@ class MemoryDepChecker {
   /// simultaneously.
   uint64_t MinDepDistBytes = 0;
 
-  /// Number of elements (from consecutive iterations) that are safe to
-  /// operate on simultaneously, multiplied by the size of the element in bits.
-  /// The size of the element is taken from the memory access that is most
-  /// restrictive.
-  uint64_t MaxSafeVectorWidthInBits = -1U;
+  /// Number of elements (from consecutive iterations) that are safe to operate
+  /// on simultaneously.
+  uint64_t MaxSafeNumElements = -1U;
 
   /// Maximum power-of-2 number of elements, which do not prevent store-load
-  /// forwarding, multiplied by the size of the elements in bits.
-  uint64_t MaxStoreLoadForwardSafeDistanceInBits =
-      std::numeric_limits<uint64_t>::max();
+  /// forwarding.
+  uint64_t MaxStoreLoadForwardSafeNumElements = -1U;
 
   /// Whether we should try to vectorize the loop with runtime checks, if the
   /// dependencies are not safe.
diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
index 3e8db73fd79d2..b1710769f905d 100644
--- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
+++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
@@ -415,8 +415,8 @@ class LoopVectorizationLegality {
            LAI->getDepChecker().isSafeForAnyStoreLoadForwardDistances();
   }
 
-  uint64_t getMaxSafeVectorWidthInBits() const {
-    return LAI->getDepChecker().getMaxSafeVectorWidthInBits();
+  uint64_t getMaxSafeNumElements() const {
+    return LAI->getDepChecker().getMaxSafeNumElements();
   }
 
   /// Returns information about whether this loop contains at least one
@@ -447,8 +447,8 @@ class LoopVectorizationLegality {
 
   /// Return safe power-of-2 number of elements, which do not prevent store-load
   /// forwarding and safe to operate simultaneously.
-  uint64_t getMaxStoreLoadForwardSafeDistanceInBits() const {
-    return LAI->getDepChecker().getStoreLoadForwardSafeDistanceInBits();
+  uint64_t getMaxStoreLoadForwardSafeNumElements() const {
+    return LAI->getDepChecker().getStoreLoadForwardSafeNumElements();
   }
 
   /// Returns true if instruction \p I requires a mask for vectorization.
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 3c2d65da94b3c..1971aa636032e 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1926,22 +1926,22 @@ bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
   // cause any slowdowns.
   const uint64_t NumItersForStoreLoadThroughMemory = 8 * TypeByteSize;
   // Maximum vector factor.
-  uint64_t MaxVFWithoutSLForwardIssuesPowerOf2 =
-      std::min(VectorizerParams::MaxVectorWidth * TypeByteSize,
-               MaxStoreLoadForwardSafeDistanceInBits);
+  // TODO: This "8" doesn't make any sense:
+  uint64_t MaxVFWithoutSLForwardIssuesPowerOf2 = std::min<uint64_t>(
+      VectorizerParams::MaxVectorWidth, MaxStoreLoadForwardSafeNumElements * 8);
 
   // Compute the smallest VF at which the store and load would be misaligned.
-  for (uint64_t VF = 2 * TypeByteSize;
-       VF <= MaxVFWithoutSLForwardIssuesPowerOf2; VF *= 2) {
+  for (uint64_t VF = 2; VF <= MaxVFWithoutSLForwardIssuesPowerOf2; VF *= 2) {
     // If the number of vector iteration between the store and the load are
     // small we could incur conflicts.
-    if (Distance % VF && Distance / VF < NumItersForStoreLoadThroughMemory) {
+    if (Distance % (VF * TypeByteSize) &&
+        Distance / (VF * TypeByteSize) < NumItersForStoreLoadThroughMemory) {
       MaxVFWithoutSLForwardIssuesPowerOf2 = (VF >> 1);
       break;
     }
   }
 
-  if (MaxVFWithoutSLForwardIssuesPowerOf2 < 2 * TypeByteSize) {
+  if (MaxVFWithoutSLForwardIssuesPowerOf2 < 2) {
     LLVM_DEBUG(
         dbgs() << "LAA: Distance " << Distance
                << " that could cause a store-load forwarding conflict\n");
@@ -1950,14 +1950,12 @@ bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
 
   if (CommonStride &&
       MaxVFWithoutSLForwardIssuesPowerOf2 <
-          MaxStoreLoadForwardSafeDistanceInBits &&
-      MaxVFWithoutSLForwardIssuesPowerOf2 !=
-          VectorizerParams::MaxVectorWidth * TypeByteSize) {
-    uint64_t MaxVF =
-        bit_floor(MaxVFWithoutSLForwardIssuesPowerOf2 / CommonStride);
-    uint64_t MaxVFInBits = MaxVF * TypeByteSize * 8;
-    MaxStoreLoadForwardSafeDistanceInBits =
-        std::min(MaxStoreLoadForwardSafeDistanceInBits, MaxVFInBits);
+          MaxStoreLoadForwardSafeNumElements * 8 &&
+      MaxVFWithoutSLForwardIssuesPowerOf2 != VectorizerParams::MaxVectorWidth) {
+    uint64_t MaxVF = bit_floor(MaxVFWithoutSLForwardIssuesPowerOf2 *
+                               TypeByteSize / CommonStride);
+    MaxStoreLoadForwardSafeNumElements =
+        std::min(MaxStoreLoadForwardSafeNumElements, MaxVF);
 
     if (MaxVF == 1) {
       LLVM_DEBUG(
@@ -2442,7 +2440,7 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
   if (CheckCompletelyBeforeOrAfter())
     return Dependence::NoDep;
 
-  MaxSafeVectorWidthInBits = std::min(MaxSafeVectorWidthInBits, MaxVFInBits);
+  MaxSafeNumElements = std::min(MaxSafeNumElements, MaxVF);
   return Dependence::BackwardVectorizable;
 }
 
@@ -3203,12 +3201,13 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const {
     OS.indent(Depth) << "Memory dependences are safe";
     const MemoryDepChecker &DC = getDepChecker();
     if (!DC.isSafeForAnyVectorWidth())
-      OS << " with a maximum safe vector width of "
-         << DC.getMaxSafeVectorWidthInBits() << " bits";
+      OS << " with a maximum safe number of elements to operate on equal to "
+         << DC.getMaxSafeNumElements();
     if (!DC.isSafeForAnyStoreLoadForwardDistances()) {
-      uint64_t SLDist = DC.getStoreLoadForwardSafeDistanceInBits();
-      OS << ", with a maximum safe store-load forward width of " << SLDist
-         << " bits";
+      uint64_t SLDist = DC.getStoreLoadForwardSafeNumElements();
+      OS << ", with a maximum safe store-load forward number of elements to "
+            "operate on equal to "
+         << SLDist;
     }
     if (PtrRtChecking->Need)
       OS << " with run-time checks";
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
index dbb5ad28fb4ed..7b228e3594d02 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.cpp
@@ -402,11 +402,10 @@ FixedScalableVFPair VFSelectionContext::computeFeasibleMaxVF(
   // the memory accesses that is most restrictive (involved in the smallest
   // dependence distance).
   unsigned MaxSafeElementsPowerOf2 =
-      llvm::bit_floor(Legal->getMaxSafeVectorWidthInBits() / WidestType);
+      llvm::bit_floor(Legal->getMaxSafeNumElements());
   if (!Legal->isSafeForAnyStoreLoadForwardDistances()) {
-    unsigned SLDist = Legal->getMaxStoreLoadForwardSafeDistanceInBits();
-    MaxSafeElementsPowerOf2 =
-        std::min(MaxSafeElementsPowerOf2, SLDist / WidestType);
+    unsigned SLDist = Legal->getMaxStoreLoadForwardSafeNumElements();
+    MaxSafeElementsPowerOf2 = std::min(MaxSafeElementsPowerOf2, SLDist);
   }
 
   auto MaxSafeFixedVF = ElementCount::getFixed(MaxSafeElementsPowerOf2);
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll b/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll
index 9a329b70338bd..e224408f60c3e 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll
@@ -254,7 +254,7 @@ exit:
 define void @accesses_may_overlap_backwards_vectorizable(ptr dereferenceable(800) %dst) {
 ; CHECK-LABEL: 'accesses_may_overlap_backwards_vectorizable'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 128 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 8
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            store i16 0, ptr %gep.mul.2, align 2 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll
index 5d59660a68e90..55f916a3ab8a7 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/depend_diff_types.ll
@@ -11,7 +11,7 @@
 define void @backdep_type_size_equivalence(ptr nocapture %vec, i64 %n) {
 ; CHECK-LABEL: 'backdep_type_size_equivalence'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 3200 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 100
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        Forward:
 ; CHECK-NEXT:            %ld.f32 = load float, ptr %gep.iv, align 8 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/different-strides-safe-dep-due-to-backedge-taken-count.ll b/llvm/test/Analysis/LoopAccessAnalysis/different-strides-safe-dep-due-to-backedge-taken-count.ll
index 311de84993001..506a13194a1e2 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/different-strides-safe-dep-due-to-backedge-taken-count.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/different-strides-safe-dep-due-to-backedge-taken-count.ll
@@ -142,7 +142,7 @@ exit:
 define void @backward_dep_known_distance_less_than_btc(ptr %A) {
 ; CHECK-LABEL: 'backward_dep_known_distance_less_than_btc'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 4064 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 127
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %l = load i32, ptr %gep, align 4 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/max_safe_dep_dist_non_unit_stride.ll b/llvm/test/Analysis/LoopAccessAnalysis/max_safe_dep_dist_non_unit_stride.ll
index 54445c0182435..01c00bf09fa45 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/max_safe_dep_dist_non_unit_stride.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/max_safe_dep_dist_non_unit_stride.ll
@@ -11,7 +11,7 @@
 define void @foo(i64  %len, ptr %a) {
 ; CHECK-LABEL: 'foo'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            store i32 %0, ptr %arrayidx2, align 4 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll b/llvm/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll
index a338a339575a4..20da3ac6a2923 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/multiple-strides-rt-memory-checks.ll
@@ -29,7 +29,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 define void @Test(ptr nocapture %obj, i64 %z) #0 {
 ; CHECK-LABEL: 'Test'
 ; CHECK-NEXT:    .inner:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 2048 bits with run-time checks
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 64 with run-time checks
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:      Run-time memory checks:
 ; CHECK-NEXT:      Check 0:
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-distance-backward.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-distance-backward.ll
index b444c061c2632..a1045cf59175e 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-distance-backward.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-distance-backward.ll
@@ -79,7 +79,7 @@ exit:
 define void @backward_min_distance_120(ptr %A, i64 %N) {
 ; CHECK-LABEL: 'backward_min_distance_120'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 120 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 15
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %l = load i8, ptr %gep, align 4 ->
@@ -200,7 +200,7 @@ exit:
 define void @backward_min_distance_128(ptr %A, i64 %N) {
 ; CHECK-LABEL: 'backward_min_distance_128'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 128 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 16
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %l = load i8, ptr %gep, align 4 ->
@@ -321,7 +321,7 @@ exit:
 define void @backward_min_distance_256(ptr %A, i64 %N) {
 ; CHECK-LABEL: 'backward_min_distance_256'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 256 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 32
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %l = load i8, ptr %gep, align 4 ->
@@ -347,7 +347,7 @@ define void @backward_min_distance_256(ptr %A, i64 %N) {
 ;
 ; VW128-LABEL: 'backward_min_distance_256'
 ; VW128-NEXT:    loop:
-; VW128-NEXT:      Memory dependences are safe with a maximum safe vector width of 256 bits
+; VW128-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 32
 ; VW128-NEXT:      Dependences:
 ; VW128-NEXT:        BackwardVectorizable:
 ; VW128-NEXT:            %l = load i8, ptr %gep, align 4 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
index 76e2d30dcdc25..31d2c071885bb 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
@@ -78,7 +78,7 @@ exit:
 define void @different_non_constant_strides_known_backward_min_distance_16(ptr %A) {
 ; CHECK-LABEL: 'different_non_constant_strides_known_backward_min_distance_16'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %l = load i32, ptr %gep, align 4 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
index 0ad4d1b7bf3b9..40e70ea13520f 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
@@ -43,7 +43,7 @@ exit:
 define void @test_may_clobber1(ptr %p) {
 ; CHECK-LABEL: 'test_may_clobber1'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 6400 bits, with a maximum safe store-load forward width of 256 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 100, with a maximum safe store-load forward number of elements to operate on equal to 4
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %v = load i64, ptr %a1, align 32 ->
@@ -114,7 +114,7 @@ exit:
 define void @test_may_clobber3(ptr %p) {
 ; CHECK-LABEL: 'test_may_clobber3'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 640 bits, with a maximum safe store-load forward width of 128 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 10, with a maximum safe store-load forward number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %v = load i64, ptr %a1, align 32 ->
@@ -182,7 +182,7 @@ exit:
 define void @no_high_lmul_or_interleave(ptr %p) {
 ; CHECK-LABEL: 'no_high_lmul_or_interleave'
 ; CHECK-NEXT:    loop:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 65536 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 1024
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %v = load i64, ptr %a1, align 32 ->
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll
index 8e249b36f6445..d716df1f5ae76 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance.ll
@@ -4,7 +4,7 @@
 ;   for (i = 0; i < n; i++)
 ;    A[i + 4] = A[i] * 2;
 
-; CHECK: Memory dependences are safe with a maximum safe vector width of 64 bits, with a maximum safe store-load forward width of 64 bits
+; CHECK: Memory dependences are safe with a maximum safe number of elements to operate on equal to 4, with a maximum safe store-load forward number of elements to operate on equal to 4
 
 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-apple-macosx10.10.0"
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll b/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll
index 335ad67faee04..d80955f1afadd 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/stride-access-dependence.ll
@@ -276,7 +276,7 @@ for.body:                                         ; preds = %entry, %for.body
 define void @vectorizable_Read_Write(ptr nocapture %A) {
 ; CHECK-LABEL: 'vectorizable_Read_Write'
 ; CHECK-NEXT:    for.body:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits, with a maximum safe store-load forward width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2, with a maximum safe store-load forward number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            %0 = load i32, ptr %arrayidx, align 4 ->
@@ -323,7 +323,7 @@ for.body:                                         ; preds = %entry, %for.body
 define i32 @vectorizable_Write_Read(ptr nocapture %A) {
 ; CHECK-LABEL: 'vectorizable_Write_Read'
 ; CHECK-NEXT:    for.body:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            store i32 %0, ptr %arrayidx, align 4 ->
@@ -369,7 +369,7 @@ for.body:                                         ; preds = %entry, %for.body
 define void @vectorizable_Write_Write(ptr nocapture %A) {
 ; CHECK-LABEL: 'vectorizable_Write_Write'
 ; CHECK-NEXT:    for.body:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            store i32 %0, ptr %arrayidx, align 4 ->
@@ -464,7 +464,7 @@ for.body:                                         ; preds = %entry, %for.body
 define i32 @vectorizable_unscaled_Write_Read(ptr nocapture %A) {
 ; CHECK-LABEL: 'vectorizable_unscaled_Write_Read'
 ; CHECK-NEXT:    for.body:
-; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 64 bits
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe number of elements to operate on equal to 2
 ; CHECK-NEXT:      Dependences:
 ; CHECK-NEXT:        BackwardVectorizable:
 ; CHECK-NEXT:            store i32 %0, ptr %arrayidx, align 4 ->

>From 62e406a5b7eac32f76c705148351b9df168e2055 Mon Sep 17 00:00:00 2001
From: Andrei Elovikov <andrei.elovikov at sifive.com>
Date: Mon, 13 Apr 2026 11:13:18 -0700
Subject: [PATCH 4/4] Drop unexplainable "* 8"

---
 llvm/lib/Analysis/LoopAccessAnalysis.cpp                     | 5 ++---
 .../safe-with-dep-distance-non-power-of-2.ll                 | 2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 1971aa636032e..85a1cf93d975b 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -1926,9 +1926,8 @@ bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
   // cause any slowdowns.
   const uint64_t NumItersForStoreLoadThroughMemory = 8 * TypeByteSize;
   // Maximum vector factor.
-  // TODO: This "8" doesn't make any sense:
   uint64_t MaxVFWithoutSLForwardIssuesPowerOf2 = std::min<uint64_t>(
-      VectorizerParams::MaxVectorWidth, MaxStoreLoadForwardSafeNumElements * 8);
+      VectorizerParams::MaxVectorWidth, MaxStoreLoadForwardSafeNumElements);
 
   // Compute the smallest VF at which the store and load would be misaligned.
   for (uint64_t VF = 2; VF <= MaxVFWithoutSLForwardIssuesPowerOf2; VF *= 2) {
@@ -1950,7 +1949,7 @@ bool MemoryDepChecker::couldPreventStoreLoadForward(uint64_t Distance,
 
   if (CommonStride &&
       MaxVFWithoutSLForwardIssuesPowerOf2 <
-          MaxStoreLoadForwardSafeNumElements * 8 &&
+          MaxStoreLoadForwardSafeNumElements &&
       MaxVFWithoutSLForwardIssuesPowerOf2 != VectorizerParams::MaxVectorWidth) {
     uint64_t MaxVF = bit_floor(MaxVFWithoutSLForwardIssuesPowerOf2 *
                                TypeByteSize / CommonStride);
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
index 40e70ea13520f..e618401c90758 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/safe-with-dep-distance-non-power-of-2.ll
@@ -269,7 +269,7 @@ define void @two_store_load_forward_deps(ptr %A, ptr %B) {
 ; CHECK-NEXT:            %vb = load i32, ptr %b.ld, align 4 ->
 ; CHECK-NEXT:            store i32 %vb, ptr %b.st, align 4
 ; CHECK-EMPTY:
-; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:        BackwardVectorizableButPreventsForwarding:
 ; CHECK-NEXT:            %va = load i32, ptr %a.ld, align 4 ->
 ; CHECK-NEXT:            store i32 %va, ptr %a.st, align 4
 ; CHECK-EMPTY:



More information about the llvm-commits mailing list