[llvm] e90b123 - [LAA] Add additional tests for incorrect negative stride handling (NFC) (#218376)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 24 05:10:34 PDT 2026
Author: Florian Hahn
Date: 2026-08-24T12:10:29Z
New Revision: e90b123a872630f1b26d5507e05227a2447e4189
URL: https://github.com/llvm/llvm-project/commit/e90b123a872630f1b26d5507e05227a2447e4189
DIFF: https://github.com/llvm/llvm-project/commit/e90b123a872630f1b26d5507e05227a2447e4189.diff
LOG: [LAA] Add additional tests for incorrect negative stride handling (NFC) (#218376)
Added:
llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
Modified:
llvm/test/Analysis/LoopAccessAnalysis/evaluate-at-symbolic-max-backedge-taken-count-may-wrap.ll
llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
Removed:
################################################################################
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll b/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
new file mode 100644
index 0000000000000..f58c7cf587ff6
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/all-ones-null-pointer.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "po1:64:64"
+
+; Tests with an address space that has an all-ones nullptr.
+
+; The step is negative and evaluating at the symbolic max BTC may wrap, so the
+; lowest accessed address is unknown and no runtime checks can be formed.
+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: 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:
+; CHECK-EMPTY:
+; CHECK-NEXT: Expressions re-written:
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr addrspace(1) [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr addrspace(1) %S
+ store i32 %l, ptr addrspace(1) %ptr.iv, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr addrspace(1) %ptr.iv, i32 -4
+ %iv.next = add nsw i32 %iv, 1
+ %c.2 = icmp slt i32 %iv.next, %l
+ br i1 %c.2, label %loop, label %exit
+
+exit:
+ ret void
+}
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 e319c89577e24..ebbb435bc2264 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
@@ -177,3 +177,185 @@ loop:
exit:
ret void
}
+
+; 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:
+; CHECK-NEXT: Memory dependences are safe with run-time checks
+; 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> 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:
+; CHECK-EMPTY:
+; CHECK-NEXT: Expressions re-written:
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr %S
+ store i32 %l, ptr %ptr.iv, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i32 -4
+ %iv.next = add nsw i32 %iv, 1
+ %c.2 = icmp slt i32 %iv.next, %l
+ br i1 %c.2, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; 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:
+; CHECK-NEXT: Memory dependences are safe with run-time checks
+; 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,+,(-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))
+; CHECK-NEXT: Member: %S
+; 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:
+ %step.masked = and i32 %step, 65535
+ %step.neg = sub i32 -1, %step.masked
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr %S
+ store i32 %l, ptr %ptr.iv, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i32 %step.neg
+ %iv.next = add nsw i32 %iv, 1
+ %c.2 = icmp slt i32 %iv.next, %l
+ br i1 %c.2, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; 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:
+; CHECK-NEXT: Memory dependences are safe with run-time checks
+; 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,+,(zext i16 (trunc i32 %step to i16) to i32)}<nuw><%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:
+; CHECK-EMPTY:
+; CHECK-NEXT: Expressions re-written:
+;
+entry:
+ %step.masked = and i32 %step, 65535
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr %S
+ store i32 %l, ptr %ptr.iv, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i32 %step.masked
+ %iv.next = add nsw i32 %iv, 1
+ %c.2 = icmp slt i32 %iv.next, %l
+ br i1 %c.2, label %loop, label %exit
+
+exit:
+ ret void
+}
+
+; The step direction is unknown, so neither end of the accessed range is known
+; when evaluating at the symbolic max BTC.
+; FIXME: Currently the bounds are incorrect.
+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: 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:
+; CHECK-EMPTY:
+; CHECK-NEXT: Expressions re-written:
+;
+entry:
+ %step = add i32 %step.a, %step.b
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr %S
+ store i32 %l, ptr %ptr.iv, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i32 %step
+ %iv.next = add nsw i32 %iv, 1
+ %c.2 = icmp slt i32 %iv.next, %l
+ br i1 %c.2, label %loop, label %exit
+
+exit:
+ ret void
+}
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 3a5730eb471ed..ad0467fc6b734 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
@@ -246,3 +246,43 @@ loop:
exit:
ret void
}
+
+; The bounds of the second pointer of the forked store cannot be computed: the
+; step direction is unknown and evaluating at the symbolic max BTC may wrap. The
+; store must not be inserted partially.
+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: 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-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:
+ %step = add i32 %step.a, %step.b
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %P, %entry ], [ %ptr.iv.next, %loop ]
+ %l = load i32, ptr %S, align 4
+ %select = select i1 %c, ptr %S, ptr %ptr.iv
+ store i32 %l, ptr %select, align 4
+ %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i32 %step
+ %iv.next = add nsw i32 %iv, 1
+ %ec = icmp slt i32 %iv.next, %l
+ br i1 %ec, label %loop, label %exit
+
+exit:
+ ret void
+}
More information about the llvm-commits
mailing list