[DAG] TransformFPLoadStorePair - early out if we're not loading a simple type
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / predicated_ranges.ll
blobd005804ff633e36e2deb70b1bb7c188bcc798cee
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=indvars -S < %s | FileCheck %s
4 ; Check that we are able to remove the range check basing on the following facts:
5 ; 0 <= len <= MAX_INT [1];
6 ; iv starts from len and goes down stopping at zero and [1], therefore
7 ;   0 <= iv <= len [2];
8 ; 3. In range_check_block, iv != 0 and [2], therefore
9 ;   1 <= iv <= len [3];
10 ; 4. iv.next = iv - 1 and [3], therefore
11 ;   0 <= iv.next < len.
12 define void @test_predicated_simple_unsigned(ptr %p, ptr %arr) {
13 ; CHECK-LABEL: @test_predicated_simple_unsigned(
14 ; CHECK-NEXT:  preheader:
15 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0:![0-9]+]]
16 ; CHECK-NEXT:    br label [[LOOP:%.*]]
17 ; CHECK:       loop:
18 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
19 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
20 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
21 ; CHECK:       range_check_block:
22 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1
23 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
24 ; CHECK:       backedge:
25 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
26 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
27 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
28 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
29 ; CHECK:       exit:
30 ; CHECK-NEXT:    ret void
31 ; CHECK:       fail:
32 ; CHECK-NEXT:    unreachable
34 preheader:
35   %len = load i32, ptr %p, !range !0
36   br label %loop
38 loop:
39   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
40   %zero_cond = icmp eq i32 %iv, 0
41   br i1 %zero_cond, label %exit, label %range_check_block
43 range_check_block:
44   %iv.next = sub i32 %iv, 1
45   %range_check = icmp ult i32 %iv.next, %len
46   br i1 %range_check, label %backedge, label %fail
48 backedge:
49   %el.ptr = getelementptr i32, ptr %p, i32 %iv
50   %el = load i32, ptr %el.ptr
51   %loop.cond = icmp eq i32 %el, 0
52   br i1 %loop.cond, label %loop, label %exit
54 exit:
55   ret void
57 fail:
58   unreachable
61 define void @test_predicated_simple_signed(ptr %p, ptr %arr) {
62 ; CHECK-LABEL: @test_predicated_simple_signed(
63 ; CHECK-NEXT:  preheader:
64 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4, !range [[RNG0]]
65 ; CHECK-NEXT:    br label [[LOOP:%.*]]
66 ; CHECK:       loop:
67 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
68 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
69 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
70 ; CHECK:       range_check_block:
71 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw nsw i32 [[IV]], 1
72 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
73 ; CHECK:       backedge:
74 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
75 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
76 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
77 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
78 ; CHECK:       exit:
79 ; CHECK-NEXT:    ret void
80 ; CHECK:       fail:
81 ; CHECK-NEXT:    unreachable
83 preheader:
84   %len = load i32, ptr %p, !range !0
85   br label %loop
87 loop:
88   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
89   %zero_cond = icmp eq i32 %iv, 0
90   br i1 %zero_cond, label %exit, label %range_check_block
92 range_check_block:
93   %iv.next = sub i32 %iv, 1
94   %range_check = icmp slt i32 %iv.next, %len
95   br i1 %range_check, label %backedge, label %fail
97 backedge:
98   %el.ptr = getelementptr i32, ptr %p, i32 %iv
99   %el = load i32, ptr %el.ptr
100   %loop.cond = icmp eq i32 %el, 0
101   br i1 %loop.cond, label %loop, label %exit
103 exit:
104   ret void
106 fail:
107   unreachable
110 ; Cannot remove checks because the range check fails on the last iteration.
111 define void @predicated_outside_loop_signed_neg(i32 %arg) nounwind #0 {
112 ; CHECK-LABEL: @predicated_outside_loop_signed_neg(
113 ; CHECK-NEXT:  entry:
114 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
115 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
116 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
117 ; CHECK:       outer.preheader:
118 ; CHECK-NEXT:    br label [[OUTER:%.*]]
119 ; CHECK:       outer:
120 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
121 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
122 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
123 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
124 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
125 ; CHECK:       inner.ph:
126 ; CHECK-NEXT:    br label [[INNER:%.*]]
127 ; CHECK:       inner:
128 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
129 ; CHECK:       outer.inc.loopexit:
130 ; CHECK-NEXT:    br label [[OUTER_INC]]
131 ; CHECK:       outer.inc:
132 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
133 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
134 ; CHECK:       exit.loopexit:
135 ; CHECK-NEXT:    br label [[EXIT]]
136 ; CHECK:       exit:
137 ; CHECK-NEXT:    ret void
139 entry:
140   %sub1 = sub nsw i32 %arg, 1
141   %cmp1 = icmp slt i32 0, %sub1
142   br i1 %cmp1, label %outer, label %exit
144 outer:
145   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
146   %sub2 = sub nsw i32 %arg, %i
147   %sub3 = sub nsw i32 %sub2, 1
148   %cmp2 = icmp slt i32 0, %sub3
149   br i1 %cmp2, label %inner.ph, label %outer.inc
151 inner.ph:
152   br label %inner
154 inner:
155   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
156   %j.inc = add nsw i32 %j, 1
157   %cmp3 = icmp slt i32 %j.inc, %sub3
158   br i1 %cmp3, label %inner, label %outer.inc
160 outer.inc:
161   %i.inc = add nsw i32 %i, 1
162   %cmp4 = icmp slt i32 %i.inc, %arg
163   br i1 %cmp4, label %outer, label %exit
165 exit:
166   ret void
169 ; Range check can be removed.
170 define void @predicated_outside_loop_signed_pos(i32 %arg) nounwind #0 {
171 ; CHECK-LABEL: @predicated_outside_loop_signed_pos(
172 ; CHECK-NEXT:  entry:
173 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
174 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
175 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
176 ; CHECK:       outer.preheader:
177 ; CHECK-NEXT:    br label [[OUTER:%.*]]
178 ; CHECK:       outer:
179 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
180 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
181 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
182 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
183 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
184 ; CHECK:       inner.ph:
185 ; CHECK-NEXT:    br label [[INNER:%.*]]
186 ; CHECK:       inner:
187 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
188 ; CHECK:       outer.inc.loopexit:
189 ; CHECK-NEXT:    br label [[OUTER_INC]]
190 ; CHECK:       outer.inc:
191 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
192 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
193 ; CHECK:       exit.loopexit:
194 ; CHECK-NEXT:    br label [[EXIT]]
195 ; CHECK:       exit:
196 ; CHECK-NEXT:    ret void
198 entry:
199   %sub1 = sub nsw i32 %arg, 1
200   %cmp1 = icmp slt i32 0, %sub1
201   br i1 %cmp1, label %outer, label %exit
203 outer:
204   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
205   %sub2 = sub nsw i32 %arg, %i
206   %sub3 = sub nsw i32 %sub2, 1
207   %cmp2 = icmp slt i32 0, %sub3
208   br i1 %cmp2, label %inner.ph, label %outer.inc
210 inner.ph:
211   br label %inner
213 inner:
214   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
215   %j.inc = add nsw i32 %j, 1
216   %cmp3 = icmp slt i32 %j.inc, %sub3
217   br i1 %cmp3, label %inner, label %outer.inc
219 outer.inc:
220   %i.inc = add nsw i32 %i, 1
221   %cmp4 = icmp slt i32 %i.inc, %sub1
222   br i1 %cmp4, label %outer, label %exit
224 exit:
225   ret void
228 define void @predicated_outside_loop_unsigned(i32 %arg) nounwind #0 {
229 ; CHECK-LABEL: @predicated_outside_loop_unsigned(
230 ; CHECK-NEXT:  entry:
231 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
232 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
233 ; CHECK-NEXT:    br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
234 ; CHECK:       outer.preheader:
235 ; CHECK-NEXT:    br label [[OUTER:%.*]]
236 ; CHECK:       outer:
237 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
238 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
239 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
240 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
241 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
242 ; CHECK:       inner.ph:
243 ; CHECK-NEXT:    br label [[INNER:%.*]]
244 ; CHECK:       inner:
245 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
246 ; CHECK:       outer.inc.loopexit:
247 ; CHECK-NEXT:    br label [[OUTER_INC]]
248 ; CHECK:       outer.inc:
249 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
250 ; CHECK-NEXT:    br i1 false, label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
251 ; CHECK:       exit.loopexit:
252 ; CHECK-NEXT:    br label [[EXIT]]
253 ; CHECK:       exit:
254 ; CHECK-NEXT:    ret void
256 entry:
257   %sub1 = sub nsw i32 %arg, 1
258   %cmp1 = icmp slt i32 0, %sub1
259   br i1 %cmp1, label %outer, label %exit
261 outer:
262   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
263   %sub2 = sub nsw i32 %arg, %i
264   %sub3 = sub nsw i32 %sub2, 1
265   %cmp2 = icmp ult i32 0, %sub3
266   br i1 %cmp2, label %inner.ph, label %outer.inc
268 inner.ph:
269   br label %inner
271 inner:
272   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
273   %j.inc = add nsw i32 %j, 1
274   %cmp3 = icmp slt i32 %j.inc, %sub3
275   br i1 %cmp3, label %inner, label %outer.inc
277 outer.inc:
278   %i.inc = add nsw i32 %i, 1
279   %cmp4 = icmp slt i32 %i.inc, %arg
280   br i1 %cmp4, label %outer, label %exit
282 exit:
283   ret void
286 ; Cannot remove checks because the range check fails on the last iteration.
287 define void @predicated_inside_loop_signed_neg(i32 %arg) nounwind #0 {
288 ; CHECK-LABEL: @predicated_inside_loop_signed_neg(
289 ; CHECK-NEXT:  entry:
290 ; CHECK-NEXT:    br label [[OUTER:%.*]]
291 ; CHECK:       outer:
292 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
293 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
294 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
295 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
296 ; CHECK:       guarded:
297 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
298 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
299 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
300 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
301 ; CHECK:       inner.ph:
302 ; CHECK-NEXT:    br label [[INNER:%.*]]
303 ; CHECK:       inner:
304 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
305 ; CHECK:       outer.inc.loopexit:
306 ; CHECK-NEXT:    br label [[OUTER_INC]]
307 ; CHECK:       outer.inc:
308 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
309 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
310 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
311 ; CHECK:       exit:
312 ; CHECK-NEXT:    ret void
314 entry:
315   br label %outer
317 outer:
318   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
319   %sub1 = sub nsw i32 %arg, 1
320   %cmp1 = icmp slt i32 0, %sub1
321   br i1 %cmp1, label %guarded, label %exit
323 guarded:
324   %sub2 = sub nsw i32 %arg, %i
325   %sub3 = sub nsw i32 %sub2, 1
326   %cmp2 = icmp slt i32 0, %sub3
327   br i1 %cmp2, label %inner.ph, label %outer.inc
329 inner.ph:
330   br label %inner
332 inner:
333   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
334   %j.inc = add nsw i32 %j, 1
335   %cmp3 = icmp slt i32 %j.inc, %sub3
336   br i1 %cmp3, label %inner, label %outer.inc
338 outer.inc:
339   %i.inc = add nsw i32 %i, 1
340   %cmp4 = icmp slt i32 %i.inc, %arg
341   br i1 %cmp4, label %outer, label %exit
343 exit:
344   ret void
347 ; Range check can be trivially removed.
348 define void @predicated_inside_loop_signed_pos(i32 %arg) nounwind #0 {
349 ; CHECK-LABEL: @predicated_inside_loop_signed_pos(
350 ; CHECK-NEXT:  entry:
351 ; CHECK-NEXT:    br label [[OUTER:%.*]]
352 ; CHECK:       outer:
353 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
354 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
355 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
356 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
357 ; CHECK:       guarded:
358 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
359 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
360 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
361 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
362 ; CHECK:       inner.ph:
363 ; CHECK-NEXT:    br label [[INNER:%.*]]
364 ; CHECK:       inner:
365 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
366 ; CHECK:       outer.inc.loopexit:
367 ; CHECK-NEXT:    br label [[OUTER_INC]]
368 ; CHECK:       outer.inc:
369 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
370 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[SUB1]]
371 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
372 ; CHECK:       exit:
373 ; CHECK-NEXT:    ret void
375 entry:
376   br label %outer
378 outer:
379   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
380   %sub1 = sub nsw i32 %arg, 1
381   %cmp1 = icmp slt i32 0, %sub1
382   br i1 %cmp1, label %guarded, label %exit
384 guarded:
385   %sub2 = sub nsw i32 %arg, %i
386   %sub3 = sub nsw i32 %sub2, 1
387   %cmp2 = icmp slt i32 0, %sub3
388   br i1 %cmp2, label %inner.ph, label %outer.inc
390 inner.ph:
391   br label %inner
393 inner:
394   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
395   %j.inc = add nsw i32 %j, 1
396   %cmp3 = icmp slt i32 %j.inc, %sub3
397   br i1 %cmp3, label %inner, label %outer.inc
399 outer.inc:
400   %i.inc = add nsw i32 %i, 1
401   %cmp4 = icmp slt i32 %i.inc, %sub1
402   br i1 %cmp4, label %outer, label %exit
404 exit:
405   ret void
408 define void @predicated_inside_loop_unsigned(i32 %arg) nounwind #0 {
409 ; CHECK-LABEL: @predicated_inside_loop_unsigned(
410 ; CHECK-NEXT:  entry:
411 ; CHECK-NEXT:    br label [[OUTER:%.*]]
412 ; CHECK:       outer:
413 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_INC:%.*]] ]
414 ; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
415 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
416 ; CHECK-NEXT:    br i1 [[CMP1]], label [[GUARDED:%.*]], label [[EXIT:%.*]]
417 ; CHECK:       guarded:
418 ; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
419 ; CHECK-NEXT:    [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
420 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i32 0, [[SUB3]]
421 ; CHECK-NEXT:    br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
422 ; CHECK:       inner.ph:
423 ; CHECK-NEXT:    br label [[INNER:%.*]]
424 ; CHECK:       inner:
425 ; CHECK-NEXT:    br i1 false, label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
426 ; CHECK:       outer.inc.loopexit:
427 ; CHECK-NEXT:    br label [[OUTER_INC]]
428 ; CHECK:       outer.inc:
429 ; CHECK-NEXT:    [[I_INC]] = add nuw nsw i32 [[I]], 1
430 ; CHECK-NEXT:    [[CMP4:%.*]] = icmp slt i32 [[I_INC]], [[ARG]]
431 ; CHECK-NEXT:    br i1 [[CMP4]], label [[OUTER]], label [[EXIT]]
432 ; CHECK:       exit:
433 ; CHECK-NEXT:    ret void
435 entry:
436   br label %outer
438 outer:
439   %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
440   %sub1 = sub nsw i32 %arg, 1
441   %cmp1 = icmp slt i32 0, %sub1
442   br i1 %cmp1, label %guarded, label %exit
444 guarded:
445   %sub2 = sub nsw i32 %arg, %i
446   %sub3 = sub nsw i32 %sub2, 1
447   %cmp2 = icmp ult i32 0, %sub3
448   br i1 %cmp2, label %inner.ph, label %outer.inc
450 inner.ph:
451   br label %inner
453 inner:
454   %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
455   %j.inc = add nsw i32 %j, 1
456   %cmp3 = icmp slt i32 %j.inc, %sub3
457   br i1 %cmp3, label %inner, label %outer.inc
459 outer.inc:
460   %i.inc = add nsw i32 %i, 1
461   %cmp4 = icmp slt i32 %i.inc, %arg
462   br i1 %cmp4, label %outer, label %exit
464 exit:
465   ret void
468 define void @test_can_predicate_simple_unsigned(ptr %p, ptr %arr) {
469 ; CHECK-LABEL: @test_can_predicate_simple_unsigned(
470 ; CHECK-NEXT:  preheader:
471 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
472 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
473 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
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 nuw i32 [[IV]], 1
481 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
482 ; CHECK:       backedge:
483 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
484 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
485 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
486 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
487 ; CHECK:       exit:
488 ; CHECK-NEXT:    ret void
489 ; CHECK:       fail:
490 ; CHECK-NEXT:    unreachable
492 preheader:
493   %len = load i32, ptr %p
494   br label %loop
496 loop:
497   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
498   %zero_cond = icmp eq i32 %iv, 0
499   br i1 %zero_cond, label %exit, label %range_check_block
501 range_check_block:
502   %iv.next = sub i32 %iv, 1
503   %range_check = icmp ult i32 %iv.next, %len
504   br i1 %range_check, label %backedge, label %fail
506 backedge:
507   %el.ptr = getelementptr i32, ptr %p, i32 %iv
508   %el = load i32, ptr %el.ptr
509   %loop.cond = icmp eq i32 %el, 0
510   br i1 %loop.cond, label %loop, label %exit
512 exit:
513   ret void
515 fail:
516   unreachable
519 define void @test_can_predicate_simple_unsigned_inverted(ptr %p, ptr %arr) {
520 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted(
521 ; CHECK-NEXT:  preheader:
522 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
523 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
524 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
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 nuw i32 [[IV]], 1
532 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
533 ; CHECK:       backedge:
534 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
535 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
536 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
537 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
538 ; CHECK:       exit:
539 ; CHECK-NEXT:    ret void
540 ; CHECK:       fail:
541 ; CHECK-NEXT:    unreachable
543 preheader:
544   %len = load i32, ptr %p
545   br label %loop
547 loop:
548   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
549   %zero_cond = icmp eq i32 %iv, 0
550   br i1 %zero_cond, label %exit, label %range_check_block
552 range_check_block:
553   %iv.next = sub i32 %iv, 1
554   %range_check = icmp uge i32 %iv.next, %len
555   br i1 %range_check, label %fail, label %backedge
557 backedge:
558   %el.ptr = getelementptr i32, ptr %p, i32 %iv
559   %el = load i32, ptr %el.ptr
560   %loop.cond = icmp eq i32 %el, 0
561   br i1 %loop.cond, label %loop, label %exit
563 exit:
564   ret void
566 fail:
567   unreachable
571 define void @test_can_predicate_simple_signed(ptr %p, ptr %arr) {
572 ; CHECK-LABEL: @test_can_predicate_simple_signed(
573 ; CHECK-NEXT:  preheader:
574 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
575 ; CHECK-NEXT:    br label [[LOOP:%.*]]
576 ; CHECK:       loop:
577 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[LEN]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
578 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
579 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
580 ; CHECK:       range_check_block:
581 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw i32 [[IV]], 1
582 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
583 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
584 ; CHECK:       backedge:
585 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
586 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
587 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
588 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
589 ; CHECK:       exit:
590 ; CHECK-NEXT:    ret void
591 ; CHECK:       fail:
592 ; CHECK-NEXT:    unreachable
594 preheader:
595   %len = load i32, ptr %p
596   br label %loop
598 loop:
599   %iv = phi i32 [%len, %preheader], [%iv.next, %backedge]
600   %zero_cond = icmp eq i32 %iv, 0
601   br i1 %zero_cond, label %exit, label %range_check_block
603 range_check_block:
604   %iv.next = sub i32 %iv, 1
605   %range_check = icmp slt i32 %iv.next, %len
606   br i1 %range_check, label %backedge, label %fail
608 backedge:
609   %el.ptr = getelementptr i32, ptr %p, i32 %iv
610   %el = load i32, ptr %el.ptr
611   %loop.cond = icmp eq i32 %el, 0
612   br i1 %loop.cond, label %loop, label %exit
614 exit:
615   ret void
617 fail:
618   unreachable
621 define void @test_can_predicate_trunc_unsigned(ptr %p, ptr %arr) {
622 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned(
623 ; CHECK-NEXT:  preheader:
624 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
625 ; CHECK-NEXT:    [[START:%.*]] = zext i32 [[LEN]] to i64
626 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
627 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
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 nuw nsw i64 [[IV]], 1
635 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
636 ; CHECK:       backedge:
637 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
638 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
639 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
640 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
641 ; CHECK:       exit:
642 ; CHECK-NEXT:    ret void
643 ; CHECK:       fail:
644 ; CHECK-NEXT:    unreachable
646 preheader:
647   %len = load i32, ptr %p
648   %start = zext i32 %len to i64
649   br label %loop
651 loop:
652   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
653   %zero_cond = icmp eq i64 %iv, 0
654   br i1 %zero_cond, label %exit, label %range_check_block
656 range_check_block:
657   %iv.next = sub i64 %iv, 1
658   %narrow = trunc i64 %iv.next to i32
659   %range_check = icmp ult i32 %narrow, %len
660   br i1 %range_check, label %backedge, label %fail
662 backedge:
663   %el.ptr = getelementptr i32, ptr %arr, i64 %iv
664   %el = load i32, ptr %el.ptr
665   %loop.cond = icmp eq i32 %el, 0
666   br i1 %loop.cond, label %loop, label %exit
668 exit:
669   ret void
671 fail:
672   unreachable
675 define void @test_can_predicate_trunc_unsigned_inverted(ptr %p, ptr %arr) {
676 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_inverted(
677 ; CHECK-NEXT:  preheader:
678 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
679 ; CHECK-NEXT:    [[START:%.*]] = zext i32 [[LEN]] to i64
680 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LEN]], -1
681 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
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 nuw nsw i64 [[IV]], 1
689 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
690 ; CHECK:       backedge:
691 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
692 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
693 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
694 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
695 ; CHECK:       exit:
696 ; CHECK-NEXT:    ret void
697 ; CHECK:       fail:
698 ; CHECK-NEXT:    unreachable
700 preheader:
701   %len = load i32, ptr %p
702   %start = zext i32 %len to i64
703   br label %loop
705 loop:
706   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
707   %zero_cond = icmp eq i64 %iv, 0
708   br i1 %zero_cond, label %exit, label %range_check_block
710 range_check_block:
711   %iv.next = sub i64 %iv, 1
712   %narrow = trunc i64 %iv.next to i32
713   %range_check = icmp uge i32 %narrow, %len
714   br i1 %range_check, label %fail, label %backedge
716 backedge:
717   %el.ptr = getelementptr i32, ptr %arr, i64 %iv
718   %el = load i32, ptr %el.ptr
719   %loop.cond = icmp eq i32 %el, 0
720   br i1 %loop.cond, label %loop, label %exit
722 exit:
723   ret void
725 fail:
726   unreachable
729 define void @test_can_predicate_trunc_unsigned_different_start_and_len(ptr %p, i64 %start, ptr %arr) {
730 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len(
731 ; CHECK-NEXT:  preheader:
732 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
733 ; CHECK-NEXT:    br label [[LOOP:%.*]]
734 ; CHECK:       loop:
735 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
736 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
737 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
738 ; CHECK:       range_check_block:
739 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw i64 [[IV]], 1
740 ; CHECK-NEXT:    [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
741 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp ult i32 [[NARROW]], [[LEN]]
742 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
743 ; CHECK:       backedge:
744 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
745 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
746 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
747 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
748 ; CHECK:       exit:
749 ; CHECK-NEXT:    ret void
750 ; CHECK:       fail:
751 ; CHECK-NEXT:    unreachable
753 preheader:
754   %len = load i32, ptr %p
755   br label %loop
757 loop:
758   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
759   %zero_cond = icmp eq i64 %iv, 0
760   br i1 %zero_cond, label %exit, label %range_check_block
762 range_check_block:
763   %iv.next = sub i64 %iv, 1
764   %narrow = trunc i64 %iv.next to i32
765   %range_check = icmp ult i32 %narrow, %len
766   br i1 %range_check, label %backedge, label %fail
768 backedge:
769   %el.ptr = getelementptr i32, ptr %arr, i64 %iv
770   %el = load i32, ptr %el.ptr
771   %loop.cond = icmp eq i32 %el, 0
772   br i1 %loop.cond, label %loop, label %exit
774 exit:
775   ret void
777 fail:
778   unreachable
781 define void @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(ptr %p, i64 %start, ptr %arr) {
782 ; CHECK-LABEL: @test_can_predicate_trunc_unsigned_different_start_and_len_inverted(
783 ; CHECK-NEXT:  preheader:
784 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
785 ; CHECK-NEXT:    br label [[LOOP:%.*]]
786 ; CHECK:       loop:
787 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
788 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i64 [[IV]], 0
789 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
790 ; CHECK:       range_check_block:
791 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw i64 [[IV]], 1
792 ; CHECK-NEXT:    [[NARROW:%.*]] = trunc i64 [[IV_NEXT]] to i32
793 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp uge i32 [[NARROW]], [[LEN]]
794 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[FAIL:%.*]], label [[BACKEDGE]]
795 ; CHECK:       backedge:
796 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i64 [[IV]]
797 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
798 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
799 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
800 ; CHECK:       exit:
801 ; CHECK-NEXT:    ret void
802 ; CHECK:       fail:
803 ; CHECK-NEXT:    unreachable
805 preheader:
806   %len = load i32, ptr %p
807   br label %loop
809 loop:
810   %iv = phi i64 [%start, %preheader], [%iv.next, %backedge]
811   %zero_cond = icmp eq i64 %iv, 0
812   br i1 %zero_cond, label %exit, label %range_check_block
814 range_check_block:
815   %iv.next = sub i64 %iv, 1
816   %narrow = trunc i64 %iv.next to i32
817   %range_check = icmp uge i32 %narrow, %len
818   br i1 %range_check, label %fail, label %backedge
820 backedge:
821   %el.ptr = getelementptr i32, ptr %arr, i64 %iv
822   %el = load i32, ptr %el.ptr
823   %loop.cond = icmp eq i32 %el, 0
824   br i1 %loop.cond, label %loop, label %exit
826 exit:
827   ret void
829 fail:
830   unreachable
833 define void @test_can_predicate_simple_unsigned_different_start(i32 %start, ptr %p, ptr %arr) {
834 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_different_start(
835 ; CHECK-NEXT:  preheader:
836 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
837 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
838 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp ult i32 [[TMP0]], [[LEN]]
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 nuw i32 [[IV]], 1
846 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[BACKEDGE]], label [[FAIL:%.*]]
847 ; CHECK:       backedge:
848 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
849 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
850 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
851 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
852 ; CHECK:       exit:
853 ; CHECK-NEXT:    ret void
854 ; CHECK:       fail:
855 ; CHECK-NEXT:    unreachable
857 preheader:
858   %len = load i32, ptr %p
859   br label %loop
861 loop:
862   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
863   %zero_cond = icmp eq i32 %iv, 0
864   br i1 %zero_cond, label %exit, label %range_check_block
866 range_check_block:
867   %iv.next = sub i32 %iv, 1
868   %range_check = icmp ult i32 %iv.next, %len
869   br i1 %range_check, label %backedge, label %fail
871 backedge:
872   %el.ptr = getelementptr i32, ptr %p, i32 %iv
873   %el = load i32, ptr %el.ptr
874   %loop.cond = icmp eq i32 %el, 0
875   br i1 %loop.cond, label %loop, label %exit
877 exit:
878   ret void
880 fail:
881   unreachable
884 define void @test_can_predicate_simple_unsigned_inverted_different_start(i32 %start, ptr %p, ptr %arr) {
885 ; CHECK-LABEL: @test_can_predicate_simple_unsigned_inverted_different_start(
886 ; CHECK-NEXT:  preheader:
887 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
888 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[START:%.*]], -1
889 ; CHECK-NEXT:    [[RANGE_CHECK_FIRST_ITER:%.*]] = icmp uge i32 [[TMP0]], [[LEN]]
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 nuw i32 [[IV]], 1
897 ; CHECK-NEXT:    br i1 [[RANGE_CHECK_FIRST_ITER]], label [[FAIL:%.*]], label [[BACKEDGE]]
898 ; CHECK:       backedge:
899 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
900 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
901 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
902 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
903 ; CHECK:       exit:
904 ; CHECK-NEXT:    ret void
905 ; CHECK:       fail:
906 ; CHECK-NEXT:    unreachable
908 preheader:
909   %len = load i32, ptr %p
910   br label %loop
912 loop:
913   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
914   %zero_cond = icmp eq i32 %iv, 0
915   br i1 %zero_cond, label %exit, label %range_check_block
917 range_check_block:
918   %iv.next = sub i32 %iv, 1
919   %range_check = icmp uge i32 %iv.next, %len
920   br i1 %range_check, label %fail, label %backedge
922 backedge:
923   %el.ptr = getelementptr i32, ptr %p, i32 %iv
924   %el = load i32, ptr %el.ptr
925   %loop.cond = icmp eq i32 %el, 0
926   br i1 %loop.cond, label %loop, label %exit
928 exit:
929   ret void
931 fail:
932   unreachable
936 define void @test_can_predicate_simple_signed_different_start(i32 %start, ptr %p, ptr %arr) {
937 ; CHECK-LABEL: @test_can_predicate_simple_signed_different_start(
938 ; CHECK-NEXT:  preheader:
939 ; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[P:%.*]], align 4
940 ; CHECK-NEXT:    br label [[LOOP:%.*]]
941 ; CHECK:       loop:
942 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[PREHEADER:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
943 ; CHECK-NEXT:    [[ZERO_COND:%.*]] = icmp eq i32 [[IV]], 0
944 ; CHECK-NEXT:    br i1 [[ZERO_COND]], label [[EXIT:%.*]], label [[RANGE_CHECK_BLOCK:%.*]]
945 ; CHECK:       range_check_block:
946 ; CHECK-NEXT:    [[IV_NEXT]] = sub nuw i32 [[IV]], 1
947 ; CHECK-NEXT:    [[RANGE_CHECK:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
948 ; CHECK-NEXT:    br i1 [[RANGE_CHECK]], label [[BACKEDGE]], label [[FAIL:%.*]]
949 ; CHECK:       backedge:
950 ; CHECK-NEXT:    [[EL_PTR:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
951 ; CHECK-NEXT:    [[EL:%.*]] = load i32, ptr [[EL_PTR]], align 4
952 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp eq i32 [[EL]], 0
953 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT]]
954 ; CHECK:       exit:
955 ; CHECK-NEXT:    ret void
956 ; CHECK:       fail:
957 ; CHECK-NEXT:    unreachable
959 preheader:
960   %len = load i32, ptr %p
961   br label %loop
963 loop:
964   %iv = phi i32 [%start, %preheader], [%iv.next, %backedge]
965   %zero_cond = icmp eq i32 %iv, 0
966   br i1 %zero_cond, label %exit, label %range_check_block
968 range_check_block:
969   %iv.next = sub i32 %iv, 1
970   %range_check = icmp slt i32 %iv.next, %len
971   br i1 %range_check, label %backedge, label %fail
973 backedge:
974   %el.ptr = getelementptr i32, ptr %p, i32 %iv
975   %el = load i32, ptr %el.ptr
976   %loop.cond = icmp eq i32 %el, 0
977   br i1 %loop.cond, label %loop, label %exit
979 exit:
980   ret void
982 fail:
983   unreachable
986 !0 = !{i32 0, i32 2147483647}