xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll (revision e6a1657fa30c747f4412fc47f567660ebe861a9e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
5
6
7declare void @use(ptr)
8declare void @use.i1(i1)
9declare void @llvm.assume(i1)
10declare i1 @cond()
11
12define 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
33;
34entry:
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
38
39loop.ph:
40  br label %loop.header
41
42loop.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
46
47for.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
52
53loop.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
57
58exit:
59  ret void
60}
61
62define 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
83;
84entry:
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
88
89loop.ph:
90  br label %loop.header
91
92loop.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
96
97for.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
102
103loop.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
107
108exit:
109  ret void
110}
111
112define 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
131;
132entry:
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
136
137loop.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
141
142for.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
147
148loop.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
152
153exit:
154  ret void
155}
156
157define 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
178;
179entry:
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
183
184loop.ph:
185  br label %loop.header
186
187loop.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
191
192for.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
197
198loop.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
202
203exit:
204  ret void
205}
206
207define 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
229;
230entry:
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
234
235loop.ph:
236  br label %loop.header
237
238loop.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
242
243for.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
248
249loop.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
253
254exit:
255  ret void
256}
257
258define 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
278;
279entry:
280  %start.ult.end = icmp uge ptr %start, %end
281  br i1 %start.ult.end, label %exit, label %loop.ph
282
283loop.ph:
284  br label %loop.header
285
286loop.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
290
291for.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
296
297loop.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
301
302exit:
303  ret void
304}
305
306define 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
327;
328entry:
329  %start.ult.end = icmp uge ptr %start, %end
330  br i1 %start.ult.end, label %exit, label %loop.ph
331
332loop.ph:
333  br label %loop.header
334
335loop.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
339
340for.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
345
346loop.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
350
351exit:
352  ret void
353}
354
355define 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
374;
375entry:
376  %upper = getelementptr inbounds i32, ptr %start, i16 %len
377  br label %loop.header
378
379loop.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
383
384for.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
389
390loop.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
394
395exit:
396  ret void
397}
398
399define 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
422;
423entry:
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
427
428loop.ph:
429  br label %loop.header
430
431loop.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
435
436for.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
441
442loop.latch:
443  call void @use(ptr %ptr.iv)
444  %ptr.iv.next = getelementptr inbounds i32, ptr %p, i16 1
445  br label %loop.header
446
447exit:
448  ret void
449}
450
451define 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
475;
476entry:
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
480
481loop.ph:
482  br label %loop.header
483
484loop.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
489
490loop.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
495
496loop.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
500
501exit:
502  ret void
503}
504
505define 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
528;
529entry:
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
533
534loop.ph:
535  br label %loop.header
536
537loop.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
541
542for.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
547
548loop.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
552
553exit:
554  ret void
555}
556
557define 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
578;
579entry:
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
583
584loop.ph:
585  br label %loop.header
586
587loop.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
591
592for.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
597
598loop.latch:
599  call void @use(ptr %ptr.iv)
600  %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
601  br label %loop.header
602
603exit:
604  ret void
605}
606
607define 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
630;
631entry:
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
635
636loop.ph:
637  br label %loop.header
638
639loop.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
643
644for.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
649
650loop.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
654
655exit:
656  ret void
657}
658
659define 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
682;
683entry:
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
687
688loop.ph:
689  br label %loop.header
690
691loop.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
695
696for.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
701
702loop.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
706
707exit:
708  ret void
709}
710
711define 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
734;
735entry:
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
739
740loop.ph:
741  br label %loop.header
742
743loop.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
747
748for.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
753
754loop.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
758
759exit:
760  ret void
761}
762
763define 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
788;
789entry:
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
795
796loop.ph:
797  br label %loop.header
798
799loop.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
803
804for.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
809
810loop.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
814
815exit:
816  ret void
817}
818
819define 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
844;
845entry:
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
851
852loop.ph:
853  br label %loop.header
854
855loop.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
859
860for.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
865
866loop.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
870
871exit:
872  ret void
873}
874
875define 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
897;
898entry:
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
902
903loop.ph:
904  br label %loop.header
905
906loop.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
910
911for.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
916
917loop.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
921
922exit:
923  ret void
924}
925
926define 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
949;
950entry:
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
954
955loop.ph:
956  br label %loop.header
957
958loop.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
962
963for.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
969
970loop.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
974
975exit:
976  ret void
977}
978
979define 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
1004;
1005entry:
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
1010
1011loop.ph:
1012  br label %loop.header
1013
1014loop.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
1018
1019for.body:
1020  br label %loop.latch
1021
1022loop.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
1026
1027exit:
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
1033}
1034
1035define 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
1058;
1059entry:
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
1063
1064loop.ph:
1065  br label %loop.header
1066
1067loop.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
1071
1072for.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
1077
1078loop.latch:
1079  call void @use(ptr %ptr.iv)
1080  %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
1081  br label %loop.header
1082
1083exit:
1084  ret void
1085}
1086
1087