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
4
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.
13define 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
34;
35preheader:
36  %len = load i32, i32* %p, !range !0
37  br label %loop
38
39loop:
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
43
44range_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
48
49backedge:
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
54
55exit:
56  ret void
57
58fail:
59  unreachable
60}
61
62define 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
83;
84preheader:
85  %len = load i32, i32* %p, !range !0
86  br label %loop
87
88loop:
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
92
93range_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
97
98backedge:
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
103
104exit:
105  ret void
106
107fail:
108  unreachable
109}
110
111; Cannot remove checks because the range check fails on the last iteration.
112define 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
139;
140entry:
141  %sub1 = sub nsw i32 %arg, 1
142  %cmp1 = icmp slt i32 0, %sub1
143  br i1 %cmp1, label %outer, label %exit
144
145outer:
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
151
152inner.ph:
153  br label %inner
154
155inner:
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
160
161outer.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
165
166exit:
167  ret void
168}
169
170; Range check can be removed.
171define 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
198;
199entry:
200  %sub1 = sub nsw i32 %arg, 1
201  %cmp1 = icmp slt i32 0, %sub1
202  br i1 %cmp1, label %outer, label %exit
203
204outer:
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
210
211inner.ph:
212  br label %inner
213
214inner:
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
219
220outer.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
224
225exit:
226  ret void
227}
228
229define 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
256;
257entry:
258  %sub1 = sub nsw i32 %arg, 1
259  %cmp1 = icmp slt i32 0, %sub1
260  br i1 %cmp1, label %outer, label %exit
261
262outer:
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
268
269inner.ph:
270  br label %inner
271
272inner:
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
277
278outer.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
282
283exit:
284  ret void
285}
286
287; Cannot remove checks because the range check fails on the last iteration.
288define 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
314;
315entry:
316  br label %outer
317
318outer:
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
323
324guarded:
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
329
330inner.ph:
331  br label %inner
332
333inner:
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
338
339outer.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
343
344exit:
345  ret void
346}
347
348; Range check can be trivially removed.
349define 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
375;
376entry:
377  br label %outer
378
379outer:
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
384
385guarded:
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
390
391inner.ph:
392  br label %inner
393
394inner:
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
399
400outer.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
404
405exit:
406  ret void
407}
408
409define 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
435;
436entry:
437  br label %outer
438
439outer:
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
444
445guarded:
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
450
451inner.ph:
452  br label %inner
453
454inner:
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
459
460outer.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
464
465exit:
466  ret void
467}
468
469define 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
492;
493preheader:
494  %len = load i32, i32* %p
495  br label %loop
496
497loop:
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
501
502range_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
506
507backedge:
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
512
513exit:
514  ret void
515
516fail:
517  unreachable
518}
519
520define 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
543;
544preheader:
545  %len = load i32, i32* %p
546  br label %loop
547
548loop:
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
552
553range_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
557
558backedge:
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
563
564exit:
565  ret void
566
567fail:
568  unreachable
569}
570
571
572define 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
594;
595preheader:
596  %len = load i32, i32* %p
597  br label %loop
598
599loop:
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
603
604range_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
608
609backedge:
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
614
615exit:
616  ret void
617
618fail:
619  unreachable
620}
621
622define 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
646;
647preheader:
648  %len = load i32, i32* %p
649  %start = zext i32 %len to i64
650  br label %loop
651
652loop:
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
656
657range_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
662
663backedge:
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
668
669exit:
670  ret void
671
672fail:
673  unreachable
674}
675
676define 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
700;
701preheader:
702  %len = load i32, i32* %p
703  %start = zext i32 %len to i64
704  br label %loop
705
706loop:
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
710
711range_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
716
717backedge:
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
722
723exit:
724  ret void
725
726fail:
727  unreachable
728}
729
730define 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
753;
754preheader:
755  %len = load i32, i32* %p
756  br label %loop
757
758loop:
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
762
763range_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
768
769backedge:
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
774
775exit:
776  ret void
777
778fail:
779  unreachable
780}
781
782define 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
805;
806preheader:
807  %len = load i32, i32* %p
808  br label %loop
809
810loop:
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
814
815range_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
820
821backedge:
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
826
827exit:
828  ret void
829
830fail:
831  unreachable
832}
833
834define 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
857;
858preheader:
859  %len = load i32, i32* %p
860  br label %loop
861
862loop:
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
866
867range_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
871
872backedge:
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
877
878exit:
879  ret void
880
881fail:
882  unreachable
883}
884
885define 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
908;
909preheader:
910  %len = load i32, i32* %p
911  br label %loop
912
913loop:
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
917
918range_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
922
923backedge:
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
928
929exit:
930  ret void
931
932fail:
933  unreachable
934}
935
936
937define 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
959;
960preheader:
961  %len = load i32, i32* %p
962  br label %loop
963
964loop:
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
968
969range_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
973
974backedge:
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
979
980exit:
981  ret void
982
983fail:
984  unreachable
985}
986
987!0 = !{i32 0, i32 2147483647}
988