[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