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