[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