1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
3 ; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
5 declare void @llvm.experimental.guard(i1, ...)
7 define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
8 ; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check(
10 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
11 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
12 ; CHECK: loop.preheader:
13 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
14 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
15 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
16 ; CHECK-NEXT: br label [[LOOP:%.*]]
18 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
19 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
20 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
21 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
22 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
23 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
24 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
25 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
26 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
27 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
28 ; CHECK: exit.loopexit:
29 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
30 ; CHECK-NEXT: br label [[EXIT]]
32 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
33 ; CHECK-NEXT: ret i32 [[RESULT]]
36 %tmp5 = icmp eq i32 %n, 0
37 br i1 %tmp5, label %exit, label %loop.preheader
43 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
44 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
45 %within.bounds = icmp ult i32 %i, %length
46 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
48 %i.i64 = zext i32 %i to i64
49 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
50 %array.i = load i32, i32* %array.i.ptr, align 4
51 %loop.acc.next = add i32 %loop.acc, %array.i
53 %i.next = add nuw i32 %i, 1
54 %continue = icmp ult i32 %i.next, %n
55 br i1 %continue, label %loop, label %exit
58 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
62 define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) {
63 ; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check(
65 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
66 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
67 ; CHECK: loop.preheader:
68 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]]
69 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
70 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
71 ; CHECK-NEXT: br label [[LOOP:%.*]]
73 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
74 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
75 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
76 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
77 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
78 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
79 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
80 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
81 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]]
82 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
83 ; CHECK: exit.loopexit:
84 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
85 ; CHECK-NEXT: br label [[EXIT]]
87 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
88 ; CHECK-NEXT: ret i32 [[RESULT]]
91 %tmp5 = icmp eq i32 %n, 0
92 br i1 %tmp5, label %exit, label %loop.preheader
98 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
99 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
100 %within.bounds = icmp ult i32 %i, %length
101 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
103 %i.i64 = zext i32 %i to i64
104 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
105 %array.i = load i32, i32* %array.i.ptr, align 4
106 %loop.acc.next = add i32 %loop.acc, %array.i
108 %i.next = add nuw i32 %i, 1
109 %continue = icmp ule i32 %i.next, %n
110 br i1 %continue, label %loop, label %exit
113 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
117 define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) {
118 ; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check(
120 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
121 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
122 ; CHECK: loop.preheader:
123 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
124 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
125 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
126 ; CHECK-NEXT: br label [[LOOP:%.*]]
128 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
129 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
130 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
131 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
132 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
133 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
134 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
135 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
136 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
137 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
138 ; CHECK: exit.loopexit:
139 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
140 ; CHECK-NEXT: br label [[EXIT]]
142 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
143 ; CHECK-NEXT: ret i32 [[RESULT]]
146 %tmp5 = icmp eq i32 %n, 0
147 br i1 %tmp5, label %exit, label %loop.preheader
153 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
154 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
155 %within.bounds = icmp ugt i32 %length, %i
156 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
158 %i.i64 = zext i32 %i to i64
159 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
160 %array.i = load i32, i32* %array.i.ptr, align 4
161 %loop.acc.next = add i32 %loop.acc, %array.i
163 %i.next = add nuw i32 %i, 1
164 %continue = icmp ult i32 %i.next, %n
165 br i1 %continue, label %loop, label %exit
168 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
172 define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) {
173 ; CHECK-LABEL: @signed_loop_0_to_n_ult_check(
175 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
176 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
177 ; CHECK: loop.preheader:
178 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
179 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
180 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
181 ; CHECK-NEXT: br label [[LOOP:%.*]]
183 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
184 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
185 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
186 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
187 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
188 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
189 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
190 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
191 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
192 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
193 ; CHECK: exit.loopexit:
194 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
195 ; CHECK-NEXT: br label [[EXIT]]
197 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
198 ; CHECK-NEXT: ret i32 [[RESULT]]
201 %tmp5 = icmp sle i32 %n, 0
202 br i1 %tmp5, label %exit, label %loop.preheader
208 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
209 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
210 %within.bounds = icmp ult i32 %i, %length
211 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
213 %i.i64 = zext i32 %i to i64
214 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
215 %array.i = load i32, i32* %array.i.ptr, align 4
216 %loop.acc.next = add i32 %loop.acc, %array.i
218 %i.next = add nuw i32 %i, 1
219 %continue = icmp slt i32 %i.next, %n
220 br i1 %continue, label %loop, label %exit
223 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
227 define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) {
228 ; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known(
230 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
231 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !0
232 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
233 ; CHECK: loop.preheader:
234 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]]
235 ; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]]
236 ; CHECK-NEXT: br label [[LOOP:%.*]]
238 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
239 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
240 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
241 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
242 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
243 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
244 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
245 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
246 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
247 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
248 ; CHECK: exit.loopexit:
249 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
250 ; CHECK-NEXT: br label [[EXIT]]
252 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
253 ; CHECK-NEXT: ret i32 [[RESULT]]
256 %tmp5 = icmp sle i32 %n, 0
257 %length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648}
258 br i1 %tmp5, label %exit, label %loop.preheader
264 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
265 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
266 %within.bounds = icmp ult i32 %i, %length
267 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
269 %i.i64 = zext i32 %i to i64
270 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
271 %array.i = load i32, i32* %array.i.ptr, align 4
272 %loop.acc.next = add i32 %loop.acc, %array.i
274 %i.next = add nuw i32 %i, 1
275 %continue = icmp slt i32 %i.next, %n
276 br i1 %continue, label %loop, label %exit
279 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
283 define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) {
284 ; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate(
286 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
287 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
288 ; CHECK: loop.preheader:
289 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
290 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
291 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
292 ; CHECK-NEXT: br label [[LOOP:%.*]]
294 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
295 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
296 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
297 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
298 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
299 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
300 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
301 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
302 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]]
303 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
304 ; CHECK: exit.loopexit:
305 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
306 ; CHECK-NEXT: br label [[EXIT]]
308 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
309 ; CHECK-NEXT: ret i32 [[RESULT]]
312 %tmp5 = icmp sle i32 %n, 0
313 br i1 %tmp5, label %exit, label %loop.preheader
319 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
320 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
321 %within.bounds = icmp ult i32 %i, %length
322 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
324 %i.i64 = zext i32 %i to i64
325 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
326 %array.i = load i32, i32* %array.i.ptr, align 4
327 %loop.acc.next = add i32 %loop.acc, %array.i
329 %i.next = add nuw i32 %i, 1
330 %continue = icmp sgt i32 %i.next, %n
331 br i1 %continue, label %exit, label %loop
334 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
338 define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) {
339 ; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check(
341 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
342 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
343 ; CHECK: loop.preheader:
344 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
345 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
346 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
347 ; CHECK-NEXT: br label [[LOOP:%.*]]
349 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
350 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
351 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
352 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
353 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
354 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
355 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
356 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
357 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
358 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
359 ; CHECK: exit.loopexit:
360 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
361 ; CHECK-NEXT: br label [[EXIT]]
363 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
364 ; CHECK-NEXT: ret i32 [[RESULT]]
367 %tmp5 = icmp sle i32 %n, 0
368 br i1 %tmp5, label %exit, label %loop.preheader
374 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
375 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
376 %within.bounds = icmp ult i32 %i, %length
377 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
379 %i.i64 = zext i32 %i to i64
380 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
381 %array.i = load i32, i32* %array.i.ptr, align 4
382 %loop.acc.next = add i32 %loop.acc, %array.i
384 %i.next = add nuw i32 %i, 1
385 %continue = icmp sle i32 %i.next, %n
386 br i1 %continue, label %loop, label %exit
389 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
393 define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length, i32 %n) {
394 ; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check(
396 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
397 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
398 ; CHECK: loop.preheader:
399 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
400 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
401 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
402 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
403 ; CHECK-NEXT: br label [[LOOP:%.*]]
405 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
406 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
407 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
408 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
409 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
410 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
411 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
412 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
413 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
414 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
415 ; CHECK: exit.loopexit:
416 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
417 ; CHECK-NEXT: br label [[EXIT]]
419 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
420 ; CHECK-NEXT: ret i32 [[RESULT]]
423 %tmp5 = icmp sle i32 %n, 0
424 br i1 %tmp5, label %exit, label %loop.preheader
430 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
431 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
432 %within.bounds = icmp ult i32 %i, %length
433 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
435 %i.i64 = zext i32 %i to i64
436 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
437 %array.i = load i32, i32* %array.i.ptr, align 4
438 %loop.acc.next = add i32 %loop.acc, %array.i
440 %i.next = add i32 %i, 1
441 %continue = icmp slt i32 %i, %n
442 br i1 %continue, label %loop, label %exit
445 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
449 define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(i32* %array, i32 %length, i32 %n) {
450 ; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(
452 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
453 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
454 ; CHECK: loop.preheader:
455 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2
456 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
457 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
458 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
459 ; CHECK-NEXT: br label [[LOOP:%.*]]
461 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
462 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
463 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
464 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
465 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
466 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
467 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
468 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
469 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
470 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
471 ; CHECK: exit.loopexit:
472 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
473 ; CHECK-NEXT: br label [[EXIT]]
475 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
476 ; CHECK-NEXT: ret i32 [[RESULT]]
479 %tmp5 = icmp sle i32 %n, 0
480 br i1 %tmp5, label %exit, label %loop.preheader
486 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
487 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
489 %i.next = add i32 %i, 1
490 %within.bounds = icmp ult i32 %i.next, %length
491 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
493 %i.i64 = zext i32 %i to i64
494 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
495 %array.i = load i32, i32* %array.i.ptr, align 4
496 %loop.acc.next = add i32 %loop.acc, %array.i
498 %continue = icmp slt i32 %i, %n
499 br i1 %continue, label %loop, label %exit
502 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
506 define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
507 ; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check(
509 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
510 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
511 ; CHECK: loop.preheader:
512 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
513 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]]
514 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
515 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
516 ; CHECK-NEXT: br label [[LOOP:%.*]]
518 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
519 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
520 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
521 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
522 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
523 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
524 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
525 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
526 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
527 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
528 ; CHECK: exit.loopexit:
529 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
530 ; CHECK-NEXT: br label [[EXIT]]
532 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
533 ; CHECK-NEXT: ret i32 [[RESULT]]
536 %tmp5 = icmp sle i32 %n, 0
537 br i1 %tmp5, label %exit, label %loop.preheader
543 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
544 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
545 %i.offset = add i32 %i, 1
546 %within.bounds = icmp ult i32 %i.offset, %length
547 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
549 %i.i64 = zext i32 %i to i64
550 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
551 %array.i = load i32, i32* %array.i.ptr, align 4
552 %loop.acc.next = add i32 %loop.acc, %array.i
554 %i.next = add i32 %i, 1
555 %continue = icmp sle i32 %i.next, %n
556 br i1 %continue, label %loop, label %exit
559 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
563 define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) {
564 ; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(
566 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
567 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
568 ; CHECK: loop.preheader:
569 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
570 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]]
571 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
572 ; CHECK-NEXT: br label [[LOOP:%.*]]
574 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
575 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
576 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
577 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
578 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
579 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
580 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
581 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
582 ; CHECK-NEXT: [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1
583 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]]
584 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
585 ; CHECK: exit.loopexit:
586 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
587 ; CHECK-NEXT: br label [[EXIT]]
589 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
590 ; CHECK-NEXT: ret i32 [[RESULT]]
593 %tmp5 = icmp sle i32 %n, 0
594 br i1 %tmp5, label %exit, label %loop.preheader
600 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
601 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
602 %i.offset = add i32 %i, 1
603 %within.bounds = icmp ult i32 %i.offset, %length
604 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
606 %i.i64 = zext i32 %i to i64
607 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
608 %array.i = load i32, i32* %array.i.ptr, align 4
609 %loop.acc.next = add i32 %loop.acc, %array.i
611 %i.next = add i32 %i, 1
612 %i.next.offset = add i32 %i.next, 1
613 %continue = icmp sle i32 %i.next.offset, %n
614 br i1 %continue, label %loop, label %exit
617 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
621 define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) {
622 ; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n(
624 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
625 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
626 ; CHECK: loop.preheader:
627 ; CHECK-NEXT: br label [[LOOP:%.*]]
629 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
630 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
631 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
632 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
633 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
634 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
635 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
636 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
637 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
638 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
639 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
640 ; CHECK: exit.loopexit:
641 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
642 ; CHECK-NEXT: br label [[EXIT]]
644 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
645 ; CHECK-NEXT: ret i32 [[RESULT]]
648 %tmp5 = icmp sle i32 %n, 0
649 br i1 %tmp5, label %exit, label %loop.preheader
655 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
656 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
657 %within.bounds = icmp ult i32 %i, %length
658 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
660 %i.i64 = zext i32 %i to i64
661 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
662 %array.i = load i32, i32* %array.i.ptr, align 4
663 %loop.acc.next = add i32 %loop.acc, %array.i
665 %i.next = add nsw i32 %i, 1
666 %continue = icmp ne i32 %i.next, %n
667 br i1 %continue, label %loop, label %exit
670 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
674 define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) {
675 ; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step(
677 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
678 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
679 ; CHECK: loop.preheader:
680 ; CHECK-NEXT: br label [[LOOP:%.*]]
682 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
683 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
684 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
685 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
686 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
687 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
688 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
689 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
690 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 2
691 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
692 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
693 ; CHECK: exit.loopexit:
694 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
695 ; CHECK-NEXT: br label [[EXIT]]
697 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
698 ; CHECK-NEXT: ret i32 [[RESULT]]
701 %tmp5 = icmp sle i32 %n, 0
702 br i1 %tmp5, label %exit, label %loop.preheader
708 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
709 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
710 %within.bounds = icmp ult i32 %i, %length
711 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
713 %i.i64 = zext i32 %i to i64
714 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
715 %array.i = load i32, i32* %array.i.ptr, align 4
716 %loop.acc.next = add i32 %loop.acc, %array.i
718 %i.next = add nsw i32 %i, 2
719 %continue = icmp slt i32 %i.next, %n
720 br i1 %continue, label %loop, label %exit
723 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
727 define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) {
728 ; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check(
730 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
731 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
732 ; CHECK: loop.preheader:
733 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
734 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
735 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
736 ; CHECK-NEXT: br label [[LOOP:%.*]]
738 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
739 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
740 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
741 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
742 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
743 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
744 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
745 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
746 ; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1
747 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
748 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
749 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
750 ; CHECK: exit.loopexit:
751 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
752 ; CHECK-NEXT: br label [[EXIT]]
754 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
755 ; CHECK-NEXT: ret i32 [[RESULT]]
758 %tmp5 = icmp sle i32 %n, 0
759 br i1 %tmp5, label %exit, label %loop.preheader
765 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
766 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
767 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
769 %within.bounds = icmp ult i32 %j, %length
770 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
772 %i.i64 = zext i32 %i to i64
773 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
774 %array.i = load i32, i32* %array.i.ptr, align 4
775 %loop.acc.next = add i32 %loop.acc, %array.i
777 %j.next = add nsw i32 %j, 1
778 %i.next = add nsw i32 %i, 1
779 %continue = icmp slt i32 %i.next, %n
780 br i1 %continue, label %loop, label %exit
783 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
787 define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start.i,
788 ; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check(
790 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
791 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
792 ; CHECK: loop.preheader:
793 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]]
794 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]]
795 ; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]]
796 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]]
797 ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]]
798 ; CHECK-NEXT: br label [[LOOP:%.*]]
800 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
801 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START_I]], [[LOOP_PREHEADER]] ]
802 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ]
803 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ]
804 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
805 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
806 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
807 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
808 ; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
809 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
810 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
811 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
812 ; CHECK: exit.loopexit:
813 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
814 ; CHECK-NEXT: br label [[EXIT]]
816 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
817 ; CHECK-NEXT: ret i32 [[RESULT]]
819 i32 %start.j, i32 %length,
822 %tmp5 = icmp sle i32 %n, 0
823 br i1 %tmp5, label %exit, label %loop.preheader
829 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
830 %i = phi i32 [ %i.next, %loop ], [ %start.i, %loop.preheader ]
831 %j = phi i32 [ %j.next, %loop ], [ %start.j, %loop.preheader ]
833 %within.bounds = icmp ult i32 %j, %length
834 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
836 %i.i64 = zext i32 %i to i64
837 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
838 %array.i = load i32, i32* %array.i.ptr, align 4
839 %loop.acc.next = add i32 %loop.acc, %array.i
841 %j.next = add i32 %j, 1
842 %i.next = add i32 %i, 1
843 %continue = icmp slt i32 %i.next, %n
844 br i1 %continue, label %loop, label %exit
847 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
851 define i32 @signed_loop_0_to_n_different_iv_types(i32* %array, i16 %length, i32 %n) {
852 ; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types(
854 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
855 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
856 ; CHECK: loop.preheader:
857 ; CHECK-NEXT: br label [[LOOP:%.*]]
859 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
860 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
861 ; CHECK-NEXT: [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
862 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]]
863 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
864 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
865 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
866 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
867 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
868 ; CHECK-NEXT: [[J_NEXT]] = add i16 [[J]], 1
869 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
870 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
871 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
872 ; CHECK: exit.loopexit:
873 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
874 ; CHECK-NEXT: br label [[EXIT]]
876 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
877 ; CHECK-NEXT: ret i32 [[RESULT]]
880 %tmp5 = icmp sle i32 %n, 0
881 br i1 %tmp5, label %exit, label %loop.preheader
887 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
888 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
889 %j = phi i16 [ %j.next, %loop ], [ 0, %loop.preheader ]
891 %within.bounds = icmp ult i16 %j, %length
892 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
894 %i.i64 = zext i32 %i to i64
895 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
896 %array.i = load i32, i32* %array.i.ptr, align 4
897 %loop.acc.next = add i32 %loop.acc, %array.i
899 %j.next = add i16 %j, 1
900 %i.next = add i32 %i, 1
901 %continue = icmp slt i32 %i.next, %n
902 br i1 %continue, label %loop, label %exit
905 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
909 define i32 @signed_loop_0_to_n_different_iv_strides(i32* %array, i32 %length, i32 %n) {
910 ; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides(
912 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
913 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
914 ; CHECK: loop.preheader:
915 ; CHECK-NEXT: br label [[LOOP:%.*]]
917 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
918 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
919 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
920 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]]
921 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
922 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
923 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
924 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
925 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
926 ; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 2
927 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
928 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
929 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
930 ; CHECK: exit.loopexit:
931 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
932 ; CHECK-NEXT: br label [[EXIT]]
934 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
935 ; CHECK-NEXT: ret i32 [[RESULT]]
938 %tmp5 = icmp sle i32 %n, 0
939 br i1 %tmp5, label %exit, label %loop.preheader
945 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
946 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
947 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ]
949 %within.bounds = icmp ult i32 %j, %length
950 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
952 %i.i64 = zext i32 %i to i64
953 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
954 %array.i = load i32, i32* %array.i.ptr, align 4
955 %loop.acc.next = add i32 %loop.acc, %array.i
957 %j.next = add nsw i32 %j, 2
958 %i.next = add nsw i32 %i, 1
959 %continue = icmp slt i32 %i.next, %n
960 br i1 %continue, label %loop, label %exit
963 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
967 define i32 @two_range_checks(i32* %array.1, i32 %length.1,
968 ; CHECK-LABEL: @two_range_checks(
970 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
971 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
972 ; CHECK: loop.preheader:
973 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
974 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]]
975 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
976 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
977 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_1]]
978 ; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
979 ; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP2]], [[TMP5]]
980 ; CHECK-NEXT: br label [[LOOP:%.*]]
982 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
983 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
984 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ]
985 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
986 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
987 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
988 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
989 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
990 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
991 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
992 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
993 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
994 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
995 ; CHECK: exit.loopexit:
996 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
997 ; CHECK-NEXT: br label [[EXIT]]
999 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1000 ; CHECK-NEXT: ret i32 [[RESULT]]
1002 i32* %array.2, i32 %length.2, i32 %n) {
1004 %tmp5 = icmp eq i32 %n, 0
1005 br i1 %tmp5, label %exit, label %loop.preheader
1011 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1012 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1013 %within.bounds.1 = icmp ult i32 %i, %length.1
1014 %within.bounds.2 = icmp ult i32 %i, %length.2
1015 %within.bounds = and i1 %within.bounds.1, %within.bounds.2
1016 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1018 %i.i64 = zext i32 %i to i64
1019 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1020 %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1021 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1023 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1024 %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1025 %loop.acc.next = add i32 %loop.acc.1, %array.2.i
1027 %i.next = add nuw i32 %i, 1
1028 %continue = icmp ult i32 %i.next, %n
1029 br i1 %continue, label %loop, label %exit
1032 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1036 define i32 @three_range_checks(i32* %array.1, i32 %length.1,
1037 ; CHECK-LABEL: @three_range_checks(
1038 ; CHECK-NEXT: entry:
1039 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1040 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1041 ; CHECK: loop.preheader:
1042 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1043 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1044 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1045 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1046 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1047 ; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
1048 ; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1049 ; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1050 ; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
1051 ; CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP2]], [[TMP5]]
1052 ; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1053 ; CHECK-NEXT: br label [[LOOP:%.*]]
1055 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1056 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1057 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP10]], i32 9) [ "deopt"() ]
1058 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1059 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
1060 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
1061 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1062 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
1063 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
1064 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1065 ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
1066 ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
1067 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1068 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1069 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1070 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1071 ; CHECK: exit.loopexit:
1072 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1073 ; CHECK-NEXT: br label [[EXIT]]
1075 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1076 ; CHECK-NEXT: ret i32 [[RESULT]]
1078 i32* %array.2, i32 %length.2,
1079 i32* %array.3, i32 %length.3, i32 %n) {
1081 %tmp5 = icmp eq i32 %n, 0
1082 br i1 %tmp5, label %exit, label %loop.preheader
1088 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1089 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1090 %within.bounds.1 = icmp ult i32 %i, %length.1
1091 %within.bounds.2 = icmp ult i32 %i, %length.2
1092 %within.bounds.3 = icmp ult i32 %i, %length.3
1093 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
1094 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
1095 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1097 %i.i64 = zext i32 %i to i64
1098 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1099 %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1100 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1102 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1103 %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1104 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1106 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
1107 %array.3.i = load i32, i32* %array.3.i.ptr, align 4
1108 %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1110 %i.next = add nuw i32 %i, 1
1111 %continue = icmp ult i32 %i.next, %n
1112 br i1 %continue, label %loop, label %exit
1115 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1119 define i32 @three_guards(i32* %array.1, i32 %length.1,
1120 ; CHECK-LABEL: @three_guards(
1121 ; CHECK-NEXT: entry:
1122 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1123 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1124 ; CHECK: loop.preheader:
1125 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1126 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1127 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1128 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1129 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1130 ; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]]
1131 ; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1132 ; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1133 ; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]]
1134 ; CHECK-NEXT: br label [[LOOP:%.*]]
1136 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1137 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1138 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1139 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1140 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
1141 ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
1142 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1143 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ]
1144 ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
1145 ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
1146 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1147 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ]
1148 ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
1149 ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
1150 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1151 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1152 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1153 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1154 ; CHECK: exit.loopexit:
1155 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1156 ; CHECK-NEXT: br label [[EXIT]]
1158 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1159 ; CHECK-NEXT: ret i32 [[RESULT]]
1161 i32* %array.2, i32 %length.2,
1162 i32* %array.3, i32 %length.3, i32 %n) {
1164 %tmp5 = icmp eq i32 %n, 0
1165 br i1 %tmp5, label %exit, label %loop.preheader
1172 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1173 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1175 %within.bounds.1 = icmp ult i32 %i, %length.1
1176 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ]
1178 %i.i64 = zext i32 %i to i64
1179 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
1180 %array.1.i = load i32, i32* %array.1.i.ptr, align 4
1181 %loop.acc.1 = add i32 %loop.acc, %array.1.i
1183 %within.bounds.2 = icmp ult i32 %i, %length.2
1184 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ]
1186 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
1187 %array.2.i = load i32, i32* %array.2.i.ptr, align 4
1188 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1190 %within.bounds.3 = icmp ult i32 %i, %length.3
1191 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ]
1193 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
1194 %array.3.i = load i32, i32* %array.3.i.ptr, align 4
1195 %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1197 %i.next = add nuw i32 %i, 1
1198 %continue = icmp ult i32 %i.next, %n
1199 br i1 %continue, label %loop, label %exit
1202 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1206 define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) {
1207 ; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition(
1208 ; CHECK-NEXT: entry:
1209 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1210 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1211 ; CHECK: loop.preheader:
1212 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
1213 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1214 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1215 ; CHECK-NEXT: br label [[LOOP:%.*]]
1217 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1218 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1219 ; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
1220 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]]
1221 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1222 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1223 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1224 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1225 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1226 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1227 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1228 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1229 ; CHECK: exit.loopexit:
1230 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1231 ; CHECK-NEXT: br label [[EXIT]]
1233 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1234 ; CHECK-NEXT: ret i32 [[RESULT]]
1237 %tmp5 = icmp eq i32 %n, 0
1238 br i1 %tmp5, label %exit, label %loop.preheader
1244 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1245 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1246 %within.bounds = icmp ult i32 %i, %length
1247 %unrelated.cond = icmp ult i32 %x, %length
1248 %guard.cond = and i1 %within.bounds, %unrelated.cond
1249 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1251 %i.i64 = zext i32 %i to i64
1252 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1253 %array.i = load i32, i32* %array.i.ptr, align 4
1254 %loop.acc.next = add i32 %loop.acc, %array.i
1256 %i.next = add nuw i32 %i, 1
1257 %continue = icmp ult i32 %i.next, %n
1258 br i1 %continue, label %loop, label %exit
1261 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1265 ; Don't change the guard condition if there were no widened subconditions
1266 define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
1267 ; CHECK-LABEL: @test_no_widened_conditions(
1268 ; CHECK-NEXT: entry:
1269 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1270 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1271 ; CHECK: loop.preheader:
1272 ; CHECK-NEXT: br label [[LOOP:%.*]]
1274 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1275 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1276 ; CHECK-NEXT: [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]]
1277 ; CHECK-NEXT: [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]]
1278 ; CHECK-NEXT: [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]]
1279 ; CHECK-NEXT: [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]]
1280 ; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]]
1281 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1282 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1283 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1284 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1285 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1286 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1287 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1288 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1289 ; CHECK: exit.loopexit:
1290 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1291 ; CHECK-NEXT: br label [[EXIT]]
1293 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1294 ; CHECK-NEXT: ret i32 [[RESULT]]
1297 %tmp5 = icmp eq i32 %n, 0
1298 br i1 %tmp5, label %exit, label %loop.preheader
1304 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1305 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1306 %unrelated.cond.1 = icmp eq i32 %x1, %i
1307 %unrelated.cond.2 = icmp eq i32 %x2, %i
1308 %unrelated.cond.3 = icmp eq i32 %x3, %i
1309 %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
1310 %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
1312 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1314 %i.i64 = zext i32 %i to i64
1315 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1316 %array.i = load i32, i32* %array.i.ptr, align 4
1317 %loop.acc.next = add i32 %loop.acc, %array.i
1319 %i.next = add nuw i32 %i, 1
1320 %continue = icmp ult i32 %i.next, %n
1321 br i1 %continue, label %loop, label %exit
1324 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1328 define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) {
1329 ; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound(
1330 ; CHECK-NEXT: entry:
1331 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1332 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1333 ; CHECK: loop.preheader:
1334 ; CHECK-NEXT: br label [[LOOP:%.*]]
1336 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1337 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1338 ; CHECK-NEXT: [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]]
1339 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]]
1340 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1341 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1342 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1343 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1344 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1345 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
1346 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1347 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1348 ; CHECK: exit.loopexit:
1349 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1350 ; CHECK-NEXT: br label [[EXIT]]
1352 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1353 ; CHECK-NEXT: ret i32 [[RESULT]]
1356 %tmp5 = icmp sle i32 %n, 0
1357 br i1 %tmp5, label %exit, label %loop.preheader
1363 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1364 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1365 %bound = add i32 %i, %x
1366 %within.bounds = icmp ult i32 %i, %bound
1367 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1369 %i.i64 = zext i32 %i to i64
1370 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1371 %array.i = load i32, i32* %array.i.ptr, align 4
1372 %loop.acc.next = add i32 %loop.acc, %array.i
1374 %i.next = add nsw i32 %i, 1
1375 %continue = icmp slt i32 %i.next, %n
1376 br i1 %continue, label %loop, label %exit
1379 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1383 define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) {
1384 ; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate(
1385 ; CHECK-NEXT: entry:
1386 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1387 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1388 ; CHECK: loop.preheader:
1389 ; CHECK-NEXT: br label [[LOOP:%.*]]
1391 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1392 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1393 ; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]]
1394 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ]
1395 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1396 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1397 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1398 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1399 ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1
1400 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1401 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1402 ; CHECK: exit.loopexit:
1403 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1404 ; CHECK-NEXT: br label [[EXIT]]
1406 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1407 ; CHECK-NEXT: ret i32 [[RESULT]]
1410 %tmp5 = icmp sle i32 %n, 0
1411 br i1 %tmp5, label %exit, label %loop.preheader
1417 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1418 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ]
1419 %guard.cond = icmp eq i32 %i, %x
1420 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ]
1422 %i.i64 = zext i32 %i to i64
1423 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1424 %array.i = load i32, i32* %array.i.ptr, align 4
1425 %loop.acc.next = add i32 %loop.acc, %array.i
1427 %i.next = add nsw i32 %i, 1
1428 %continue = icmp slt i32 %i.next, %n
1429 br i1 %continue, label %loop, label %exit
1432 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1436 define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) {
1437 ; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length(
1438 ; CHECK-NEXT: entry:
1439 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1440 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1441 ; CHECK: loop.preheader:
1442 ; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32
1443 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1444 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]]
1445 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1446 ; CHECK-NEXT: br label [[LOOP:%.*]]
1448 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1449 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1450 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1451 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1452 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1453 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1454 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1455 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1456 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1457 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1458 ; CHECK: exit.loopexit:
1459 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1460 ; CHECK-NEXT: br label [[EXIT]]
1462 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1463 ; CHECK-NEXT: ret i32 [[RESULT]]
1466 %tmp5 = icmp eq i32 %n, 0
1467 br i1 %tmp5, label %exit, label %loop.preheader
1473 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1474 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1475 %length = zext i16 %length.i16 to i32
1476 %within.bounds = icmp ult i32 %i, %length
1477 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1479 %i.i64 = zext i32 %i to i64
1480 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1481 %array.i = load i32, i32* %array.i.ptr, align 4
1482 %loop.acc.next = add i32 %loop.acc, %array.i
1484 %i.next = add nuw i32 %i, 1
1485 %continue = icmp ult i32 %i.next, %n
1486 br i1 %continue, label %loop, label %exit
1489 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1493 define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) {
1494 ; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length(
1495 ; CHECK-NEXT: entry:
1496 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1497 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1498 ; CHECK: loop.preheader:
1499 ; CHECK-NEXT: br label [[LOOP:%.*]]
1501 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1502 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1503 ; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]]
1504 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]]
1505 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]]
1506 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1507 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1508 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1509 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1510 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1511 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1512 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1513 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1514 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1515 ; CHECK: exit.loopexit:
1516 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1517 ; CHECK-NEXT: br label [[EXIT]]
1519 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1520 ; CHECK-NEXT: ret i32 [[RESULT]]
1523 %tmp5 = icmp eq i32 %n, 0
1524 br i1 %tmp5, label %exit, label %loop.preheader
1530 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1531 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1532 %length.udiv = udiv i32 %length, %divider
1533 %within.bounds = icmp ult i32 %i, %length.udiv
1534 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1536 %i.i64 = zext i32 %i to i64
1537 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1538 %array.i = load i32, i32* %array.i.ptr, align 4
1539 %loop.acc.next = add i32 %loop.acc, %array.i
1541 %i.next = add nuw i32 %i, 1
1542 %continue = icmp ult i32 %i.next, %n
1543 br i1 %continue, label %loop, label %exit
1546 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
1551 ; This is a case where the length information tells us that the guard
1552 ; must trigger on some iteration.
1553 define i32 @provably_taken(i32* %array, i32* %length.ptr) {
1554 ; CHECK-LABEL: @provably_taken(
1555 ; CHECK-NEXT: loop.preheader:
1556 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !1
1557 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]]
1558 ; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], false
1559 ; CHECK-NEXT: br label [[LOOP:%.*]]
1561 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1562 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1563 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
1564 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
1565 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1566 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1567 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1568 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1569 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200
1570 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1572 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
1573 ; CHECK-NEXT: ret i32 [[RESULT]]
1576 %length = load i32, i32* %length.ptr, !range !{i32 0, i32 50}
1580 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
1581 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1582 %within.bounds = icmp ult i32 %i, %length
1583 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1585 %i.i64 = zext i32 %i to i64
1586 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1587 %array.i = load i32, i32* %array.i.ptr, align 4
1588 %loop.acc.next = add i32 %loop.acc, %array.i
1590 %i.next = add nuw i32 %i, 1
1591 %continue = icmp slt i32 %i.next, 200
1592 br i1 %continue, label %loop, label %exit
1595 %result = phi i32 [ %loop.acc.next, %loop ]
1599 ; NE Check (as produced by LFTR) where we can prove Start < End via simple
1600 ; instruction analysis
1601 define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) {
1602 ; CHECK-LABEL: @ne_latch_zext(
1603 ; CHECK-NEXT: loop.preheader:
1604 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1605 ; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw nsw i32 [[N]], 1
1606 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[NPLUS1]], [[LENGTH:%.*]]
1607 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1608 ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1609 ; CHECK-NEXT: br label [[LOOP:%.*]]
1611 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1612 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ]
1613 ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1614 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1615 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1617 ; CHECK-NEXT: ret i32 0
1620 %n = zext i16 %n16 to i32
1621 %nplus1 = add nsw nuw i32 %n, 1
1625 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1626 %within.bounds = icmp ult i32 %i, %length
1627 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1629 %i.next = add nsw nuw i32 %i, 1
1630 %continue = icmp ne i32 %i.next, %nplus1
1631 br i1 %continue, label %loop, label %exit
1637 ; Same as previous, but with a pre-increment test since this is easier to match
1638 define i32 @ne_latch_zext_preinc(i32* %array, i32 %length, i16 %n16) {
1639 ; CHECK-LABEL: @ne_latch_zext_preinc(
1640 ; CHECK-NEXT: loop.preheader:
1641 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1642 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1643 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1644 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1645 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1646 ; CHECK-NEXT: br label [[LOOP:%.*]]
1648 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1649 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1650 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1651 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1652 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1654 ; CHECK-NEXT: ret i32 0
1657 %n = zext i16 %n16 to i32
1661 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1662 %within.bounds = icmp ult i32 %i, %length
1663 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1665 %i.next = add nuw i32 %i, 1
1666 %continue = icmp ne i32 %i, %n
1667 br i1 %continue, label %loop, label %exit
1673 ; NE Check (as produced by LFTR) where we can prove Start < End via the
1674 ; condition guarding the loop entry.
1675 define i32 @ne_latch_dom_check(i32* %array, i32 %length, i32 %n) {
1676 ; CHECK-LABEL: @ne_latch_dom_check(
1677 ; CHECK-NEXT: entry:
1678 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1679 ; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw i32 [[N]], 1
1680 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1681 ; CHECK: loop.preheader:
1682 ; CHECK-NEXT: br label [[LOOP:%.*]]
1684 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1685 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1686 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1687 ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1
1688 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]]
1689 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1690 ; CHECK: exit.loopexit:
1691 ; CHECK-NEXT: br label [[EXIT]]
1693 ; CHECK-NEXT: ret i32 0
1696 %tmp5 = icmp sle i32 %n, 0
1697 %nplus1 = add nuw i32 %n, 1
1698 br i1 %tmp5, label %exit, label %loop.preheader
1704 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1705 %within.bounds = icmp ult i32 %i, %length
1706 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1708 %i.next = add nsw nuw i32 %i, 1
1709 %continue = icmp ne i32 %i.next, %nplus1
1710 br i1 %continue, label %loop, label %exit
1716 ; Same as previous, but easier to match
1717 define i32 @ne_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) {
1718 ; CHECK-LABEL: @ne_latch_dom_check_preinc(
1719 ; CHECK-NEXT: entry:
1720 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1721 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1722 ; CHECK: loop.preheader:
1723 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1724 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1725 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1726 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1727 ; CHECK-NEXT: br label [[LOOP:%.*]]
1729 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1730 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1731 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1732 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1733 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
1734 ; CHECK: exit.loopexit:
1735 ; CHECK-NEXT: br label [[EXIT]]
1737 ; CHECK-NEXT: ret i32 0
1740 %tmp5 = icmp sle i32 %n, 0
1741 br i1 %tmp5, label %exit, label %loop.preheader
1747 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1748 %within.bounds = icmp ult i32 %i, %length
1749 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1751 %i.next = add nuw i32 %i, 1
1752 %continue = icmp ne i32 %i, %n
1753 br i1 %continue, label %loop, label %exit
1759 ; Same as previous, except swapped br/cmp
1760 define i32 @eq_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) {
1761 ; CHECK-LABEL: @eq_latch_dom_check_preinc(
1762 ; CHECK-NEXT: entry:
1763 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1764 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1765 ; CHECK: loop.preheader:
1766 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
1767 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1768 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
1769 ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1770 ; CHECK-NEXT: br label [[LOOP:%.*]]
1772 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
1773 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ]
1774 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
1775 ; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[I]], [[N]]
1776 ; CHECK-NEXT: br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]]
1777 ; CHECK: exit.loopexit:
1778 ; CHECK-NEXT: br label [[EXIT]]
1780 ; CHECK-NEXT: ret i32 0
1783 %tmp5 = icmp sle i32 %n, 0
1784 br i1 %tmp5, label %exit, label %loop.preheader
1790 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1791 %within.bounds = icmp ult i32 %i, %length
1792 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1794 %i.next = add nuw i32 %i, 1
1795 %done = icmp eq i32 %i, %n
1796 br i1 %done, label %exit, label %loop
1803 ; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap
1804 ; around several times or even be infinite)
1805 define i32 @neg_ne_latch_mod_step(i32* %array, i32 %length, i16 %n16) {
1806 ; CHECK-LABEL: @neg_ne_latch_mod_step(
1807 ; CHECK-NEXT: loop.preheader:
1808 ; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32
1809 ; CHECK-NEXT: br label [[LOOP:%.*]]
1811 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1812 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1813 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1814 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 3
1815 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]]
1816 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1818 ; CHECK-NEXT: ret i32 0
1821 %n = zext i16 %n16 to i32
1825 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1826 %within.bounds = icmp ult i32 %i, %length
1827 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1829 %i.next = add i32 %i, 3
1830 %continue = icmp ne i32 %i, %n
1831 br i1 %continue, label %loop, label %exit
1837 ; NE latch - TODO: could prove (end-start) mod step == 0
1838 define i32 @ne_latch_mod_step(i32* %array, i32 %length) {
1839 ; CHECK-LABEL: @ne_latch_mod_step(
1840 ; CHECK-NEXT: loop.preheader:
1841 ; CHECK-NEXT: br label [[LOOP:%.*]]
1843 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1844 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1845 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1846 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 2
1847 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 400
1848 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1850 ; CHECK-NEXT: ret i32 0
1856 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
1857 %within.bounds = icmp ult i32 %i, %length
1858 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1860 %i.next = add nuw i32 %i, 2
1861 %continue = icmp ne i32 %i, 400
1862 br i1 %continue, label %loop, label %exit
1868 ; NE Latch - but end > start so wraps around and not equivelent to a ult
1869 define i32 @neg_ne_latch_swapped_order(i32* %array, i32 %length) {
1870 ; CHECK-LABEL: @neg_ne_latch_swapped_order(
1871 ; CHECK-NEXT: loop.preheader:
1872 ; CHECK-NEXT: br label [[LOOP:%.*]]
1874 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1875 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1876 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1877 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
1878 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 0
1879 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1881 ; CHECK-NEXT: ret i32 0
1887 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
1888 %within.bounds = icmp ult i32 %i, %length
1889 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1891 %i.next = add i32 %i, 1
1892 %continue = icmp ne i32 %i, 0
1893 br i1 %continue, label %loop, label %exit
1899 ; Negative test, make sure we don't crash on unconditional latches
1900 ; TODO: there's no reason we shouldn't be able to predicate the
1901 ; condition for an statically infinite loop.
1902 define i32 @unconditional_latch(i32* %a, i32 %length) {
1903 ; CHECK-LABEL: @unconditional_latch(
1904 ; CHECK-NEXT: loop.preheader:
1905 ; CHECK-NEXT: br label [[LOOP:%.*]]
1907 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
1908 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1909 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
1910 ; CHECK-NEXT: store volatile i32 0, i32* [[A:%.*]]
1911 ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1
1912 ; CHECK-NEXT: br label [[LOOP]]
1918 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ]
1919 %within.bounds = icmp ult i32 %i, %length
1920 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
1921 store volatile i32 0, i32* %a
1922 %i.next = add i32 %i, 1