[llvm] [LAA] Properly report strided access preventing store-to-load forwarding (PR #208791)

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


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

>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/2] 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/2] [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:



More information about the llvm-commits mailing list