[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / predicated_ranges.ll
blobffe4db9435488935975bf2588a087fb475ca8988
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -indvars -S < %s | FileCheck %s
3 ; RUN: opt -passes=indvars -S < %s | FileCheck %s
5 ; Check that we are able to remove the range check basing on the following facts:
6 ; 0 <= len <= MAX_INT [1];
7 ; iv starts from len and goes down stopping at zero and [1], therefore
8 ;   0 <= iv <= len [2];
9 ; 3. In range_check_block, iv != 0 and [2], therefore
10 ;   1 <= iv <= len [3];
11 ; 4. iv.next = iv - 1 and [3], therefore
12 ;   0 <= iv.next < len.
13 define void @test_predicated_simple_unsigned(i32* %p, i32* %arr) {
14 ; CHECK-LABEL: @test_predicated_simple_unsigned(
15 ; CHECK-NEXT:  preheader:
16 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0:!range !.*]]
17 ; CHECK-NEXT:    br label [[LOOP:%.*]]
18 ; CHECK:       loop:
19 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
20 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
21 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
22 ; CHECK:       range_check_block:
23 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
24 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
25 ; CHECK:       backedge:
26 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
27 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
28 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
29 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
30 ; CHECK:       exit:
31 ; CHECK-NEXT:    ret void
32 ; CHECK:       fail:
33 ; CHECK-NEXT:    unreachable
35 preheader:
36   %len = load i32, i32* %p, !range !0
37   br label %loop
39 loop:
40   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
41   %zero_cond = icmp eq i32 %iv, 0
42   br i1 %zero_cond, label %exit, label %range_check_block
44 range_check_block:
45   %iv.next = sub i32 %iv, 1
46   %range_check = icmp ult i32 %iv.next, %len
47   br i1 %range_check, label %backedge, label %fail
49 backedge:
50   %el.ptr = getelementptr i32, i32* %p, i32 %iv
51   %el = load i32, i32* %el.ptr
52   %loop.cond = icmp eq i32 %el, 0
53   br i1 %loop.cond, label %loop, label %exit
55 exit:
56   ret void
58 fail:
59   unreachable
62 define void @test_predicated_simple_signed(i32* %p, i32* %arr) {
63 ; CHECK-LABEL: @test_predicated_simple_signed(
64 ; CHECK-NEXT:  preheader:
65 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0]]
66 ; CHECK-NEXT:    br label [[LOOP:%.*]]
67 ; CHECK:       loop:
68 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
69 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
70 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
71 ; CHECK:       range_check_block:
72 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
73 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
74 ; CHECK:       backedge:
75 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
76 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
77 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
78 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
79 ; CHECK:       exit:
80 ; CHECK-NEXT:    ret void
81 ; CHECK:       fail:
82 ; CHECK-NEXT:    unreachable
84 preheader:
85   %len = load i32, i32* %p, !range !0
86   br label %loop
88 loop:
89   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
90   %zero_cond = icmp eq i32 %iv, 0
91   br i1 %zero_cond, label %exit, label %range_check_block
93 range_check_block:
94   %iv.next = sub i32 %iv, 1
95   %range_check = icmp slt i32 %iv.next, %len
96   br i1 %range_check, label %backedge, label %fail
98 backedge:
99   %el.ptr = getelementptr i32, i32* %p, i32 %iv
100   %el = load i32, i32* %el.ptr
101   %loop.cond = icmp eq i32 %el, 0
102   br i1 %loop.cond, label %loop, label %exit
104 exit:
105   ret void
107 fail:
108   unreachable
111 ; Cannot remove checks because the range check fails on the last iteration.
112 define void @predicated_outside_loop_signed_neg(i32 %arg) nounwind #0 {
113 ; CHECK-LABEL: @predicated_outside_loop_signed_neg(
114 ; CHECK-NEXT:  entry:
115 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
116 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
117 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
118 ; CHECK:       outer.preheader:
119 ; CHECK-NEXT:    br label [[OUTER:%.*]]
120 ; CHECK:       outer:
121 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
122 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
123 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
124 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
125 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
126 ; CHECK:       inner.ph:
127 ; CHECK-NEXT:    br label [[INNER:%.*]]
128 ; CHECK:       inner:
129 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
130 ; CHECK:       outer.inc.loopexit:
131 ; CHECK-NEXT:    br label [[OUTER_INC]]
132 ; CHECK:       outer.inc:
133 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
134 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
135 ; CHECK:       exit.loopexit:
136 ; CHECK-NEXT:    br label [[EXIT]]
137 ; CHECK:       exit:
138 ; CHECK-NEXT:    ret void
140 entry:
141   %sub1 = sub nsw i32 %arg, 1
142   %cmp1 = icmp slt i32 0, %sub1
143   br i1 %cmp1, label %outer, label %exit
145 outer:
146   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
147   %sub2 = sub nsw i32 %arg, %i
148   %sub3 = sub nsw i32 %sub2, 1
149   %cmp2 = icmp slt i32 0, %sub3
150   br i1 %cmp2, label %inner.ph, label %outer.inc
152 inner.ph:
153   br label %inner
155 inner:
156   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
157   %j.inc = add nsw i32 %j, 1
158   %cmp3 = icmp slt i32 %j.inc, %sub3
159   br i1 %cmp3, label %inner, label %outer.inc
161 outer.inc:
162   %i.inc = add nsw i32 %i, 1
163   %cmp4 = icmp slt i32 %i.inc, %arg
164   br i1 %cmp4, label %outer, label %exit
166 exit:
167   ret void
170 ; Range check can be removed.
171 define void @predicated_outside_loop_signed_pos(i32 %arg) nounwind #0 {
172 ; CHECK-LABEL: @predicated_outside_loop_signed_pos(
173 ; CHECK-NEXT:  entry:
174 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
175 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
176 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
177 ; CHECK:       outer.preheader:
178 ; CHECK-NEXT:    br label [[OUTER:%.*]]
179 ; CHECK:       outer:
180 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
181 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
182 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
183 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
184 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
185 ; CHECK:       inner.ph:
186 ; CHECK-NEXT:    br label [[INNER:%.*]]
187 ; CHECK:       inner:
188 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
189 ; CHECK:       outer.inc.loopexit:
190 ; CHECK-NEXT:    br label [[OUTER_INC]]
191 ; CHECK:       outer.inc:
192 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
193 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
194 ; CHECK:       exit.loopexit:
195 ; CHECK-NEXT:    br label [[EXIT]]
196 ; CHECK:       exit:
197 ; CHECK-NEXT:    ret void
199 entry:
200   %sub1 = sub nsw i32 %arg, 1
201   %cmp1 = icmp slt i32 0, %sub1
202   br i1 %cmp1, label %outer, label %exit
204 outer:
205   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
206   %sub2 = sub nsw i32 %arg, %i
207   %sub3 = sub nsw i32 %sub2, 1
208   %cmp2 = icmp slt i32 0, %sub3
209   br i1 %cmp2, label %inner.ph, label %outer.inc
211 inner.ph:
212   br label %inner
214 inner:
215   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
216   %j.inc = add nsw i32 %j, 1
217   %cmp3 = icmp slt i32 %j.inc, %sub3
218   br i1 %cmp3, label %inner, label %outer.inc
220 outer.inc:
221   %i.inc = add nsw i32 %i, 1
222   %cmp4 = icmp slt i32 %i.inc, %sub1
223   br i1 %cmp4, label %outer, label %exit
225 exit:
226   ret void
229 define void @predicated_outside_loop_unsigned(i32 %arg) nounwind #0 {
230 ; CHECK-LABEL: @predicated_outside_loop_unsigned(
231 ; CHECK-NEXT:  entry:
232 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
233 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
234 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
235 ; CHECK:       outer.preheader:
236 ; CHECK-NEXT:    br label [[OUTER:%.*]]
237 ; CHECK:       outer:
238 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
239 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
240 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
241 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
242 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
243 ; CHECK:       inner.ph:
244 ; CHECK-NEXT:    br label [[INNER:%.*]]
245 ; CHECK:       inner:
246 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
247 ; CHECK:       outer.inc.loopexit:
248 ; CHECK-NEXT:    br label [[OUTER_INC]]
249 ; CHECK:       outer.inc:
250 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
251 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
252 ; CHECK:       exit.loopexit:
253 ; CHECK-NEXT:    br label [[EXIT]]
254 ; CHECK:       exit:
255 ; CHECK-NEXT:    ret void
257 entry:
258   %sub1 = sub nsw i32 %arg, 1
259   %cmp1 = icmp slt i32 0, %sub1
260   br i1 %cmp1, label %outer, label %exit
262 outer:
263   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
264   %sub2 = sub nsw i32 %arg, %i
265   %sub3 = sub nsw i32 %sub2, 1
266   %cmp2 = icmp ult i32 0, %sub3
267   br i1 %cmp2, label %inner.ph, label %outer.inc
269 inner.ph:
270   br label %inner
272 inner:
273   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
274   %j.inc = add nsw i32 %j, 1
275   %cmp3 = icmp slt i32 %j.inc, %sub3
276   br i1 %cmp3, label %inner, label %outer.inc
278 outer.inc:
279   %i.inc = add nsw i32 %i, 1
280   %cmp4 = icmp slt i32 %i.inc, %arg
281   br i1 %cmp4, label %outer, label %exit
283 exit:
284   ret void
287 ; Cannot remove checks because the range check fails on the last iteration.
288 define void @predicated_inside_loop_signed_neg(i32 %arg) nounwind #0 {
289 ; CHECK-LABEL: @predicated_inside_loop_signed_neg(
290 ; CHECK-NEXT:  entry:
291 ; CHECK-NEXT:    br label [[OUTER:%.*]]
292 ; CHECK:       outer:
293 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
294 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
295 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
296 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
297 ; CHECK:       guarded:
298 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
299 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
300 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
301 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
302 ; CHECK:       inner.ph:
303 ; CHECK-NEXT:    br label [[INNER:%.*]]
304 ; CHECK:       inner:
305 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
306 ; CHECK:       outer.inc.loopexit:
307 ; CHECK-NEXT:    br label [[OUTER_INC]]
308 ; CHECK:       outer.inc:
309 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
310 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
311 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
312 ; CHECK:       exit:
313 ; CHECK-NEXT:    ret void
315 entry:
316   br label %outer
318 outer:
319   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
320   %sub1 = sub nsw i32 %arg, 1
321   %cmp1 = icmp slt i32 0, %sub1
322   br i1 %cmp1, label %guarded, label %exit
324 guarded:
325   %sub2 = sub nsw i32 %arg, %i
326   %sub3 = sub nsw i32 %sub2, 1
327   %cmp2 = icmp slt i32 0, %sub3
328   br i1 %cmp2, label %inner.ph, label %outer.inc
330 inner.ph:
331   br label %inner
333 inner:
334   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
335   %j.inc = add nsw i32 %j, 1
336   %cmp3 = icmp slt i32 %j.inc, %sub3
337   br i1 %cmp3, label %inner, label %outer.inc
339 outer.inc:
340   %i.inc = add nsw i32 %i, 1
341   %cmp4 = icmp slt i32 %i.inc, %arg
342   br i1 %cmp4, label %outer, label %exit
344 exit:
345   ret void
348 ; Range check can be trivially removed.
349 define void @predicated_inside_loop_signed_pos(i32 %arg) nounwind #0 {
350 ; CHECK-LABEL: @predicated_inside_loop_signed_pos(
351 ; CHECK-NEXT:  entry:
352 ; CHECK-NEXT:    br label [[OUTER:%.*]]
353 ; CHECK:       outer:
354 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
355 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
356 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
357 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
358 ; CHECK:       guarded:
359 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
360 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
361 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
362 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
363 ; CHECK:       inner.ph:
364 ; CHECK-NEXT:    br label [[INNER:%.*]]
365 ; CHECK:       inner:
366 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
367 ; CHECK:       outer.inc.loopexit:
368 ; CHECK-NEXT:    br label [[OUTER_INC]]
369 ; CHECK:       outer.inc:
370 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
371 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[SUB1]]
372 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
373 ; CHECK:       exit:
374 ; CHECK-NEXT:    ret void
376 entry:
377   br label %outer
379 outer:
380   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
381   %sub1 = sub nsw i32 %arg, 1
382   %cmp1 = icmp slt i32 0, %sub1
383   br i1 %cmp1, label %guarded, label %exit
385 guarded:
386   %sub2 = sub nsw i32 %arg, %i
387   %sub3 = sub nsw i32 %sub2, 1
388   %cmp2 = icmp slt i32 0, %sub3
389   br i1 %cmp2, label %inner.ph, label %outer.inc
391 inner.ph:
392   br label %inner
394 inner:
395   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
396   %j.inc = add nsw i32 %j, 1
397   %cmp3 = icmp slt i32 %j.inc, %sub3
398   br i1 %cmp3, label %inner, label %outer.inc
400 outer.inc:
401   %i.inc = add nsw i32 %i, 1
402   %cmp4 = icmp slt i32 %i.inc, %sub1
403   br i1 %cmp4, label %outer, label %exit
405 exit:
406   ret void
409 define void @predicated_inside_loop_unsigned(i32 %arg) nounwind #0 {
410 ; CHECK-LABEL: @predicated_inside_loop_unsigned(
411 ; CHECK-NEXT:  entry:
412 ; CHECK-NEXT:    br label [[OUTER:%.*]]
413 ; CHECK:       outer:
414 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
415 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
416 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
417 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
418 ; CHECK:       guarded:
419 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
420 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
421 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
422 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
423 ; CHECK:       inner.ph:
424 ; CHECK-NEXT:    br label [[INNER:%.*]]
425 ; CHECK:       inner:
426 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
427 ; CHECK:       outer.inc.loopexit:
428 ; CHECK-NEXT:    br label [[OUTER_INC]]
429 ; CHECK:       outer.inc:
430 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
431 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
432 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
433 ; CHECK:       exit:
434 ; CHECK-NEXT:    ret void
436 entry:
437   br label %outer
439 outer:
440   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
441   %sub1 = sub nsw i32 %arg, 1
442   %cmp1 = icmp slt i32 0, %sub1
443   br i1 %cmp1, label %guarded, label %exit
445 guarded:
446   %sub2 = sub nsw i32 %arg, %i
447   %sub3 = sub nsw i32 %sub2, 1
448   %cmp2 = icmp ult i32 0, %sub3
449   br i1 %cmp2, label %inner.ph, label %outer.inc
451 inner.ph:
452   br label %inner
454 inner:
455   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
456   %j.inc = add nsw i32 %j, 1
457   %cmp3 = icmp slt i32 %j.inc, %sub3
458   br i1 %cmp3, label %inner, label %outer.inc
460 outer.inc:
461   %i.inc = add nsw i32 %i, 1
462   %cmp4 = icmp slt i32 %i.inc, %arg
463   br i1 %cmp4, label %outer, label %exit
465 exit:
466   ret void
469 define void @test_can_predicate_simple_unsigned(i32* %p, i32* %arr) {
470 ; CHECK-LABEL: @test_can_predicate_simple_unsigned(
471 ; CHECK-NEXT:  preheader:
472 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
473 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
474 ; CHECK-NEXT:    br label [[LOOP:%.*]]
475 ; CHECK:       loop:
476 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
477 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
478 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
479 ; CHECK:       range_check_block:
480 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
481 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
482 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[BACKEDGE]], label [[FAIL:%.*]]
483 ; CHECK:       backedge:
484 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
485 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
486 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
487 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
488 ; CHECK:       exit:
489 ; CHECK-NEXT:    ret void
490 ; CHECK:       fail:
491 ; CHECK-NEXT:    unreachable
493 preheader:
494   %len = load i32, i32* %p
495   br label %loop
497 loop:
498   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
499   %zero_cond = icmp eq i32 %iv, 0
500   br i1 %zero_cond, label %exit, label %range_check_block
502 range_check_block:
503   %iv.next = sub i32 %iv, 1
504   %range_check = icmp ult i32 %iv.next, %len
505   br i1 %range_check, label %backedge, label %fail
507 backedge:
508   %el.ptr = getelementptr i32, i32* %p, i32 %iv
509   %el = load i32, i32* %el.ptr
510   %loop.cond = icmp eq i32 %el, 0
511   br i1 %loop.cond, label %loop, label %exit
513 exit:
514   ret void
516 fail:
517   unreachable
520 define void @test_can_predicate_simple_unsigned_inverted(i32* %p, i32* %arr) {
521 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted(
522 ; CHECK-NEXT:  preheader:
523 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
524 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
525 ; CHECK-NEXT:    br label [[LOOP:%.*]]
526 ; CHECK:       loop:
527 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
528 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
529 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
530 ; CHECK:       range_check_block:
531 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
532 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
533 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[FAIL:%.*]], label [[BACKEDGE]]
534 ; CHECK:       backedge:
535 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
536 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
537 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
538 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
539 ; CHECK:       exit:
540 ; CHECK-NEXT:    ret void
541 ; CHECK:       fail:
542 ; CHECK-NEXT:    unreachable
544 preheader:
545   %len = load i32, i32* %p
546   br label %loop
548 loop:
549   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
550   %zero_cond = icmp eq i32 %iv, 0
551   br i1 %zero_cond, label %exit, label %range_check_block
553 range_check_block:
554   %iv.next = sub i32 %iv, 1
555   %range_check = icmp uge i32 %iv.next, %len
556   br i1 %range_check, label %fail, label %backedge
558 backedge:
559   %el.ptr = getelementptr i32, i32* %p, i32 %iv
560   %el = load i32, i32* %el.ptr
561   %loop.cond = icmp eq i32 %el, 0
562   br i1 %loop.cond, label %loop, label %exit
564 exit:
565   ret void
567 fail:
568   unreachable
572 define void @test_can_predicate_simple_signed(i32* %p, i32* %arr) {
573 ; CHECK-LABEL: @test_can_predicate_simple_signed(
574 ; CHECK-NEXT:  preheader:
575 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
576 ; CHECK-NEXT:    br label [[LOOP:%.*]]
577 ; CHECK:       loop:
578 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
579 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
580 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
581 ; CHECK:       range_check_block:
582 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
583 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
584 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
585 ; CHECK:       backedge:
586 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
587 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
588 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
589 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
590 ; CHECK:       exit:
591 ; CHECK-NEXT:    ret void
592 ; CHECK:       fail:
593 ; CHECK-NEXT:    unreachable
595 preheader:
596   %len = load i32, i32* %p
597   br label %loop
599 loop:
600   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
601   %zero_cond = icmp eq i32 %iv, 0
602   br i1 %zero_cond, label %exit, label %range_check_block
604 range_check_block:
605   %iv.next = sub i32 %iv, 1
606   %range_check = icmp slt i32 %iv.next, %len
607   br i1 %range_check, label %backedge, label %fail
609 backedge:
610   %el.ptr = getelementptr i32, i32* %p, i32 %iv
611   %el = load i32, i32* %el.ptr
612   %loop.cond = icmp eq i32 %el, 0
613   br i1 %loop.cond, label %loop, label %exit
615 exit:
616   ret void
618 fail:
619   unreachable
622 define void @test_can_predicate_trunc_unsigned(i32* %p, i32* %arr) {
623 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned(
624 ; CHECK-NEXT:  preheader:
625 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
626 ; CHECK-NEXT:    [[START:%.*]] = zext i32 [[LEN]] to i64
627 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
628 ; CHECK-NEXT:    br label [[LOOP:%.*]]
629 ; CHECK:       loop:
630 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
631 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
632 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
633 ; CHECK:       range_check_block:
634 ; CHECK-NEXT:    [[IV_NEXT]] = sub nsw i64 [[IV]], 1
635 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
636 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[BACKEDGE]], label [[FAIL:%.*]]
637 ; CHECK:       backedge:
638 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i64 [[IV]]
639 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
640 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
641 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
642 ; CHECK:       exit:
643 ; CHECK-NEXT:    ret void
644 ; CHECK:       fail:
645 ; CHECK-NEXT:    unreachable
647 preheader:
648   %len = load i32, i32* %p
649   %start = zext i32 %len to i64
650   br label %loop
652 loop:
653   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
654   %zero_cond = icmp eq i64 %iv, 0
655   br i1 %zero_cond, label %exit, label %range_check_block
657 range_check_block:
658   %iv.next = sub i64 %iv, 1
659   %narrow = trunc i64 %iv.next to i32
660   %range_check = icmp ult i32 %narrow, %len
661   br i1 %range_check, label %backedge, label %fail
663 backedge:
664   %el.ptr = getelementptr i32, i32* %arr, i64 %iv
665   %el = load i32, i32* %el.ptr
666   %loop.cond = icmp eq i32 %el, 0
667   br i1 %loop.cond, label %loop, label %exit
669 exit:
670   ret void
672 fail:
673   unreachable
676 define void @test_can_predicate_trunc_unsigned_inverted(i32* %p, i32* %arr) {
677 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_inverted(
678 ; CHECK-NEXT:  preheader:
679 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
680 ; CHECK-NEXT:    [[START:%.*]] = zext i32 [[LEN]] to i64
681 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
682 ; CHECK-NEXT:    br label [[LOOP:%.*]]
683 ; CHECK:       loop:
684 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
685 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
686 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
687 ; CHECK:       range_check_block:
688 ; CHECK-NEXT:    [[IV_NEXT]] = sub nsw i64 [[IV]], 1
689 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
690 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[FAIL:%.*]], label [[BACKEDGE]]
691 ; CHECK:       backedge:
692 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i64 [[IV]]
693 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
694 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
695 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
696 ; CHECK:       exit:
697 ; CHECK-NEXT:    ret void
698 ; CHECK:       fail:
699 ; CHECK-NEXT:    unreachable
701 preheader:
702   %len = load i32, i32* %p
703   %start = zext i32 %len to i64
704   br label %loop
706 loop:
707   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
708   %zero_cond = icmp eq i64 %iv, 0
709   br i1 %zero_cond, label %exit, label %range_check_block
711 range_check_block:
712   %iv.next = sub i64 %iv, 1
713   %narrow = trunc i64 %iv.next to i32
714   %range_check = icmp uge i32 %narrow, %len
715   br i1 %range_check, label %fail, label %backedge
717 backedge:
718   %el.ptr = getelementptr i32, i32* %arr, i64 %iv
719   %el = load i32, i32* %el.ptr
720   %loop.cond = icmp eq i32 %el, 0
721   br i1 %loop.cond, label %loop, label %exit
723 exit:
724   ret void
726 fail:
727   unreachable
730 define void @test_can_predicate_trunc_unsigned_different_start_and_len(i32* %p, i64 %start, i32* %arr) {
731 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len(
732 ; CHECK-NEXT:  preheader:
733 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
734 ; CHECK-NEXT:    br label [[LOOP:%.*]]
735 ; CHECK:       loop:
736 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
737 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
738 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
739 ; CHECK:       range_check_block:
740 ; CHECK-NEXT:    [[IV_NEXT]] = sub i64 [[IV]], 1
741 ; CHECK-NEXT:    [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
742 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[NARROW]], [[LEN]]
743 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
744 ; CHECK:       backedge:
745 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i64 [[IV]]
746 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
747 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
748 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
749 ; CHECK:       exit:
750 ; CHECK-NEXT:    ret void
751 ; CHECK:       fail:
752 ; CHECK-NEXT:    unreachable
754 preheader:
755   %len = load i32, i32* %p
756   br label %loop
758 loop:
759   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
760   %zero_cond = icmp eq i64 %iv, 0
761   br i1 %zero_cond, label %exit, label %range_check_block
763 range_check_block:
764   %iv.next = sub i64 %iv, 1
765   %narrow = trunc i64 %iv.next to i32
766   %range_check = icmp ult i32 %narrow, %len
767   br i1 %range_check, label %backedge, label %fail
769 backedge:
770   %el.ptr = getelementptr i32, i32* %arr, i64 %iv
771   %el = load i32, i32* %el.ptr
772   %loop.cond = icmp eq i32 %el, 0
773   br i1 %loop.cond, label %loop, label %exit
775 exit:
776   ret void
778 fail:
779   unreachable
782 define void @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(i32* %p, i64 %start, i32* %arr) {
783 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(
784 ; CHECK-NEXT:  preheader:
785 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
786 ; CHECK-NEXT:    br label [[LOOP:%.*]]
787 ; CHECK:       loop:
788 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
789 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
790 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
791 ; CHECK:       range_check_block:
792 ; CHECK-NEXT:    [[IV_NEXT]] = sub i64 [[IV]], 1
793 ; CHECK-NEXT:    [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
794 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp uge i32 [[NARROW]], [[LEN]]
795 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[FAIL:%.*]], label [[BACKEDGE]]
796 ; CHECK:       backedge:
797 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i64 [[IV]]
798 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
799 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
800 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
801 ; CHECK:       exit:
802 ; CHECK-NEXT:    ret void
803 ; CHECK:       fail:
804 ; CHECK-NEXT:    unreachable
806 preheader:
807   %len = load i32, i32* %p
808   br label %loop
810 loop:
811   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
812   %zero_cond = icmp eq i64 %iv, 0
813   br i1 %zero_cond, label %exit, label %range_check_block
815 range_check_block:
816   %iv.next = sub i64 %iv, 1
817   %narrow = trunc i64 %iv.next to i32
818   %range_check = icmp uge i32 %narrow, %len
819   br i1 %range_check, label %fail, label %backedge
821 backedge:
822   %el.ptr = getelementptr i32, i32* %arr, i64 %iv
823   %el = load i32, i32* %el.ptr
824   %loop.cond = icmp eq i32 %el, 0
825   br i1 %loop.cond, label %loop, label %exit
827 exit:
828   ret void
830 fail:
831   unreachable
834 define void @test_can_predicate_simple_unsigned_different_start(i32 %start, i32* %p, i32* %arr) {
835 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_different_start(
836 ; CHECK-NEXT:  preheader:
837 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
838 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
839 ; CHECK-NEXT:    br label [[LOOP:%.*]]
840 ; CHECK:       loop:
841 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
842 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
843 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
844 ; CHECK:       range_check_block:
845 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
846 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
847 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[BACKEDGE]], label [[FAIL:%.*]]
848 ; CHECK:       backedge:
849 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
850 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
851 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
852 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
853 ; CHECK:       exit:
854 ; CHECK-NEXT:    ret void
855 ; CHECK:       fail:
856 ; CHECK-NEXT:    unreachable
858 preheader:
859   %len = load i32, i32* %p
860   br label %loop
862 loop:
863   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
864   %zero_cond = icmp eq i32 %iv, 0
865   br i1 %zero_cond, label %exit, label %range_check_block
867 range_check_block:
868   %iv.next = sub i32 %iv, 1
869   %range_check = icmp ult i32 %iv.next, %len
870   br i1 %range_check, label %backedge, label %fail
872 backedge:
873   %el.ptr = getelementptr i32, i32* %p, i32 %iv
874   %el = load i32, i32* %el.ptr
875   %loop.cond = icmp eq i32 %el, 0
876   br i1 %loop.cond, label %loop, label %exit
878 exit:
879   ret void
881 fail:
882   unreachable
885 define void @test_can_predicate_simple_unsigned_inverted_different_start(i32 %start, i32* %p, i32* %arr) {
886 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted_different_start(
887 ; CHECK-NEXT:  preheader:
888 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
889 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
890 ; CHECK-NEXT:    br label [[LOOP:%.*]]
891 ; CHECK:       loop:
892 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
893 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
894 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
895 ; CHECK:       range_check_block:
896 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
897 ; CHECK-NEXT:    [[RANGE_CHECK1:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
898 ; CHECK-NEXT:    br i1 [[RANGE_CHECK1]], label [[FAIL:%.*]], label [[BACKEDGE]]
899 ; CHECK:       backedge:
900 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
901 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
902 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
903 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
904 ; CHECK:       exit:
905 ; CHECK-NEXT:    ret void
906 ; CHECK:       fail:
907 ; CHECK-NEXT:    unreachable
909 preheader:
910   %len = load i32, i32* %p
911   br label %loop
913 loop:
914   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
915   %zero_cond = icmp eq i32 %iv, 0
916   br i1 %zero_cond, label %exit, label %range_check_block
918 range_check_block:
919   %iv.next = sub i32 %iv, 1
920   %range_check = icmp uge i32 %iv.next, %len
921   br i1 %range_check, label %fail, label %backedge
923 backedge:
924   %el.ptr = getelementptr i32, i32* %p, i32 %iv
925   %el = load i32, i32* %el.ptr
926   %loop.cond = icmp eq i32 %el, 0
927   br i1 %loop.cond, label %loop, label %exit
929 exit:
930   ret void
932 fail:
933   unreachable
937 define void @test_can_predicate_simple_signed_different_start(i32 %start, i32* %p, i32* %arr) {
938 ; CHECK-LABEL: @test_can_predicate_simple_signed_different_start(
939 ; CHECK-NEXT:  preheader:
940 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4
941 ; CHECK-NEXT:    br label [[LOOP:%.*]]
942 ; CHECK:       loop:
943 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
944 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
945 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
946 ; CHECK:       range_check_block:
947 ; CHECK-NEXT:    [[IV_NEXT]] = sub i32 [[IV]], 1
948 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
949 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
950 ; CHECK:       backedge:
951 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, i32* [[P]], i32 [[IV]]
952 ; CHECK-NEXT:    [[EL:%.*]] = load i32, i32* [[EL_PTR]], align 4
953 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
954 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
955 ; CHECK:       exit:
956 ; CHECK-NEXT:    ret void
957 ; CHECK:       fail:
958 ; CHECK-NEXT:    unreachable
960 preheader:
961   %len = load i32, i32* %p
962   br label %loop
964 loop:
965   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
966   %zero_cond = icmp eq i32 %iv, 0
967   br i1 %zero_cond, label %exit, label %range_check_block
969 range_check_block:
970   %iv.next = sub i32 %iv, 1
971   %range_check = icmp slt i32 %iv.next, %len
972   br i1 %range_check, label %backedge, label %fail
974 backedge:
975   %el.ptr = getelementptr i32, i32* %p, i32 %iv
976   %el = load i32, i32* %el.ptr
977   %loop.cond = icmp eq i32 %el, 0
978   br i1 %loop.cond, label %loop, label %exit
980 exit:
981   ret void
983 fail:
984   unreachable
987 !0 = !{i32 0, i32 2147483647}