xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.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_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
36;
37entry:
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
41
42loop.ph:
43  br label %loop.header
44
45loop.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
49
50for.body:
51  %c.1 = call i1 @cond()
52  br i1 %c.1, label %loop.next, label %exit
53
54loop.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
59
60loop.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
64
65exit:
66  ret void
67}
68
69define 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
94;
95entry:
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
99
100loop.ph:
101  br label %loop.header
102
103loop.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
107
108for.body:
109  %c.1 = call i1 @cond()
110  br i1 %c.1, label %loop.next, label %exit
111
112loop.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
117
118loop.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
122
123exit:
124  ret void
125}
126
127define 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
150;
151entry:
152  %start.ult.end = icmp uge ptr %start, %end
153  br i1 %start.ult.end, label %exit, label %loop.ph
154
155loop.ph:
156  br label %loop.header
157
158loop.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
162
163for.body:
164  %c.1 = call i1 @cond()
165  br i1 %c.1, label %loop.next, label %exit
166
167loop.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
172
173loop.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
177
178exit:
179  ret void
180}
181
182define 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
206;
207entry:
208  %start.ult.end = icmp uge ptr %start, %end
209  br i1 %start.ult.end, label %exit, label %loop.ph
210
211loop.ph:
212  br label %loop.header
213
214loop.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
218
219for.body:
220  %c.1 = call i1 @cond()
221  br i1 %c.1, label %loop.next, label %exit
222
223loop.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
228
229loop.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
233
234exit:
235  ret void
236}
237
238define 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
265;
266entry:
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
270
271loop.ph:
272  %start.ult.end = icmp ult ptr %start, %upper
273  call void @llvm.assume(i1 %start.ult.end)
274  br label %loop.header
275
276loop.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
280
281for.body:
282  %c.1 = call i1 @cond()
283  br i1 %c.1, label %loop.next, label %exit
284
285loop.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
290
291loop.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
295
296exit:
297  ret void
298}
299
300define 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
328;
329entry:
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
335
336loop.ph:
337  br label %loop.header
338
339loop.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
343
344for.body:
345  %c.1 = call i1 @cond()
346  br i1 %c.1, label %then, label %exit
347
348then:
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
353
354loop.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
358
359exit:
360  ret void
361}
362
363define 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
390;
391entry:
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
395
396loop.ph:
397  br label %loop.header
398
399loop.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
403
404for.body:
405  %c.1 = icmp ne ptr %ptr.iv, %upper
406  br i1 %c.1, label %then, label %loop.latch
407
408then:
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
414
415loop.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
419
420exit:
421  ret void
422}
423
424define 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
451;
452entry:
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
456
457loop.ph:
458  br label %loop.header
459
460loop.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
464
465for.body:
466  %c.0 = call i1 @cond()
467  br i1 %c.0, label %exit, label %loop.latch
468
469then:
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
475
476loop.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
480
481exit:
482  ret void
483}
484
485define 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
512;
513entry:
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
517
518loop.ph:
519  br label %loop.header
520
521loop.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
525
526for.body:
527  %c.1 = icmp ne ptr %ptr.iv, %upper
528  br i1 %c.1, label %then, label %loop.latch
529
530then:
531  br label %loop.latch
532
533loop.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
541
542exit:
543  ret void
544}
545
546define 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
572;
573entry:
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
577
578loop.ph:
579  br label %loop.header
580
581loop.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
585
586for.body:
587  %c.0 = call i1 @cond()
588  br i1 %c.0, label %exit, label %then
589
590then:
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
596
597loop.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
601
602exit:
603  ret void
604}
605
606define 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
633;
634entry:
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
638
639loop.ph:
640  br label %loop.header
641
642loop.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
646
647for.body:
648  %c.1 = icmp ne ptr %ptr.iv, %upper
649  br i1 %c.1, label %then, label %loop.latch
650
651then:
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
657
658loop.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
662
663exit:
664  ret void
665}
666
667define 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
694;
695entry:
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
699
700loop.ph:
701  br label %loop.header
702
703loop.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
707
708for.body:
709  %c.1 = icmp ne ptr %ptr.iv, %upper
710  br i1 %c.1, label %then, label %loop.latch
711
712then:
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
718
719loop.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
723
724exit:
725  ret void
726}
727
728define 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
755;
756entry:
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
760
761loop.ph:
762  br label %loop.header
763
764loop.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
768
769for.body:
770  %c.1 = icmp ne ptr %ptr.iv, %upper
771  br i1 %c.1, label %then, label %loop.latch
772
773then:
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
779
780loop.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
784
785exit:
786  ret void
787}
788
789define 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
817;
818entry:
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
823
824loop.ph:
825  br label %loop.header
826
827loop.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
831
832loop.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
836
837exit:
838  %c.1 = icmp ne ptr %ptr.iv, %upper
839  br i1 %c.1, label %then, label %exit.2
840
841then:
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
847
848exit.2:
849  ret void
850}
851
852define 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
878;
879entry:
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
883
884loop.ph:
885  br label %loop.header
886
887loop.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
891
892for.body:
893  %c.1 = call i1 @cond()
894  br i1 %c.1, label %loop.next, label %exit
895
896loop.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
901
902loop.latch:
903  call void @use(ptr %ptr.iv)
904  %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1
905  br label %loop.header
906
907exit:
908  ret void
909}
910
911define 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
935;
936entry:
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
940
941loop.ph:
942  br label %loop.header
943
944loop.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
948
949for.body:
950  %c.1 = call i1 @cond()
951  br i1 %c.1, label %loop.next, label %exit
952
953loop.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
958
959loop.latch:
960  call void @use(ptr %ptr.iv)
961  %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1
962  br label %loop.header
963
964exit:
965  ret void
966}
967
968define 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
993;
994entry:
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
998
999loop.ph:
1000  br label %loop.header
1001
1002loop.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
1006
1007for.body:
1008  %c.1 = call i1 @cond()
1009  br i1 %c.1, label %loop.next, label %exit
1010
1011loop.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
1016
1017loop.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
1021
1022exit:
1023  ret void
1024}
1025