Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / monotonic-pointer-phis.ll
blobb3432695a96a58703ba1dea99c5b41116d8e1ed1
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_eq_to_uge(ptr %start, i16 %len) {
13 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge(
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:    [[AND:%.*]] = and i1 true, true
26 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
27 ; CHECK:       loop.latch:
28 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
29 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
30 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
31 ; CHECK:       exit:
32 ; CHECK-NEXT:    ret void
34 entry:
35   %upper = getelementptr inbounds i32, ptr %start, i16 %len
36   %len.neg = icmp slt i16 %len, 0
37   br i1 %len.neg, label %exit, label %loop.ph
39 loop.ph:
40   br label %loop.header
42 loop.header:
43   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
44   %c = icmp eq ptr %ptr.iv, %upper
45   br i1 %c, label %exit, label %for.body
47 for.body:
48   %t.1 = icmp uge ptr %ptr.iv, %start
49   %t.2 = icmp ult ptr %ptr.iv, %upper
50   %and = and i1 %t.1, %t.2
51   br i1 %and, label %loop.latch, label %exit
53 loop.latch:
54   call void @use(ptr %ptr.iv)
55   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
56   br label %loop.header
58 exit:
59   ret void
62 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_incoming_values_reordered(ptr %start, i16 %len) {
63 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_incoming_values_reordered(
64 ; CHECK-NEXT:  entry:
65 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
66 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
67 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
68 ; CHECK:       loop.ph:
69 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
70 ; CHECK:       loop.header:
71 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ [[START]], [[LOOP_PH]] ]
72 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
73 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
74 ; CHECK:       for.body:
75 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
76 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
77 ; CHECK:       loop.latch:
78 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
79 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
80 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
81 ; CHECK:       exit:
82 ; CHECK-NEXT:    ret void
84 entry:
85   %upper = getelementptr inbounds i32, ptr %start, i16 %len
86   %len.neg = icmp slt i16 %len, 0
87   br i1 %len.neg, label %exit, label %loop.ph
89 loop.ph:
90   br label %loop.header
92 loop.header:
93   %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %loop.ph ]
94   %c = icmp eq ptr %ptr.iv, %upper
95   br i1 %c, label %exit, label %for.body
97 for.body:
98   %t.1 = icmp uge ptr %ptr.iv, %start
99   %t.2 = icmp ult ptr %ptr.iv, %upper
100   %and = and i1 %t.1, %t.2
101   br i1 %and, label %loop.latch, label %exit
103 loop.latch:
104   call void @use(ptr %ptr.iv)
105   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
106   br label %loop.header
108 exit:
109   ret void
112 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_preheader(ptr %start, i16 %len) {
113 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_preheader(
114 ; CHECK-NEXT:  entry:
115 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
116 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
117 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_HEADER:%.*]]
118 ; CHECK:       loop.header:
119 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
120 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
121 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
122 ; CHECK:       for.body:
123 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
124 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
125 ; CHECK:       loop.latch:
126 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
127 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
128 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
129 ; CHECK:       exit:
130 ; CHECK-NEXT:    ret void
132 entry:
133   %upper = getelementptr inbounds i32, ptr %start, i16 %len
134   %len.neg = icmp slt i16 %len, 0
135   br i1 %len.neg, label %exit, label %loop.header
137 loop.header:
138   %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
139   %c = icmp eq ptr %ptr.iv, %upper
140   br i1 %c, label %exit, label %for.body
142 for.body:
143   %t.1 = icmp uge ptr %ptr.iv, %start
144   %t.2 = icmp ult ptr %ptr.iv, %upper
145   %and = and i1 %t.1, %t.2
146   br i1 %and, label %loop.latch, label %exit
148 loop.latch:
149   call void @use(ptr %ptr.iv)
150   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
151   br label %loop.header
153 exit:
154   ret void
157 define void @test_monotonic_ptr_iv_inc_1_different_element_types(ptr %start, i16 %len) {
158 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types(
159 ; CHECK-NEXT:  entry:
160 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
161 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
162 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
163 ; CHECK:       loop.ph:
164 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
165 ; CHECK:       loop.header:
166 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
167 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
168 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
169 ; CHECK:       for.body:
170 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
171 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
172 ; CHECK:       loop.latch:
173 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
174 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
175 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
176 ; CHECK:       exit:
177 ; CHECK-NEXT:    ret void
179 entry:
180   %upper = getelementptr inbounds i32, ptr %start, i16 %len
181   %len.neg = icmp slt i16 %len, 0
182   br i1 %len.neg, label %exit, label %loop.ph
184 loop.ph:
185   br label %loop.header
187 loop.header:
188   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
189   %c = icmp eq ptr %ptr.iv, %upper
190   br i1 %c, label %exit, label %for.body
192 for.body:
193   %t.1 = icmp uge ptr %ptr.iv, %start
194   %t.2 = icmp ult ptr %ptr.iv, %upper
195   %and = and i1 %t.1, %t.2
196   br i1 %and, label %loop.latch, label %exit
198 loop.latch:
199   call void @use(ptr %ptr.iv)
200   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
201   br label %loop.header
203 exit:
204   ret void
207 define void @test_monotonic_ptr_iv_inc_1_different_element_types_2(ptr %start, i16 %len) {
208 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_2(
209 ; CHECK-NEXT:  entry:
210 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
211 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
212 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
213 ; CHECK:       loop.ph:
214 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
215 ; CHECK:       loop.header:
216 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
217 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
218 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
219 ; CHECK:       for.body:
220 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
221 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
222 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
223 ; CHECK:       loop.latch:
224 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
225 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
226 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
227 ; CHECK:       exit:
228 ; CHECK-NEXT:    ret void
230 entry:
231   %upper = getelementptr inbounds i8, ptr %start, i16 %len
232   %len.neg = icmp slt i16 %len, 0
233   br i1 %len.neg, label %exit, label %loop.ph
235 loop.ph:
236   br label %loop.header
238 loop.header:
239   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
240   %c = icmp eq ptr %ptr.iv, %upper
241   br i1 %c, label %exit, label %for.body
243 for.body:
244   %t.1 = icmp uge ptr %ptr.iv, %start
245   %t.2 = icmp ult ptr %ptr.iv, %upper
246   %and = and i1 %t.1, %t.2
247   br i1 %and, label %loop.latch, label %exit
249 loop.latch:
250   call void @use(ptr %ptr.iv)
251   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
252   br label %loop.header
254 exit:
255   ret void
258 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(ptr %start, ptr %end) {
259 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(
260 ; CHECK-NEXT:  entry:
261 ; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
262 ; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
263 ; CHECK:       loop.ph:
264 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
265 ; CHECK:       loop.header:
266 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
267 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
268 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
269 ; CHECK:       for.body:
270 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
271 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
272 ; CHECK:       loop.latch:
273 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
274 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
275 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
276 ; CHECK:       exit:
277 ; CHECK-NEXT:    ret void
279 entry:
280   %start.ult.end = icmp uge ptr %start, %end
281   br i1 %start.ult.end, label %exit, label %loop.ph
283 loop.ph:
284   br label %loop.header
286 loop.header:
287   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
288   %c = icmp eq ptr %ptr.iv, %end
289   br i1 %c, label %exit, label %for.body
291 for.body:
292   %t.1 = icmp uge ptr %ptr.iv, %start
293   %t.2 = icmp ult ptr %ptr.iv, %end
294   %and = and i1 %t.1, %t.2
295   br i1 %and, label %loop.latch, label %exit
297 loop.latch:
298   call void @use(ptr %ptr.iv)
299   %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
300   br label %loop.header
302 exit:
303   ret void
306 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr(ptr %start, ptr %end) {
307 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr(
308 ; CHECK-NEXT:  entry:
309 ; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
310 ; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
311 ; CHECK:       loop.ph:
312 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
313 ; CHECK:       loop.header:
314 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
315 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
316 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
317 ; CHECK:       for.body:
318 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
319 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
320 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
321 ; CHECK:       loop.latch:
322 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
323 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
324 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
325 ; CHECK:       exit:
326 ; CHECK-NEXT:    ret void
328 entry:
329   %start.ult.end = icmp uge ptr %start, %end
330   br i1 %start.ult.end, label %exit, label %loop.ph
332 loop.ph:
333   br label %loop.header
335 loop.header:
336   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
337   %c = icmp eq ptr %ptr.iv, %end
338   br i1 %c, label %exit, label %for.body
340 for.body:
341   %t.1 = icmp uge ptr %ptr.iv, %start
342   %t.2 = icmp ult ptr %ptr.iv, %end
343   %and = and i1 %t.1, %t.2
344   br i1 %and, label %loop.latch, label %exit
346 loop.latch:
347   call void @use(ptr %ptr.iv)
348   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
349   br label %loop.header
351 exit:
352   ret void
355 define void @test_ptr_iv_upper_may_be_less_than_start(ptr %start, i16 %len) {
356 ; CHECK-LABEL: @test_ptr_iv_upper_may_be_less_than_start(
357 ; CHECK-NEXT:  entry:
358 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
359 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
360 ; CHECK:       loop.header:
361 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
362 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
363 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
364 ; CHECK:       for.body:
365 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
366 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_2]]
367 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
368 ; CHECK:       loop.latch:
369 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
370 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
371 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
372 ; CHECK:       exit:
373 ; CHECK-NEXT:    ret void
375 entry:
376   %upper = getelementptr inbounds i32, ptr %start, i16 %len
377   br label %loop.header
379 loop.header:
380   %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
381   %c = icmp eq ptr %ptr.iv, %upper
382   br i1 %c, label %exit, label %for.body
384 for.body:
385   %c.1 = icmp uge ptr %ptr.iv, %start
386   %c.2 = icmp ult ptr %ptr.iv, %upper
387   %and = and i1 %c.1, %c.2
388   br i1 %and, label %loop.latch, label %exit
390 loop.latch:
391   call void @use(ptr %ptr.iv)
392   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
393   br label %loop.header
395 exit:
396   ret void
399 define void @test_no_ptr_iv_step_inst_doesnt_use_phi(ptr %start, ptr %p, i16 %len) {
400 ; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi(
401 ; CHECK-NEXT:  entry:
402 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
403 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
404 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
405 ; CHECK:       loop.ph:
406 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
407 ; CHECK:       loop.header:
408 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
409 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
410 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
411 ; CHECK:       for.body:
412 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
413 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
414 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
415 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
416 ; CHECK:       loop.latch:
417 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
418 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[P:%.*]], i16 1
419 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
420 ; CHECK:       exit:
421 ; CHECK-NEXT:    ret void
423 entry:
424   %upper = getelementptr inbounds i32, ptr %start, i16 %len
425   %len.neg = icmp slt i16 %len, 0
426   br i1 %len.neg, label %exit, label %loop.ph
428 loop.ph:
429   br label %loop.header
431 loop.header:
432   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
433   %c = icmp eq ptr %ptr.iv, %upper
434   br i1 %c, label %exit, label %for.body
436 for.body:
437   %t.1 = icmp uge ptr %ptr.iv, %start
438   %t.2 = icmp ult ptr %ptr.iv, %upper
439   %and = and i1 %t.1, %t.2
440   br i1 %and, label %loop.latch, label %exit
442 loop.latch:
443   call void @use(ptr %ptr.iv)
444   %ptr.iv.next = getelementptr inbounds i32, ptr %p, i16 1
445   br label %loop.header
447 exit:
448   ret void
451 define void @test_no_ptr_iv_step_inst_doesnt_use_phi_2(ptr %start, ptr %end, i16 %len) {
452 ; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi_2(
453 ; CHECK-NEXT:  entry:
454 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
455 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
456 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
457 ; CHECK:       loop.ph:
458 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
459 ; CHECK:       loop.header:
460 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
461 ; CHECK-NEXT:    [[PTR_IV_2:%.*]] = phi ptr [ [[END:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT]], [[LOOP_LATCH]] ]
462 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
463 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[LOOP_NEXT:%.*]]
464 ; CHECK:       loop.next:
465 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
466 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
467 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
468 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
469 ; CHECK:       loop.latch:
470 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
471 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV_2]], i16 1
472 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
473 ; CHECK:       exit:
474 ; CHECK-NEXT:    ret void
476 entry:
477   %upper = getelementptr inbounds float, ptr %start, i16 %len
478   %len.neg = icmp slt i16 %len, 0
479   br i1 %len.neg, label %exit, label %loop.ph
481 loop.ph:
482   br label %loop.header
484 loop.header:
485   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
486   %ptr.iv.2 = phi ptr [ %end, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
487   %c = icmp eq ptr %ptr.iv, %upper
488   br i1 %c, label %exit, label %loop.next
490 loop.next:
491   %t.1 = icmp uge ptr %ptr.iv, %start
492   %t.2 = icmp ult ptr %ptr.iv, %upper
493   %and = and i1 %t.1, %t.2
494   br i1 %and, label %loop.latch, label %exit
496 loop.latch:
497   call void @use(ptr %ptr.iv)
498   %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv.2, i16 1
499   br label %loop.header
501 exit:
502   ret void
505 define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
506 ; CHECK-LABEL: @test_no_ptr_iv_different_start(
507 ; CHECK-NEXT:  entry:
508 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
509 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
510 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
511 ; CHECK:       loop.ph:
512 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
513 ; CHECK:       loop.header:
514 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[P:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
515 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
516 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
517 ; CHECK:       for.body:
518 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
519 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
520 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
521 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
522 ; CHECK:       loop.latch:
523 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
524 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
525 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
526 ; CHECK:       exit:
527 ; CHECK-NEXT:    ret void
529 entry:
530   %upper = getelementptr inbounds i32, ptr %start, i16 %len
531   %len.neg = icmp slt i16 %len, 0
532   br i1 %len.neg, label %exit, label %loop.ph
534 loop.ph:
535   br label %loop.header
537 loop.header:
538   %ptr.iv = phi ptr [ %p, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
539   %c = icmp eq ptr %ptr.iv, %upper
540   br i1 %c, label %exit, label %for.body
542 for.body:
543   %c.1 = icmp uge ptr %ptr.iv, %start
544   %c.2 = icmp ult ptr %ptr.iv, %upper
545   %and = and i1 %c.1, %c.2
546   br i1 %and, label %loop.latch, label %exit
548 loop.latch:
549   call void @use(ptr %ptr.iv)
550   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
551   br label %loop.header
553 exit:
554   ret void
557 define void @test_ptr_iv_not_inbounds(ptr %start, i16 %len) {
558 ; CHECK-LABEL: @test_ptr_iv_not_inbounds(
559 ; CHECK-NEXT:  entry:
560 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
561 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
562 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
563 ; CHECK:       loop.ph:
564 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
565 ; CHECK:       loop.header:
566 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
567 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
568 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
569 ; CHECK:       for.body:
570 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
571 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
572 ; CHECK:       loop.latch:
573 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
574 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
575 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
576 ; CHECK:       exit:
577 ; CHECK-NEXT:    ret void
579 entry:
580   %upper = getelementptr inbounds i32, ptr %start, i16 %len
581   %len.neg = icmp slt i16 %len, 0
582   br i1 %len.neg, label %exit, label %loop.ph
584 loop.ph:
585   br label %loop.header
587 loop.header:
588   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
589   %c = icmp eq ptr %ptr.iv, %upper
590   br i1 %c, label %exit, label %for.body
592 for.body:
593   %c.1 = icmp uge ptr %ptr.iv, %start
594   %c.2 = icmp ult ptr %ptr.iv, %upper
595   %and = and i1 %c.1, %c.2
596   br i1 %and, label %loop.latch, label %exit
598 loop.latch:
599   call void @use(ptr %ptr.iv)
600   %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
601   br label %loop.header
603 exit:
604   ret void
607 define void @test_var_step_not_monotonic(ptr %start, i16 %len, i16 %step) {
608 ; CHECK-LABEL: @test_var_step_not_monotonic(
609 ; CHECK-NEXT:  entry:
610 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
611 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
612 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
613 ; CHECK:       loop.ph:
614 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
615 ; CHECK:       loop.header:
616 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
617 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
618 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
619 ; CHECK:       for.body:
620 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
621 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
622 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
623 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
624 ; CHECK:       loop.latch:
625 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
626 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
627 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
628 ; CHECK:       exit:
629 ; CHECK-NEXT:    ret void
631 entry:
632   %upper = getelementptr inbounds i32, ptr %start, i16 %len
633   %len.neg = icmp slt i16 %len, 0
634   br i1 %len.neg, label %exit, label %loop.ph
636 loop.ph:
637   br label %loop.header
639 loop.header:
640   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
641   %c = icmp eq ptr %ptr.iv, %upper
642   br i1 %c, label %exit, label %for.body
644 for.body:
645   %c.1 = icmp uge ptr %ptr.iv, %start
646   %c.2 = icmp ult ptr %ptr.iv, %upper
647   %and = and i1 %c.1, %c.2
648   br i1 %and, label %loop.latch, label %exit
650 loop.latch:
651   call void @use(ptr %ptr.iv)
652   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
653   br label %loop.header
655 exit:
656   ret void
659 define void @test_monotonic_ptr_iv_step_neg_1(ptr %start, i16 %len) {
660 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_neg_1(
661 ; CHECK-NEXT:  entry:
662 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
663 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
664 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
665 ; CHECK:       loop.ph:
666 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
667 ; CHECK:       loop.header:
668 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
669 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
670 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
671 ; CHECK:       for.body:
672 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
673 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
674 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
675 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
676 ; CHECK:       loop.latch:
677 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
678 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 -1
679 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
680 ; CHECK:       exit:
681 ; CHECK-NEXT:    ret void
683 entry:
684   %upper = getelementptr inbounds i32, ptr %start, i16 %len
685   %len.neg = icmp slt i16 %len, 0
686   br i1 %len.neg, label %exit, label %loop.ph
688 loop.ph:
689   br label %loop.header
691 loop.header:
692   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
693   %c = icmp eq ptr %ptr.iv, %upper
694   br i1 %c, label %exit, label %for.body
696 for.body:
697   %c.1 = icmp uge ptr %ptr.iv, %start
698   %c.2 = icmp ult ptr %ptr.iv, %upper
699   %and = and i1 %c.1, %c.2
700   br i1 %and, label %loop.latch, label %exit
702 loop.latch:
703   call void @use(ptr %ptr.iv)
704   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 -1
705   br label %loop.header
707 exit:
708   ret void
711 define void @test_monotonic_ptr_iv_step_sign_unknown(ptr %start, i16 %len, i16 %step) {
712 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_unknown(
713 ; CHECK-NEXT:  entry:
714 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
715 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
716 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
717 ; CHECK:       loop.ph:
718 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
719 ; CHECK:       loop.header:
720 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
721 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
722 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
723 ; CHECK:       for.body:
724 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
725 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
726 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
727 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
728 ; CHECK:       loop.latch:
729 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
730 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
731 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
732 ; CHECK:       exit:
733 ; CHECK-NEXT:    ret void
735 entry:
736   %upper = getelementptr inbounds i32, ptr %start, i16 %len
737   %len.neg = icmp slt i16 %len, 0
738   br i1 %len.neg, label %exit, label %loop.ph
740 loop.ph:
741   br label %loop.header
743 loop.header:
744   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
745   %c = icmp eq ptr %ptr.iv, %upper
746   br i1 %c, label %exit, label %for.body
748 for.body:
749   %c.1 = icmp uge ptr %ptr.iv, %start
750   %c.2 = icmp ult ptr %ptr.iv, %upper
751   %and = and i1 %c.1, %c.2
752   br i1 %and, label %loop.latch, label %exit
754 loop.latch:
755   call void @use(ptr %ptr.iv)
756   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
757   br label %loop.header
759 exit:
760   ret void
763 define void @test_monotonic_ptr_iv_step_sign_positive_through_assume(ptr %start, i16 %len, i16 %step) {
764 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume(
765 ; CHECK-NEXT:  entry:
766 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
767 ; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
768 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
769 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
770 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
771 ; CHECK:       loop.ph:
772 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
773 ; CHECK:       loop.header:
774 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
775 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
776 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
777 ; CHECK:       for.body:
778 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
779 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
780 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
781 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
782 ; CHECK:       loop.latch:
783 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
784 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
785 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
786 ; CHECK:       exit:
787 ; CHECK-NEXT:    ret void
789 entry:
790   %step.pos = icmp sge i16 %step, 0
791   call void @llvm.assume(i1 %step.pos)
792   %upper = getelementptr inbounds i32, ptr %start, i16 %len
793   %len.neg = icmp slt i16 %len, 0
794   br i1 %len.neg, label %exit, label %loop.ph
796 loop.ph:
797   br label %loop.header
799 loop.header:
800   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
801   %c = icmp eq ptr %ptr.iv, %upper
802   br i1 %c, label %exit, label %for.body
804 for.body:
805   %t.1 = icmp uge ptr %ptr.iv, %start
806   %t.2 = icmp ult ptr %ptr.iv, %upper
807   %and = and i1 %t.1, %t.2
808   br i1 %and, label %loop.latch, label %exit
810 loop.latch:
811   call void @use(ptr %ptr.iv)
812   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
813   br label %loop.header
815 exit:
816   ret void
819 define void @test_monotonic_ptr_iv_step_sign_negative_through_assume(ptr %start, i16 %len, i16 %step) {
820 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_negative_through_assume(
821 ; CHECK-NEXT:  entry:
822 ; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sle i16 [[STEP:%.*]], 0
823 ; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
824 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
825 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
826 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
827 ; CHECK:       loop.ph:
828 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
829 ; CHECK:       loop.header:
830 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
831 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
832 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
833 ; CHECK:       for.body:
834 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
835 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
836 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
837 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
838 ; CHECK:       loop.latch:
839 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
840 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
841 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
842 ; CHECK:       exit:
843 ; CHECK-NEXT:    ret void
845 entry:
846   %step.pos = icmp sle i16 %step, 0
847   call void @llvm.assume(i1 %step.pos)
848   %upper = getelementptr inbounds i32, ptr %start, i16 %len
849   %len.neg = icmp slt i16 %len, 0
850   br i1 %len.neg, label %exit, label %loop.ph
852 loop.ph:
853   br label %loop.header
855 loop.header:
856   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
857   %c = icmp eq ptr %ptr.iv, %upper
858   br i1 %c, label %exit, label %for.body
860 for.body:
861   %c.1 = icmp uge ptr %ptr.iv, %start
862   %c.2 = icmp ult ptr %ptr.iv, %upper
863   %and = and i1 %c.1, %c.2
864   br i1 %and, label %loop.latch, label %exit
866 loop.latch:
867   call void @use(ptr %ptr.iv)
868   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
869   br label %loop.header
871 exit:
872   ret void
875 define void @test_monotonic_ptr_iv_inc_2(ptr %start, i16 %len) {
876 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2(
877 ; CHECK-NEXT:  entry:
878 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
879 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
880 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
881 ; CHECK:       loop.ph:
882 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
883 ; CHECK:       loop.header:
884 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
885 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
886 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
887 ; CHECK:       for.body:
888 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
889 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
890 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
891 ; CHECK:       loop.latch:
892 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
893 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
894 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
895 ; CHECK:       exit:
896 ; CHECK-NEXT:    ret void
898 entry:
899   %upper = getelementptr inbounds i32, ptr %start, i16 %len
900   %len.neg = icmp slt i16 %len, 0
901   br i1 %len.neg, label %exit, label %loop.ph
903 loop.ph:
904   br label %loop.header
906 loop.header:
907   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
908   %c = icmp eq ptr %ptr.iv, %upper
909   br i1 %c, label %exit, label %for.body
911 for.body:
912   %t.1 = icmp uge ptr %ptr.iv, %start
913   %t.2 = icmp ult ptr %ptr.iv, %upper
914   %and = and i1 %t.1, %t.2
915   br i1 %and, label %loop.latch, label %exit
917 loop.latch:
918   call void @use(ptr %ptr.iv)
919   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
920   br label %loop.header
922 exit:
923   ret void
926 define void @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(ptr %start, i16 %len) {
927 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(
928 ; CHECK-NEXT:  entry:
929 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
930 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
931 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
932 ; CHECK:       loop.ph:
933 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
934 ; CHECK:       loop.header:
935 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
936 ; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
937 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
938 ; CHECK:       for.body:
939 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
940 ; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
941 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
942 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
943 ; CHECK:       loop.latch:
944 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
945 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
946 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
947 ; CHECK:       exit:
948 ; CHECK-NEXT:    ret void
950 entry:
951   %upper = getelementptr inbounds i32, ptr %start, i16 %len
952   %len.neg = icmp slt i16 %len, 0
953   br i1 %len.neg, label %exit, label %loop.ph
955 loop.ph:
956   br label %loop.header
958 loop.header:
959   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
960   %c.1 = icmp eq ptr %ptr.iv, %upper
961   br i1 %c.1, label %exit, label %for.body
963 for.body:
964   %t.1 = icmp uge ptr %ptr.iv, %start
965   %t.2 = icmp ult ptr %ptr.iv, %upper
966   %and = and i1 %t.1, %t.2
967   call void @use.i1(i1 %and)
968   br label %loop.latch
970 loop.latch:
971   call void @use(ptr %ptr.iv)
972   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
973   br label %loop.header
975 exit:
976   ret void
979 define void @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(ptr %start, i16 %len) {
980 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(
981 ; CHECK-NEXT:  entry:
982 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
983 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
984 ; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NEG]])
985 ; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
986 ; CHECK:       loop.ph:
987 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
988 ; CHECK:       loop.header:
989 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
990 ; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
991 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
992 ; CHECK:       for.body:
993 ; CHECK-NEXT:    br label [[LOOP_LATCH]]
994 ; CHECK:       loop.latch:
995 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
996 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
997 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
998 ; CHECK:       exit:
999 ; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
1000 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1001 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
1002 ; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
1003 ; CHECK-NEXT:    ret void
1005 entry:
1006   %upper = getelementptr inbounds i32, ptr %start, i16 %len
1007   %len.neg = icmp sge i16 %len, 0
1008   call void @llvm.assume(i1 %len.neg)
1009   br label %loop.ph
1011 loop.ph:
1012   br label %loop.header
1014 loop.header:
1015   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1016   %c = icmp ne ptr %ptr.iv, %upper
1017   br i1 %c, label %exit, label %for.body
1019 for.body:
1020   br label %loop.latch
1022 loop.latch:
1023   call void @use(ptr %ptr.iv)
1024   %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
1025   br label %loop.header
1027 exit:
1028   %c.2 = icmp uge ptr %ptr.iv, %start
1029   %c.3 = icmp ult ptr %ptr.iv, %upper
1030   %and = and i1 %c.2, %c.3
1031   call void @use.i1(i1 %and)
1032   ret void
1035 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_inbounds(ptr %start, i16 %len) {
1036 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge_no_inbounds(
1037 ; CHECK-NEXT:  entry:
1038 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
1039 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1040 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1041 ; CHECK:       loop.ph:
1042 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
1043 ; CHECK:       loop.header:
1044 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1045 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1046 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1047 ; CHECK:       for.body:
1048 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
1049 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1050 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
1051 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1052 ; CHECK:       loop.latch:
1053 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
1054 ; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
1055 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
1056 ; CHECK:       exit:
1057 ; CHECK-NEXT:    ret void
1059 entry:
1060   %upper = getelementptr i32, ptr %start, i16 %len
1061   %len.neg = icmp slt i16 %len, 0
1062   br i1 %len.neg, label %exit, label %loop.ph
1064 loop.ph:
1065   br label %loop.header
1067 loop.header:
1068   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1069   %c = icmp eq ptr %ptr.iv, %upper
1070   br i1 %c, label %exit, label %for.body
1072 for.body:
1073   %t.1 = icmp uge ptr %ptr.iv, %start
1074   %t.2 = icmp ult ptr %ptr.iv, %upper
1075   %and = and i1 %t.1, %t.2
1076   br i1 %and, label %loop.latch, label %exit
1078 loop.latch:
1079   call void @use(ptr %ptr.iv)
1080   %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
1081   br label %loop.header
1083 exit:
1084   ret void