Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / monotonic-pointer-phis-early-exits.ll
blobf05f324ef9322f276036846b4047c83552d97d56
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
7 declare void @use(ptr)
8 declare void @use.i1(i1)
9 declare void @llvm.assume(i1)
10 declare i1 @cond()
12 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
13 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(
14 ; CHECK-NEXT:  entry:
15 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
16 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
17 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
18 ; CHECK:       loop.ph:
19 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
20 ; CHECK:       loop.header:
21 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
22 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
23 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
24 ; CHECK:       for.body:
25 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
26 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
27 ; CHECK:       loop.next:
28 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
29 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
30 ; CHECK:       loop.latch:
31 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
32 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
33 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
34 ; CHECK:       exit:
35 ; CHECK-NEXT:    ret void
37 entry:
38   %upper = getelementptr inbounds i32, ptr %start, i16 %len
39   %len.neg = icmp slt i16 %len, 0
40   br i1 %len.neg, label %exit, label %loop.ph
42 loop.ph:
43   br label %loop.header
45 loop.header:
46   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
47   %c = icmp eq ptr %ptr.iv, %upper
48   br i1 %c, label %exit, label %for.body
50 for.body:
51   %c.1 = call i1 @cond()
52   br i1 %c.1, label %loop.next, label %exit
54 loop.next:
55   %t.1 = icmp uge ptr %ptr.iv, %start
56   %t.2 = icmp ult ptr %ptr.iv, %upper
57   %and = and i1 %t.1, %t.2
58   br i1 %and, label %loop.latch, label %exit
60 loop.latch:
61   call void @use(ptr %ptr.iv)
62   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
63   br label %loop.header
65 exit:
66   ret void
69 define void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
70 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(
71 ; CHECK-NEXT:  entry:
72 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
73 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
74 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
75 ; CHECK:       loop.ph:
76 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
77 ; CHECK:       loop.header:
78 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
79 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
80 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
81 ; CHECK:       for.body:
82 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
83 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
84 ; CHECK:       loop.next:
85 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
86 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
87 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
88 ; CHECK:       loop.latch:
89 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
90 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
91 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
92 ; CHECK:       exit:
93 ; CHECK-NEXT:    ret void
95 entry:
96   %upper = getelementptr inbounds i8, ptr %start, i16 %len
97   %len.neg = icmp slt i16 %len, 0
98   br i1 %len.neg, label %exit, label %loop.ph
100 loop.ph:
101   br label %loop.header
103 loop.header:
104   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
105   %c = icmp eq ptr %ptr.iv, %upper
106   br i1 %c, label %exit, label %for.body
108 for.body:
109   %c.1 = call i1 @cond()
110   br i1 %c.1, label %loop.next, label %exit
112 loop.next:
113   %t.1 = icmp uge ptr %ptr.iv, %start
114   %t.2 = icmp ult ptr %ptr.iv, %upper
115   %and = and i1 %t.1, %t.2
116   br i1 %and, label %loop.latch, label %exit
118 loop.latch:
119   call void @use(ptr %ptr.iv)
120   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
121   br label %loop.header
123 exit:
124   ret void
127 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
128 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(
129 ; CHECK-NEXT:  entry:
130 ; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
131 ; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
132 ; CHECK:       loop.ph:
133 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
134 ; CHECK:       loop.header:
135 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
136 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
137 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
138 ; CHECK:       for.body:
139 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
140 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
141 ; CHECK:       loop.next:
142 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
143 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
144 ; CHECK:       loop.latch:
145 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
146 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
147 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
148 ; CHECK:       exit:
149 ; CHECK-NEXT:    ret void
151 entry:
152   %start.ult.end = icmp uge ptr %start, %end
153   br i1 %start.ult.end, label %exit, label %loop.ph
155 loop.ph:
156   br label %loop.header
158 loop.header:
159   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
160   %c = icmp eq ptr %ptr.iv, %end
161   br i1 %c, label %exit, label %for.body
163 for.body:
164   %c.1 = call i1 @cond()
165   br i1 %c.1, label %loop.next, label %exit
167 loop.next:
168   %t.1 = icmp uge ptr %ptr.iv, %start
169   %t.2 = icmp ult ptr %ptr.iv, %end
170   %and = and i1 %t.1, %t.2
171   br i1 %and, label %loop.latch, label %exit
173 loop.latch:
174   call void @use(ptr %ptr.iv)
175   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
176   br label %loop.header
178 exit:
179   ret void
182 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
183 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(
184 ; CHECK-NEXT:  entry:
185 ; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
186 ; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
187 ; CHECK:       loop.ph:
188 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
189 ; CHECK:       loop.header:
190 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
191 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
192 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
193 ; CHECK:       for.body:
194 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
195 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
196 ; CHECK:       loop.next:
197 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
198 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
199 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
200 ; CHECK:       loop.latch:
201 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
202 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
203 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
204 ; CHECK:       exit:
205 ; CHECK-NEXT:    ret void
207 entry:
208   %start.ult.end = icmp uge ptr %start, %end
209   br i1 %start.ult.end, label %exit, label %loop.ph
211 loop.ph:
212   br label %loop.header
214 loop.header:
215   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
216   %c = icmp eq ptr %ptr.iv, %end
217   br i1 %c, label %exit, label %for.body
219 for.body:
220   %c.1 = call i1 @cond()
221   br i1 %c.1, label %loop.next, label %exit
223 loop.next:
224   %t.1 = icmp uge ptr %ptr.iv, %start
225   %t.2 = icmp ult ptr %ptr.iv, %end
226   %and = and i1 %t.1, %t.2
227   br i1 %and, label %loop.latch, label %exit
229 loop.latch:
230   call void @use(ptr %ptr.iv)
231   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
232   br label %loop.header
234 exit:
235   ret void
238 define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) {
239 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(
240 ; CHECK-NEXT:  entry:
241 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]]
242 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
243 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
244 ; CHECK:       loop.ph:
245 ; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]]
246 ; CHECK-NEXT:    call void @llvm.assume(i1 [[START_ULT_END]])
247 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
248 ; CHECK:       loop.header:
249 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
250 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
251 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
252 ; CHECK:       for.body:
253 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
254 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
255 ; CHECK:       loop.next:
256 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
257 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
258 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
259 ; CHECK:       loop.latch:
260 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
261 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
262 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
263 ; CHECK:       exit:
264 ; CHECK-NEXT:    ret void
266 entry:
267   %upper = getelementptr inbounds i32, ptr %end, i16 %len
268   %len.neg = icmp slt i16 %len, 0
269   br i1 %len.neg, label %exit, label %loop.ph
271 loop.ph:
272   %start.ult.end = icmp ult ptr %start, %upper
273   call void @llvm.assume(i1 %start.ult.end)
274   br label %loop.header
276 loop.header:
277   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
278   %c = icmp eq ptr %ptr.iv, %upper
279   br i1 %c, label %exit, label %for.body
281 for.body:
282   %c.1 = call i1 @cond()
283   br i1 %c.1, label %loop.next, label %exit
285 loop.next:
286   %t.1 = icmp uge ptr %ptr.iv, %start
287   %t.2 = icmp ult ptr %ptr.iv, %upper
288   %and = and i1 %t.1, %t.2
289   br i1 %and, label %loop.latch, label %exit
291 loop.latch:
292   call void @use(ptr %ptr.iv)
293   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
294   br label %loop.header
296 exit:
297   ret void
300 define void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) {
301 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(
302 ; CHECK-NEXT:  entry:
303 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
304 ; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
305 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
306 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
307 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
308 ; CHECK:       loop.ph:
309 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
310 ; CHECK:       loop.header:
311 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
312 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
313 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
314 ; CHECK:       for.body:
315 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
316 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]]
317 ; CHECK:       then:
318 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
319 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
320 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
321 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
322 ; CHECK:       loop.latch:
323 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
324 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
325 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
326 ; CHECK:       exit:
327 ; CHECK-NEXT:    ret void
329 entry:
330   %step.pos = icmp sge i16 %step, 0
331   call void @llvm.assume(i1 %step.pos)
332   %upper = getelementptr inbounds i32, ptr %start, i16 %len
333   %len.neg = icmp slt i16 %len, 0
334   br i1 %len.neg, label %exit, label %loop.ph
336 loop.ph:
337   br label %loop.header
339 loop.header:
340   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
341   %c = icmp eq ptr %ptr.iv, %upper
342   br i1 %c, label %exit, label %for.body
344 for.body:
345   %c.1 = call i1 @cond()
346   br i1 %c.1, label %then, label %exit
348 then:
349   %c.2 = icmp uge ptr %ptr.iv, %start
350   %c.3 = icmp ult ptr %ptr.iv, %upper
351   %and = and i1 %c.2, %c.3
352   br i1 %and, label %loop.latch, label %exit
354 loop.latch:
355   call void @use(ptr %ptr.iv)
356   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
357   br label %loop.header
359 exit:
360   ret void
363 define void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) {
364 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit(
365 ; CHECK-NEXT:  entry:
366 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
367 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
368 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
369 ; CHECK:       loop.ph:
370 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
371 ; CHECK:       loop.header:
372 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
373 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
374 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
375 ; CHECK:       for.body:
376 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
377 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
378 ; CHECK:       then:
379 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
380 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
381 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
382 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
383 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
384 ; CHECK:       loop.latch:
385 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
386 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
387 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
388 ; CHECK:       exit:
389 ; CHECK-NEXT:    ret void
391 entry:
392   %upper = getelementptr inbounds i32, ptr %start, i16 %len
393   %len.neg = icmp slt i16 %len, 0
394   br i1 %len.neg, label %exit, label %loop.ph
396 loop.ph:
397   br label %loop.header
399 loop.header:
400   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
401   %c.0 = call i1 @cond()
402   br i1 %c.0, label %exit, label %for.body
404 for.body:
405   %c.1 = icmp ne ptr %ptr.iv, %upper
406   br i1 %c.1, label %then, label %loop.latch
408 then:
409   %t.1 = icmp uge ptr %ptr.iv, %start
410   %t.2 = icmp ult ptr %ptr.iv, %upper
411   %and = and i1 %t.1, %t.2
412   call void @use.i1(i1 %and)
413   br label %loop.latch
415 loop.latch:
416   call void @use(ptr %ptr.iv)
417   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
418   br label %loop.header
420 exit:
421   ret void
424 define void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) {
425 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2(
426 ; CHECK-NEXT:  entry:
427 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
428 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
429 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
430 ; CHECK:       loop.ph:
431 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
432 ; CHECK:       loop.header:
433 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
434 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
435 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
436 ; CHECK:       for.body:
437 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
438 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]]
439 ; CHECK:       then:
440 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
441 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
442 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
443 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
444 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
445 ; CHECK:       loop.latch:
446 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
447 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
448 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
449 ; CHECK:       exit:
450 ; CHECK-NEXT:    ret void
452 entry:
453   %upper = getelementptr inbounds i32, ptr %start, i16 %len
454   %len.neg = icmp slt i16 %len, 0
455   br i1 %len.neg, label %exit, label %loop.ph
457 loop.ph:
458   br label %loop.header
460 loop.header:
461   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
462   %c.1 = icmp ne ptr %ptr.iv, %upper
463   br i1 %c.1, label %then, label %for.body
465 for.body:
466   %c.0 = call i1 @cond()
467   br i1 %c.0, label %exit, label %loop.latch
469 then:
470   %t.1 = icmp uge ptr %ptr.iv, %start
471   %t.2 = icmp ult ptr %ptr.iv, %upper
472   %and = and i1 %t.1, %t.2
473   call void @use.i1(i1 %and)
474   br label %loop.latch
476 loop.latch:
477   call void @use(ptr %ptr.iv)
478   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
479   br label %loop.header
481 exit:
482   ret void
485 define void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) {
486 ; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(
487 ; CHECK-NEXT:  entry:
488 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
489 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
490 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
491 ; CHECK:       loop.ph:
492 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
493 ; CHECK:       loop.header:
494 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
495 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
496 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
497 ; CHECK:       for.body:
498 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
499 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
500 ; CHECK:       then:
501 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
502 ; CHECK:       loop.latch:
503 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
504 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
505 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
506 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
507 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
508 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
509 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
510 ; CHECK:       exit:
511 ; CHECK-NEXT:    ret void
513 entry:
514   %upper = getelementptr inbounds i32, ptr %start, i16 %len
515   %len.neg = icmp slt i16 %len, 0
516   br i1 %len.neg, label %exit, label %loop.ph
518 loop.ph:
519   br label %loop.header
521 loop.header:
522   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
523   %c.0 = call i1 @cond()
524   br i1 %c.0, label %exit, label %for.body
526 for.body:
527   %c.1 = icmp ne ptr %ptr.iv, %upper
528   br i1 %c.1, label %then, label %loop.latch
530 then:
531   br label %loop.latch
533 loop.latch:
534   %c.2 = icmp uge ptr %ptr.iv, %start
535   %c.3 = icmp ult ptr %ptr.iv, %upper
536   %and = and i1 %c.2, %c.3
537   call void @use.i1(i1 %and)
538   call void @use(ptr %ptr.iv)
539   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
540   br label %loop.header
542 exit:
543   ret void
546 define void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) {
547 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit(
548 ; CHECK-NEXT:  entry:
549 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
550 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
551 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
552 ; CHECK:       loop.ph:
553 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
554 ; CHECK:       loop.header:
555 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
556 ; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
557 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
558 ; CHECK:       for.body:
559 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
560 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
561 ; CHECK:       then:
562 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
563 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_3]]
564 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
565 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
566 ; CHECK:       loop.latch:
567 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
568 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
569 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
570 ; CHECK:       exit:
571 ; CHECK-NEXT:    ret void
573 entry:
574   %upper = getelementptr inbounds i32, ptr %start, i16 %len
575   %len.neg = icmp slt i16 %len, 0
576   br i1 %len.neg, label %exit, label %loop.ph
578 loop.ph:
579   br label %loop.header
581 loop.header:
582   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
583   %c.1 = icmp eq ptr %ptr.iv, %upper
584   br i1 %c.1, label %exit, label %for.body
586 for.body:
587   %c.0 = call i1 @cond()
588   br i1 %c.0, label %exit, label %then
590 then:
591   %c.2 = icmp uge ptr %ptr.iv, %start
592   %c.3 = icmp ult ptr %ptr.iv, %upper
593   %and = and i1 %c.2, %c.3
594   call void @use.i1(i1 %and)
595   br label %loop.latch
597 loop.latch:
598   call void @use(ptr %ptr.iv)
599   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
600   br label %loop.header
602 exit:
603   ret void
606 define void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) {
607 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(
608 ; CHECK-NEXT:  entry:
609 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
610 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
611 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
612 ; CHECK:       loop.ph:
613 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
614 ; CHECK:       loop.header:
615 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
616 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
617 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
618 ; CHECK:       for.body:
619 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
620 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
621 ; CHECK:       then:
622 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
623 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
624 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
625 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
626 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
627 ; CHECK:       loop.latch:
628 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
629 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
630 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
631 ; CHECK:       exit:
632 ; CHECK-NEXT:    ret void
634 entry:
635   %upper = getelementptr inbounds i32, ptr %start, i16 %len
636   %len.neg = icmp slt i16 %len, 0
637   br i1 %len.neg, label %exit, label %loop.ph
639 loop.ph:
640   br label %loop.header
642 loop.header:
643   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
644   %c.0 = call i1 @cond()
645   br i1 %c.0, label %exit, label %for.body
647 for.body:
648   %c.1 = icmp ne ptr %ptr.iv, %upper
649   br i1 %c.1, label %then, label %loop.latch
651 then:
652   %c.2 = icmp uge ptr %ptr.iv, %start
653   %c.3 = icmp ult ptr %ptr.iv, %upper
654   %and = and i1 %c.2, %c.3
655   call void @use.i1(i1 %and)
656   br label %loop.latch
658 loop.latch:
659   call void @use(ptr %ptr.iv)
660   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
661   br label %loop.header
663 exit:
664   ret void
667 define void @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(ptr %start, i16 %len) {
668 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_64_cond_doesnt_control_exit(
669 ; CHECK-NEXT:  entry:
670 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
671 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
672 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
673 ; CHECK:       loop.ph:
674 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
675 ; CHECK:       loop.header:
676 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
677 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
678 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
679 ; CHECK:       for.body:
680 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
681 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
682 ; CHECK:       then:
683 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
684 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
685 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
686 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
687 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
688 ; CHECK:       loop.latch:
689 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
690 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 4
691 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
692 ; CHECK:       exit:
693 ; CHECK-NEXT:    ret void
695 entry:
696   %upper = getelementptr inbounds i64, ptr %start, i16 %len
697   %len.neg = icmp slt i16 %len, 0
698   br i1 %len.neg, label %exit, label %loop.ph
700 loop.ph:
701   br label %loop.header
703 loop.header:
704   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
705   %c.0 = call i1 @cond()
706   br i1 %c.0, label %exit, label %for.body
708 for.body:
709   %c.1 = icmp ne ptr %ptr.iv, %upper
710   br i1 %c.1, label %then, label %loop.latch
712 then:
713   %c.2 = icmp uge ptr %ptr.iv, %start
714   %c.3 = icmp ult ptr %ptr.iv, %upper
715   %and = and i1 %c.2, %c.3
716   call void @use.i1(i1 %and)
717   br label %loop.latch
719 loop.latch:
720   call void @use(ptr %ptr.iv)
721   %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 4
722   br label %loop.header
724 exit:
725   ret void
728 define void @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(ptr %start, i16 %len) {
729 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_80_cond_doesnt_control_exit(
730 ; CHECK-NEXT:  entry:
731 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
732 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
733 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
734 ; CHECK:       loop.ph:
735 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
736 ; CHECK:       loop.header:
737 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
738 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
739 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
740 ; CHECK:       for.body:
741 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
742 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
743 ; CHECK:       then:
744 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
745 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
746 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
747 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
748 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
749 ; CHECK:       loop.latch:
750 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
751 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 5
752 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
753 ; CHECK:       exit:
754 ; CHECK-NEXT:    ret void
756 entry:
757   %upper = getelementptr inbounds i64, ptr %start, i16 %len
758   %len.neg = icmp slt i16 %len, 0
759   br i1 %len.neg, label %exit, label %loop.ph
761 loop.ph:
762   br label %loop.header
764 loop.header:
765   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
766   %c.0 = call i1 @cond()
767   br i1 %c.0, label %exit, label %for.body
769 for.body:
770   %c.1 = icmp ne ptr %ptr.iv, %upper
771   br i1 %c.1, label %then, label %loop.latch
773 then:
774   %c.2 = icmp uge ptr %ptr.iv, %start
775   %c.3 = icmp ult ptr %ptr.iv, %upper
776   %and = and i1 %c.2, %c.3
777   call void @use.i1(i1 %and)
778   br label %loop.latch
780 loop.latch:
781   call void @use(ptr %ptr.iv)
782   %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 5
783   br label %loop.header
785 exit:
786   ret void
789 define void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) {
790 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop(
791 ; CHECK-NEXT:  entry:
792 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
793 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
794 ; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NEG]])
795 ; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
796 ; CHECK:       loop.ph:
797 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
798 ; CHECK:       loop.header:
799 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
800 ; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
801 ; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
802 ; CHECK:       loop.latch:
803 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
804 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
805 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
806 ; CHECK:       exit:
807 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
808 ; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
809 ; CHECK:       then:
810 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
811 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
812 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
813 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
814 ; CHECK-NEXT:    br label [[EXIT_2]]
815 ; CHECK:       exit.2:
816 ; CHECK-NEXT:    ret void
818 entry:
819   %upper = getelementptr inbounds i32, ptr %start, i16 %len
820   %len.neg = icmp sge i16 %len, 0
821   call void @llvm.assume(i1 %len.neg)
822   br label %loop.ph
824 loop.ph:
825   br label %loop.header
827 loop.header:
828   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
829   %c.0 = call i1 @cond()
830   br i1 %c.0, label %exit, label %loop.latch
832 loop.latch:
833   call void @use(ptr %ptr.iv)
834   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
835   br label %loop.header
837 exit:
838   %c.1 = icmp ne ptr %ptr.iv, %upper
839   br i1 %c.1, label %then, label %exit.2
841 then:
842   %c.2 = icmp uge ptr %ptr.iv, %start
843   %c.3 = icmp ult ptr %ptr.iv, %upper
844   %and = and i1 %c.2, %c.3
845   call void @use.i1(i1 %and)
846   br label %exit.2
848 exit.2:
849   ret void
852 define void @test_step_gep_doesnt_use_ptr_iv_phi(ptr %start, ptr %other, i16 %len) {
853 ; CHECK-LABEL: @test_step_gep_doesnt_use_ptr_iv_phi(
854 ; CHECK-NEXT:  entry:
855 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
856 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
857 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
858 ; CHECK:       loop.ph:
859 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
860 ; CHECK:       loop.header:
861 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
862 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
863 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
864 ; CHECK:       for.body:
865 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
866 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
867 ; CHECK:       loop.next:
868 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
869 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
870 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
871 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
872 ; CHECK:       loop.latch:
873 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
874 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[OTHER:%.*]], i16 1
875 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
876 ; CHECK:       exit:
877 ; CHECK-NEXT:    ret void
879 entry:
880   %upper = getelementptr inbounds float, ptr %start, i16 %len
881   %len.neg = icmp slt i16 %len, 0
882   br i1 %len.neg, label %exit, label %loop.ph
884 loop.ph:
885   br label %loop.header
887 loop.header:
888   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
889   %c = icmp eq ptr %ptr.iv, %upper
890   br i1 %c, label %exit, label %for.body
892 for.body:
893   %c.1 = call i1 @cond()
894   br i1 %c.1, label %loop.next, label %exit
896 loop.next:
897   %t.1 = icmp uge ptr %ptr.iv, %start
898   %t.2 = icmp ult ptr %ptr.iv, %upper
899   %and = and i1 %t.1, %t.2
900   br i1 %and, label %loop.latch, label %exit
902 loop.latch:
903   call void @use(ptr %ptr.iv)
904   %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1
905   br label %loop.header
907 exit:
908   ret void
911 define void @test_step_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
912 ; CHECK-LABEL: @test_step_gep_not_inbounds(
913 ; CHECK-NEXT:  entry:
914 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
915 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
916 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
917 ; CHECK:       loop.ph:
918 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
919 ; CHECK:       loop.header:
920 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
921 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
922 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
923 ; CHECK:       for.body:
924 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
925 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
926 ; CHECK:       loop.next:
927 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
928 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
929 ; CHECK:       loop.latch:
930 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
931 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr float, ptr [[PTR_IV]], i16 1
932 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
933 ; CHECK:       exit:
934 ; CHECK-NEXT:    ret void
936 entry:
937   %upper = getelementptr inbounds float, ptr %start, i16 %len
938   %len.neg = icmp slt i16 %len, 0
939   br i1 %len.neg, label %exit, label %loop.ph
941 loop.ph:
942   br label %loop.header
944 loop.header:
945   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
946   %c = icmp eq ptr %ptr.iv, %upper
947   br i1 %c, label %exit, label %for.body
949 for.body:
950   %c.1 = call i1 @cond()
951   br i1 %c.1, label %loop.next, label %exit
953 loop.next:
954   %t.1 = icmp uge ptr %ptr.iv, %start
955   %t.2 = icmp ult ptr %ptr.iv, %upper
956   %and = and i1 %t.1, %t.2
957   br i1 %and, label %loop.latch, label %exit
959 loop.latch:
960   call void @use(ptr %ptr.iv)
961   %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1
962   br label %loop.header
964 exit:
965   ret void
968 define void @test_upper_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
969 ; CHECK-LABEL: @test_upper_gep_not_inbounds(
970 ; CHECK-NEXT:  entry:
971 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr float, ptr [[START:%.*]], i16 [[LEN:%.*]]
972 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
973 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
974 ; CHECK:       loop.ph:
975 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
976 ; CHECK:       loop.header:
977 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
978 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
979 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
980 ; CHECK:       for.body:
981 ; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
982 ; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
983 ; CHECK:       loop.next:
984 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
985 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
986 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
987 ; CHECK:       loop.latch:
988 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
989 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1
990 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
991 ; CHECK:       exit:
992 ; CHECK-NEXT:    ret void
994 entry:
995   %upper = getelementptr float, ptr %start, i16 %len
996   %len.neg = icmp slt i16 %len, 0
997   br i1 %len.neg, label %exit, label %loop.ph
999 loop.ph:
1000   br label %loop.header
1002 loop.header:
1003   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1004   %c = icmp eq ptr %ptr.iv, %upper
1005   br i1 %c, label %exit, label %for.body
1007 for.body:
1008   %c.1 = call i1 @cond()
1009   br i1 %c.1, label %loop.next, label %exit
1011 loop.next:
1012   %t.1 = icmp uge ptr %ptr.iv, %start
1013   %t.2 = icmp ult ptr %ptr.iv, %upper
1014   %and = and i1 %t.1, %t.2
1015   br i1 %and, label %loop.latch, label %exit
1017 loop.latch:
1018   call void @use(ptr %ptr.iv)
1019   %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i16 1
1020   br label %loop.header
1022 exit:
1023   ret void