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