[llvm] d749095 - [LAA] Add tests where we could derive NoDep due to no overlap.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 14 07:48:52 PDT 2025


Author: Florian Hahn
Date: 2025-07-14T15:48:41+01:00
New Revision: d749095b94e7b0361f224e6291cb2d5c6d2f366b

URL: https://github.com/llvm/llvm-project/commit/d749095b94e7b0361f224e6291cb2d5c6d2f366b
DIFF: https://github.com/llvm/llvm-project/commit/d749095b94e7b0361f224e6291cb2d5c6d2f366b.diff

LOG: [LAA] Add tests where we could derive NoDep due to no overlap.

Add additional tests where we can prove that the accesses are either
completely before or after each other.

Added: 
    llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll b/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll
new file mode 100644
index 0000000000000..92886e36a7081
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/accesses-completely-before-or-after.ll
@@ -0,0 +1,319 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes="print<access-info>" -disable-output %s 2>&1 | FileCheck %s
+
+define i32 @completely_before_or_after_true_dep_
diff erent_size(ptr %d) {
+; CHECK-LABEL: 'completely_before_or_after_true_dep_
diff erent_size'
+; 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:          %gep.128.iv = getelementptr i64, ptr %gep.128, i64 %iv
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %gep.iv = getelementptr i32, ptr %d, i64 %iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: (128 + %d) High: (384 + %d))
+; CHECK-NEXT:            Member: {(128 + %d),+,8}<nw><%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: %d High: (128 + %d))
+; CHECK-NEXT:            Member: {%d,+,4}<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:
+  %gep.128 = getelementptr i8, ptr %d, i64 128
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %gep.128.iv = getelementptr i64, ptr %gep.128, i64 %iv
+  store i64 0, ptr %gep.128.iv, align 8
+  %gep.iv = getelementptr i32, ptr %d, i64 %iv
+  %l = load i32, ptr %gep.iv, align 4
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 32
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret i32 %l
+}
+
+define i32 @may_overlap_true_dep_
diff erent_size(ptr %d) {
+; CHECK-LABEL: 'may_overlap_true_dep_
diff erent_size'
+; 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:          %gep.128.iv = getelementptr i64, ptr %gep.128, i64 %iv
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %gep.iv = getelementptr i32, ptr %d, i64 %iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: (127 + %d) High: (383 + %d))
+; CHECK-NEXT:            Member: {(127 + %d),+,8}<nw><%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: %d High: (128 + %d))
+; CHECK-NEXT:            Member: {%d,+,4}<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:
+  %gep.128 = getelementptr i8, ptr %d, i64 127
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %gep.128.iv = getelementptr i64, ptr %gep.128, i64 %iv
+  store i64 0, ptr %gep.128.iv, align 8
+  %gep.iv= getelementptr i32, ptr %d, i64 %iv
+  %l = load i32, ptr %gep.iv, align 4
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 32
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret i32 %l
+}
+
+define void @completely_after_stores_with_
diff erent_sizes(ptr %dst) {
+; CHECK-LABEL: 'completely_after_stores_with_
diff erent_sizes'
+; 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:          %gep.iv = getelementptr i16, ptr %dst, i64 %iv
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %gep.dst.128.iv = getelementptr i8, ptr %gep.dst.128, i64 %iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: %dst High: (128 + %dst)<nuw>)
+; CHECK-NEXT:            Member: {%dst,+,2}<nw><%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: (128 + %dst)<nuw> High: (192 + %dst))
+; CHECK-NEXT:            Member: {(128 + %dst)<nuw>,+,1}<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:
+  %gep.dst.128 = getelementptr nuw i8, ptr %dst, i64 128
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %gep.iv = getelementptr i16, ptr %dst, i64 %iv
+  store i16 0, ptr %gep.iv, align 2
+  %gep.dst.128.iv = getelementptr i8, ptr %gep.dst.128, i64 %iv
+  store i8 0, ptr %gep.dst.128.iv, align 1
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 64
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+
+define void @may_overlap_stores_with_
diff erent_sizes(ptr %dst) {
+; CHECK-LABEL: 'may_overlap_stores_with_
diff erent_sizes'
+; 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:          %gep.iv = getelementptr i16, ptr %dst, i64 %iv
+; CHECK-NEXT:        Against group GRP1:
+; CHECK-NEXT:          %gep.dst.128.iv = getelementptr i8, ptr %gep.dst.128, i64 %iv
+; CHECK-NEXT:      Grouped accesses:
+; CHECK-NEXT:        Group GRP0:
+; CHECK-NEXT:          (Low: %dst High: (130 + %dst))
+; CHECK-NEXT:            Member: {%dst,+,2}<nw><%loop>
+; CHECK-NEXT:        Group GRP1:
+; CHECK-NEXT:          (Low: (128 + %dst)<nuw> High: (193 + %dst))
+; CHECK-NEXT:            Member: {(128 + %dst)<nuw>,+,1}<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:
+  %gep.dst.128 = getelementptr nuw i8, ptr %dst, i64 128
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %gep.iv = getelementptr i16, ptr %dst, i64 %iv
+  store i16 0, ptr %gep.iv, align 2
+  %gep.dst.128.iv = getelementptr i8, ptr %gep.dst.128, i64 %iv
+  store i8 0, ptr %gep.dst.128.iv, align 1
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 65
+  br i1 %ec, label %exit, label %loop
+
+exit:                            ; preds = %loop
+  ret void
+}
+
+define void @completely_before_or_after_non_const_distance(ptr %dst) {
+; CHECK-LABEL: 'completely_before_or_after_non_const_distance'
+; 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:  Unknown data dependence.
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:        Unknown:
+; CHECK-NEXT:            store i32 0, ptr %gep.iv.mul, align 4 ->
+; CHECK-NEXT:            store i32 0, ptr %gep.off.iv, 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:
+  %gep.off = getelementptr i8, ptr %dst, i64 576
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %iv.mul = mul i64 %iv, 84
+  %gep.404 = getelementptr i8, ptr %dst, i64 404
+  %gep.iv.mul = getelementptr i8, ptr %gep.404, i64 %iv.mul
+  store i32 0, ptr %gep.iv.mul, align 4
+  %gep.off.iv = getelementptr i32, ptr %gep.off, i64 %iv
+  store i32 0, ptr %gep.off.iv, align 4
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 3
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+define void @overlap_non_const_distance(ptr %dst) {
+; CHECK-LABEL: 'overlap_non_const_distance'
+; 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:  Unknown data dependence.
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:        Unknown:
+; CHECK-NEXT:            store i32 0, ptr %gep.iv.mul, align 4 ->
+; CHECK-NEXT:            store i32 0, ptr %gep.off.iv, 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:
+  %gep.off = getelementptr i8, ptr %dst, i64 575
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %iv.mul = mul i64 %iv, 84
+  %gep.404 = getelementptr i8, ptr %dst, i64 404
+  %gep.iv.mul = getelementptr i8, ptr %gep.404, i64 %iv.mul
+  store i32 0, ptr %gep.iv.mul, align 4
+  %gep.off.iv = getelementptr i32, ptr %gep.off, i64 %iv
+  store i32 0, ptr %gep.off.iv, align 4
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv.next, 3
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+define void @accesses_completely_before_or_after_instead_backwards_vectorizable(ptr dereferenceable(800) %dst) {
+; CHECK-LABEL: 'accesses_completely_before_or_after_instead_backwards_vectorizable'
+; CHECK-NEXT:    loop:
+; CHECK-NEXT:      Memory dependences are safe with a maximum safe vector width of 128 bits
+; CHECK-NEXT:      Dependences:
+; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:            store i16 0, ptr %gep.mul.2, align 2 ->
+; CHECK-NEXT:            store i16 0, ptr %gep.iv.32, align 2
+; 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:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %mul.2 = shl i64 %iv, 1
+  %gep.mul.2 = getelementptr i16, ptr %dst, i64 %mul.2
+  store i16 0, ptr %gep.mul.2, align 2
+  %iv.32 = add i64 %iv, 32
+  %gep.iv.32 = getelementptr i16, ptr %dst, i64 %iv.32
+  store i16 0, ptr %gep.iv.32, align 2
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv, 15
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+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:      Dependences:
+; CHECK-NEXT:        BackwardVectorizable:
+; CHECK-NEXT:            store i16 0, ptr %gep.mul.2, align 2 ->
+; CHECK-NEXT:            store i16 0, ptr %gep.iv.32, align 2
+; 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:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %mul.2 = shl i64 %iv, 1
+  %gep.mul.2 = getelementptr i16, ptr %dst, i64 %mul.2
+  store i16 0, ptr %gep.mul.2, align 2
+  %iv.32 = add i64 %iv, 32
+  %gep.iv.32 = getelementptr i16, ptr %dst, i64 %iv.32
+  store i16 0, ptr %gep.iv.32, align 2
+  %iv.next = add i64 %iv, 1
+  %ec = icmp eq i64 %iv, 16
+  br i1 %ec, label %exit, label %loop
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list