[llvm] 977c0a6 - [LAA] Add tests with non-constant strides & distances.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 8 11:19:04 PDT 2024
Author: Florian Hahn
Date: 2024-04-08T19:18:38+01:00
New Revision: 977c0a6d29fe836f75b64a6f08a58cb3c00a56d9
URL: https://github.com/llvm/llvm-project/commit/977c0a6d29fe836f75b64a6f08a58cb3c00a56d9
DIFF: https://github.com/llvm/llvm-project/commit/977c0a6d29fe836f75b64a6f08a58cb3c00a56d9.diff
LOG: [LAA] Add tests with non-constant strides & distances.
Add a number of LAA test cases with both forward and backward
dependences with non-constant strides and dependence distances.
This includes test coverage for
https://github.com/llvm/llvm-project/issues/87336
Also includes a LoopLoadElimination test to make sure the pass does not
crash on non-constant dependence distances.
Added:
llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll
llvm/test/Analysis/LoopAccessAnalysis/positive-dependence-distance-different-access-sizes.ll
llvm/test/Transforms/LoopLoadElim/non-const-distance.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
new file mode 100644
index 00000000000000..416742a94e0d36
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-backward.ll
@@ -0,0 +1,369 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+declare void @llvm.assume(i1)
+
+define void @
diff erent_non_constant_strides_known_backward(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_distance_larger_than_trip_count(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_distance_larger_than_trip_count'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ %A.1024 = getelementptr inbounds i8, ptr %A, i64 1024
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.1024, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_min_distance_16(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_min_distance_16'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ %A.16 = getelementptr inbounds i8, ptr %A, i64 16
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.16, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_min_distance_15(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_min_distance_15'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ %A.15 = getelementptr inbounds i8, ptr %A, i64 15
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.15, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_min_distance_8(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_min_distance_8'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ %A.8 = getelementptr inbounds i8, ptr %A, i64 8
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.8, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_min_distance_3(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_min_distance_3'
+; 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: %l = load i32, ptr %gep, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, 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:
+ %A.3 = getelementptr inbounds i8, ptr %A, i64 3
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_via_assume(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_via_assume'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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:
+ %c = icmp sgt i64 %scale, 0
+ call void @llvm.assume(i1 %c)
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_via_assume_distance_larger_than_trip_count(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_via_assume_distance_larger_than_trip_count'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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:
+ %A.1024 = getelementptr inbounds i8, ptr %A, i64 1024
+ %c = icmp sgt i64 %scale, 0
+ call void @llvm.assume(i1 %c)
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.1024, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_backward_via_assume_min_distance_3(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_backward_via_assume_min_distance_3'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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:
+ %A.3 = getelementptr inbounds i8, ptr %A, i64 3
+ %c = icmp sgt i64 %scale, 0
+ call void @llvm.assume(i1 %c)
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_not_known_backward(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_not_known_backward'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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 ]
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ %l = load i32, ptr %gep, align 4
+ %add = add nsw i32 %l, 5
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ store i32 %add, ptr %gep.mul.2, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll
new file mode 100644
index 00000000000000..aa22a2143352d2
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll
@@ -0,0 +1,182 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+declare void @llvm.assume(i1)
+
+define void @
diff erent_non_constant_strides_known_forward(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_forward'
+; 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: %l = load i32, ptr %gep.mul.2, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep, 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:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ %l = load i32, ptr %gep.mul.2, align 4
+ %add = add nsw i32 %l, 5
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ store i32 %add, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_forward_min_distance_3(ptr %A) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_forward_min_distance_3'
+; 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: %l = load i32, ptr %gep.mul.2, align 4 ->
+; CHECK-NEXT: store i32 %add, ptr %gep, 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:
+ %A.3 = getelementptr inbounds i8, ptr %A, i64 3
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.mul.2 = shl nuw nsw i64 %iv, 1
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
+ %l = load i32, ptr %gep.mul.2, align 4
+ %add = add nsw i32 %l, 5
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ store i32 %add, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_forward_via_assume(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_forward_via_assume'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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:
+ %c = icmp sgt i64 %scale, 0
+ call void @llvm.assume(i1 %c)
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ %l = load i32, ptr %gep.mul.2, align 4
+ %add = add nsw i32 %l, 5
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ store i32 %add, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_known_forward_via_assume_min_distance_3(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_known_forward_via_assume_min_distance_3'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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:
+ %A.3 = getelementptr inbounds i8, ptr %A, i64 3
+ %c = icmp sgt i64 %scale, 0
+ call void @llvm.assume(i1 %c)
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
+ %l = load i32, ptr %gep.mul.2, align 4
+ %add = add nsw i32 %l, 5
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ store i32 %add, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @
diff erent_non_constant_strides_not_known_forward(ptr %A, i64 %scale) {
+; CHECK-LABEL: '
diff erent_non_constant_strides_not_known_forward'
+; CHECK-NEXT: loop:
+; CHECK-NEXT: Report: cannot identify array bounds
+; CHECK-NEXT: Dependences:
+; 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 ]
+ %iv.mul.2 = shl nuw nsw i64 %iv, %scale
+ %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
+ %l = load i32, ptr %gep.mul.2, align 4
+ %add = add nsw i32 %l, 5
+ %gep = getelementptr inbounds i32, ptr %A, i64 %iv
+ store i32 %add, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond.not = icmp eq i64 %iv.next, 256
+ br i1 %exitcond.not, label %exit, label %loop
+
+exit:
+ ret void
+}
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/positive-dependence-distance-
diff erent-access-sizes.ll b/llvm/test/Analysis/LoopAccessAnalysis/positive-dependence-distance-
diff erent-access-sizes.ll
new file mode 100644
index 00000000000000..08e0bae7f05bac
--- /dev/null
+++ b/llvm/test/Analysis/LoopAccessAnalysis/positive-dependence-distance-
diff erent-access-sizes.ll
@@ -0,0 +1,141 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+; TODO: No runtime checks should be needed, as the distance between accesses
+; is large enough to need runtime checks.
+define void @test_distance_positive_independent_via_trip_count(ptr %A) {
+; CHECK-LABEL: 'test_distance_positive_independent_via_trip_count'
+; 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 ([[GRP1:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A.400 = getelementptr inbounds i32, ptr %A.400, i64 %iv
+; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+; CHECK-NEXT: Grouped accesses:
+; CHECK-NEXT: Group [[GRP1]]:
+; CHECK-NEXT: (Low: (400 + %A)<nuw> High: (804 + %A))
+; CHECK-NEXT: Member: {(400 + %A)<nuw>,+,4}<nuw><%loop>
+; CHECK-NEXT: Group [[GRP2]]:
+; CHECK-NEXT: (Low: %A High: (101 + %A))
+; CHECK-NEXT: Member: {%A,+,1}<nuw><%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:
+ %A.400 = getelementptr inbounds i8, ptr %A, i64 400
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep.A.400 = getelementptr inbounds i32, ptr %A.400, i64 %iv
+ %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+ %l = load i8, ptr %gep.A, align 1
+ %ext = zext i8 %l to i32
+ store i32 %ext, ptr %gep.A.400, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %ec = icmp eq i64 %iv, 100
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+; TODO: Currently this is considered vectorizable with runtime checks, but the
+; runtime checks are never true.
+define void @test_distance_positive_backwards(ptr %A) {
+; CHECK-LABEL: 'test_distance_positive_backwards'
+; 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 ([[GRP3:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A.400 = getelementptr inbounds i32, ptr %A.1, i64 %iv
+; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+; CHECK-NEXT: Grouped accesses:
+; CHECK-NEXT: Group [[GRP3]]:
+; CHECK-NEXT: (Low: (1 + %A)<nuw> High: (405 + %A))
+; CHECK-NEXT: Member: {(1 + %A)<nuw>,+,4}<nuw><%loop>
+; CHECK-NEXT: Group [[GRP4]]:
+; CHECK-NEXT: (Low: %A High: (101 + %A))
+; CHECK-NEXT: Member: {%A,+,1}<nuw><%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:
+ %A.1 = getelementptr inbounds i8, ptr %A, i64 1
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep.A.400 = getelementptr inbounds i32, ptr %A.1, i64 %iv
+ %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+ %l = load i8, ptr %gep.A, align 1
+ %ext = zext i8 %l to i32
+ store i32 %ext, ptr %gep.A.400, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %ec = icmp eq i64 %iv, 100
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @test_distance_positive_via_assume(ptr %A, i64 %off) {
+; CHECK-LABEL: 'test_distance_positive_via_assume'
+; 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 ([[GRP5:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A.400 = getelementptr inbounds i32, ptr %A.off, i64 %iv
+; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+; CHECK-NEXT: Grouped accesses:
+; CHECK-NEXT: Group [[GRP5]]:
+; CHECK-NEXT: (Low: (%off + %A) High: (404 + %off + %A))
+; CHECK-NEXT: Member: {(%off + %A),+,4}<nw><%loop>
+; CHECK-NEXT: Group [[GRP6]]:
+; CHECK-NEXT: (Low: %A High: (101 + %A))
+; CHECK-NEXT: Member: {%A,+,1}<nuw><%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:
+ %c = icmp sgt i64 %off, 0
+ call void @llvm.assume(i1 %c)
+ %A.off = getelementptr inbounds i8, ptr %A, i64 %off
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep.A.400 = getelementptr inbounds i32, ptr %A.off, i64 %iv
+ %gep.A = getelementptr inbounds i8, ptr %A, i64 %iv
+ %l = load i8, ptr %gep.A, align 1
+ %ext = zext i8 %l to i32
+ store i32 %ext, ptr %gep.A.400, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %ec = icmp eq i64 %iv, 100
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+declare void @llvm.assume(i1)
diff --git a/llvm/test/Transforms/LoopLoadElim/non-const-distance.ll b/llvm/test/Transforms/LoopLoadElim/non-const-distance.ll
new file mode 100644
index 00000000000000..b97d4c23c73d19
--- /dev/null
+++ b/llvm/test/Transforms/LoopLoadElim/non-const-distance.ll
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes=loop-load-elim -S %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+define void @non_const_distance(i64 %start, ptr %A, i1 %c) {
+; CHECK-LABEL: define void @non_const_distance(
+; CHECK-SAME: i64 [[START:%.*]], ptr [[A:%.*]], i1 [[C:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i64 1, i64 0
+; CHECK-NEXT: [[SEL_NOT:%.*]] = xor i64 [[SEL]], -1
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr i32, ptr [[PTR_IV]], i64 [[SEL_NOT]]
+; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[ADD_PTR]], align 4
+; CHECK-NEXT: store i32 [[L]], ptr [[PTR_IV]], align 4
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr i8, ptr [[PTR_IV]], i64 4
+; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV]], 1000
+; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %sel = select i1 %c, i64 1, i64 0
+ %sel.not = xor i64 %sel, -1
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
+ %ptr.iv = phi ptr [ %A, %entry ], [ %ptr.iv.next, %loop ]
+ %add.ptr = getelementptr i32, ptr %ptr.iv, i64 %sel.not
+ %l = load i32, ptr %add.ptr, align 4
+ store i32 %l, ptr %ptr.iv, align 4
+ %iv.next = add i64 %iv, 1
+ %ptr.iv.next = getelementptr i8, ptr %ptr.iv, i64 4
+ %ec = icmp eq i64 %iv, 1000
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ ret void
+}
More information about the llvm-commits
mailing list