1; RUN: opt -loop-vectorize -mtriple=arm64-apple-iphoneos -vectorizer-min-trip-count=8 -S %s | FileCheck --check-prefixes=CHECK,DEFAULT %s
2; RUN: opt -loop-vectorize -mtriple=arm64-apple-iphoneos -vectorizer-min-trip-count=8 -vectorize-memory-check-threshold=1 -S %s | FileCheck --check-prefixes=CHECK,THRESHOLD %s
3
4; Tests for loops with large numbers of runtime checks. Check that loops are
5; vectorized, if the loop trip counts are large and the impact of the runtime
6; checks is very small compared to the expected loop runtimes.
7
8
9; The trip count in the loop in this function is too to warrant large runtime checks.
10; CHECK-LABEL: define {{.*}} @test_tc_too_small
11; CHECK-NOT: vector.memcheck
12; CHECK-NOT: vector.body
13define void @test_tc_too_small(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2) {
14entry:
15  br label %loop
16
17loop:                                             ; preds = %bb54, %bb37
18  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
19  %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv
20  %lv.1 = load i16, i16* %gep.1, align 2
21  %ext.1 = sext i16 %lv.1 to i32
22  %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv
23  %lv.2 = load i16, i16* %gep.2, align 2
24  %ext.2 = sext i16 %lv.2 to i32
25  %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1
26  %lv.3 = load i16, i16* %gep.off.1, align 2
27  %ext.3 = sext i16 %lv.3 to i32
28  %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2
29  %lv.4 = load i16, i16* %gep.off.2, align 2
30  %ext.4 = sext i16 %lv.4 to i32
31  %tmp62 = mul nsw i32 %ext.2, 11
32  %tmp66 = mul nsw i32 %ext.3, -4
33  %tmp70 = add nsw i32 %tmp62, 4
34  %tmp71 = add nsw i32 %tmp70, %tmp66
35  %tmp72 = add nsw i32 %tmp71, %ext.4
36  %tmp73 = lshr i32 %tmp72, 3
37  %tmp74 = add nsw i32 %tmp73, %ext.1
38  %tmp75 = lshr i32 %tmp74, 1
39  %tmp76 = mul nsw i32 %ext.2, 5
40  %tmp77 = shl nsw i32 %ext.3, 2
41  %tmp78 = add nsw i32 %tmp76, 4
42  %tmp79 = add nsw i32 %tmp78, %tmp77
43  %tmp80 = sub nsw i32 %tmp79, %ext.4
44  %tmp81 = lshr i32 %tmp80, 3
45  %tmp82 = sub nsw i32 %tmp81, %ext.1
46  %tmp83 = lshr i32 %tmp82, 1
47  %trunc.1 = trunc i32 %tmp75 to i16
48  %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv
49  store i16 %trunc.1, i16* %gep.3, align 2
50  %trunc.2 = trunc i32 %tmp83 to i16
51  %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv
52  store i16 %trunc.2, i16* %gep.4, align 2
53  %iv.next = add nuw nsw i64 %iv, 1
54  %cmp = icmp ult i64 %iv, 10
55  br i1 %cmp, label %loop, label %exit
56
57exit:
58  ret void
59}
60
61; The trip count in the loop in this function high enough to warrant large runtime checks.
62; CHECK-LABEL: define {{.*}} @test_tc_big_enough
63; DEFAULT: vector.memcheck
64; DEFAULT: vector.body
65; THRESHOLD-NOT: vector.memcheck
66; THRESHOLD-NOT: vector.body
67;
68define void @test_tc_big_enough(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2) {
69entry:
70  br label %loop
71
72loop:                                             ; preds = %bb54, %bb37
73  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
74  %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv
75  %lv.1 = load i16, i16* %gep.1, align 2
76  %ext.1 = sext i16 %lv.1 to i32
77  %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv
78  %lv.2 = load i16, i16* %gep.2, align 2
79  %ext.2 = sext i16 %lv.2 to i32
80  %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1
81  %lv.3 = load i16, i16* %gep.off.1, align 2
82  %ext.3 = sext i16 %lv.3 to i32
83  %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2
84  %lv.4 = load i16, i16* %gep.off.2, align 2
85  %ext.4 = sext i16 %lv.4 to i32
86  %tmp62 = mul nsw i32 %ext.2, 11
87  %tmp66 = mul nsw i32 %ext.3, -4
88  %tmp70 = add nsw i32 %tmp62, 4
89  %tmp71 = add nsw i32 %tmp70, %tmp66
90  %tmp72 = add nsw i32 %tmp71, %ext.4
91  %tmp73 = lshr i32 %tmp72, 3
92  %tmp74 = add nsw i32 %tmp73, %ext.1
93  %tmp75 = lshr i32 %tmp74, 1
94  %tmp76 = mul nsw i32 %ext.2, 5
95  %tmp77 = shl nsw i32 %ext.3, 2
96  %tmp78 = add nsw i32 %tmp76, 4
97  %tmp79 = add nsw i32 %tmp78, %tmp77
98  %tmp80 = sub nsw i32 %tmp79, %ext.4
99  %tmp81 = lshr i32 %tmp80, 3
100  %tmp82 = sub nsw i32 %tmp81, %ext.1
101  %tmp83 = lshr i32 %tmp82, 1
102  %trunc.1 = trunc i32 %tmp75 to i16
103  %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv
104  store i16 %trunc.1, i16* %gep.3, align 2
105  %trunc.2 = trunc i32 %tmp83 to i16
106  %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv
107  store i16 %trunc.2, i16* %gep.4, align 2
108  %iv.next = add nuw nsw i64 %iv, 1
109  %cmp = icmp ult i64 %iv, 500
110  br i1 %cmp, label %loop, label %exit
111
112exit:
113  ret void
114}
115
116define void @test_tc_unknown(i16* %ptr.1, i16* %ptr.2, i16* %ptr.3, i16* %ptr.4, i64 %off.1, i64 %off.2, i64 %N) {
117; CHECK-LABEL: define void @test_tc_unknown
118; DEFAULT:       [[ADD:%.+]] = add i64 %N, 1
119; DEFAULT-NEXT:  [[C:%.+]] = icmp ult i64 [[ADD]], 16
120; DEFAULT-NEXT:  br i1 [[C]], label %scalar.ph, label %vector.memcheck
121; THRESHOLD-NOT: vector.memcheck
122; THRESHOLD-NOT: vector.body
123;
124entry:
125  br label %loop
126
127loop:                                             ; preds = %bb54, %bb37
128  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
129  %gep.1 = getelementptr inbounds i16, i16* %ptr.1, i64 %iv
130  %lv.1 = load i16, i16* %gep.1, align 2
131  %ext.1 = sext i16 %lv.1 to i32
132  %gep.2 = getelementptr inbounds i16, i16* %ptr.2, i64 %iv
133  %lv.2 = load i16, i16* %gep.2, align 2
134  %ext.2 = sext i16 %lv.2 to i32
135  %gep.off.1 = getelementptr inbounds i16, i16* %gep.2, i64 %off.1
136  %lv.3 = load i16, i16* %gep.off.1, align 2
137  %ext.3 = sext i16 %lv.3 to i32
138  %gep.off.2 = getelementptr inbounds i16, i16* %gep.2, i64 %off.2
139  %lv.4 = load i16, i16* %gep.off.2, align 2
140  %ext.4 = sext i16 %lv.4 to i32
141  %tmp62 = mul nsw i32 %ext.2, 11
142  %tmp66 = mul nsw i32 %ext.3, -4
143  %tmp70 = add nsw i32 %tmp62, 4
144  %tmp71 = add nsw i32 %tmp70, %tmp66
145  %tmp72 = add nsw i32 %tmp71, %ext.4
146  %tmp73 = lshr i32 %tmp72, 3
147  %tmp74 = add nsw i32 %tmp73, %ext.1
148  %tmp75 = lshr i32 %tmp74, 1
149  %tmp76 = mul nsw i32 %ext.2, 5
150  %tmp77 = shl nsw i32 %ext.3, 2
151  %tmp78 = add nsw i32 %tmp76, 4
152  %tmp79 = add nsw i32 %tmp78, %tmp77
153  %tmp80 = sub nsw i32 %tmp79, %ext.4
154  %tmp81 = lshr i32 %tmp80, 3
155  %tmp82 = sub nsw i32 %tmp81, %ext.1
156  %tmp83 = lshr i32 %tmp82, 1
157  %trunc.1 = trunc i32 %tmp75 to i16
158  %gep.3 = getelementptr inbounds i16, i16* %ptr.3, i64 %iv
159  store i16 %trunc.1, i16* %gep.3, align 2
160  %trunc.2 = trunc i32 %tmp83 to i16
161  %gep.4 = getelementptr inbounds i16, i16* %ptr.4, i64 %iv
162  store i16 %trunc.2, i16* %gep.4, align 2
163  %iv.next = add nuw nsw i64 %iv, 1
164  %cmp = icmp ult i64 %iv, %N
165  br i1 %cmp, label %loop, label %exit
166
167exit:
168  ret void
169}
170