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 i1 @cond()
9
10define void @test_monotonic_ptr_iv_inc_1_eq_to_uge(ptr %start) {
11; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge(
12; CHECK-NEXT:  loop.ph:
13; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 10
14; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
15; CHECK:       loop.header:
16; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
17; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
18; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
19; CHECK:       for.body:
20; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
21; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
22; CHECK:       loop.latch:
23; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
24; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
25; CHECK-NEXT:    br label [[LOOP_HEADER]]
26; CHECK:       exit:
27; CHECK-NEXT:    ret void
28;
29loop.ph:
30  %upper = getelementptr inbounds i32, ptr %start, i16 10
31  br label %loop.header
32
33loop.header:
34  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
35  %c = icmp eq ptr %ptr.iv, %upper
36  br i1 %c, label %exit, label %for.body
37
38for.body:
39  %t.1 = icmp uge ptr %ptr.iv, %start
40  %t.2 = icmp ult ptr %ptr.iv, %upper
41  %and = and i1 %t.1, %t.2
42  br i1 %and, label %loop.latch, label %exit
43
44loop.latch:
45  call void @use(ptr %ptr.iv)
46  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
47  br label %loop.header
48
49exit:
50  ret void
51}
52
53define void @test_monotonic_ptr_iv_inc_1_upper_is_multiple_1(ptr %start) {
54; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_multiple_1(
55; CHECK-NEXT:  loop.ph:
56; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 15
57; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
58; CHECK:       loop.header:
59; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
60; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
61; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
62; CHECK:       for.body:
63; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
64; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
65; CHECK:       loop.latch:
66; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
67; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
68; CHECK-NEXT:    br label [[LOOP_HEADER]]
69; CHECK:       exit:
70; CHECK-NEXT:    ret void
71;
72loop.ph:
73  %upper = getelementptr inbounds i8, ptr %start, i16 15
74  br label %loop.header
75
76loop.header:
77  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
78  %c = icmp eq ptr %ptr.iv, %upper
79  br i1 %c, label %exit, label %for.body
80
81for.body:
82  %t.1 = icmp uge ptr %ptr.iv, %start
83  %t.2 = icmp ult ptr %ptr.iv, %upper
84  %and = and i1 %t.1, %t.2
85  br i1 %and, label %loop.latch, label %exit
86
87loop.latch:
88  call void @use(ptr %ptr.iv)
89  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
90  br label %loop.header
91
92exit:
93  ret void
94}
95
96define void @test_monotonic_ptr_iv_inc_1_upper_is_multiple_2(ptr %start) {
97; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_multiple_2(
98; CHECK-NEXT:  loop.ph:
99; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 16
100; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
101; CHECK:       loop.header:
102; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
103; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
104; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
105; CHECK:       for.body:
106; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
107; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
108; CHECK:       loop.latch:
109; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
110; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1
111; CHECK-NEXT:    br label [[LOOP_HEADER]]
112; CHECK:       exit:
113; CHECK-NEXT:    ret void
114;
115loop.ph:
116  %upper = getelementptr inbounds i8, ptr %start, i16 16
117  br label %loop.header
118
119loop.header:
120  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
121  %c = icmp eq ptr %ptr.iv, %upper
122  br i1 %c, label %exit, label %for.body
123
124for.body:
125  %t.1 = icmp uge ptr %ptr.iv, %start
126  %t.2 = icmp ult ptr %ptr.iv, %upper
127  %and = and i1 %t.1, %t.2
128  br i1 %and, label %loop.latch, label %exit
129
130loop.latch:
131  call void @use(ptr %ptr.iv)
132  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1
133  br label %loop.header
134
135exit:
136  ret void
137}
138
139define void @test_monotonic_ptr_iv_inc_upper_is_not_multiple_1(ptr %start) {
140; CHECK-LABEL: @test_monotonic_ptr_iv_inc_upper_is_not_multiple_1(
141; CHECK-NEXT:  loop.ph:
142; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 15
143; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
144; CHECK:       loop.header:
145; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
146; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
147; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
148; CHECK:       for.body:
149; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
150; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
151; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
152; CHECK:       loop.latch:
153; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
154; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
155; CHECK-NEXT:    br label [[LOOP_HEADER]]
156; CHECK:       exit:
157; CHECK-NEXT:    ret void
158;
159loop.ph:
160  %upper = getelementptr inbounds i8, ptr %start, i16 15
161  br label %loop.header
162
163loop.header:
164  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
165  %c = icmp eq ptr %ptr.iv, %upper
166  br i1 %c, label %exit, label %for.body
167
168for.body:
169  %t.1 = icmp uge ptr %ptr.iv, %start
170  %t.2 = icmp ult ptr %ptr.iv, %upper
171  %and = and i1 %t.1, %t.2
172  br i1 %and, label %loop.latch, label %exit
173
174loop.latch:
175  call void @use(ptr %ptr.iv)
176  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
177  br label %loop.header
178
179exit:
180  ret void
181}
182
183define void @test_monotonic_ptr_iv_inc_upper_is_not_multiple_2(ptr %start) {
184; CHECK-LABEL: @test_monotonic_ptr_iv_inc_upper_is_not_multiple_2(
185; CHECK-NEXT:  loop.ph:
186; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 15
187; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
188; CHECK:       loop.header:
189; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
190; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
191; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
192; CHECK:       for.body:
193; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
194; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
195; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
196; CHECK:       loop.latch:
197; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
198; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
199; CHECK-NEXT:    br label [[LOOP_HEADER]]
200; CHECK:       exit:
201; CHECK-NEXT:    ret void
202;
203loop.ph:
204  %upper = getelementptr inbounds i8, ptr %start, i16 15
205  br label %loop.header
206
207loop.header:
208  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
209  %c = icmp eq ptr %ptr.iv, %upper
210  br i1 %c, label %exit, label %for.body
211
212for.body:
213  %t.1 = icmp uge ptr %ptr.iv, %start
214  %t.2 = icmp ult ptr %ptr.iv, %upper
215  %and = and i1 %t.1, %t.2
216  br i1 %and, label %loop.latch, label %exit
217
218loop.latch:
219  call void @use(ptr %ptr.iv)
220  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
221  br label %loop.header
222
223exit:
224  ret void
225}
226
227define void @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_1(ptr %start) {
228; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_1(
229; CHECK-NEXT:  loop.ph:
230; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 10
231; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
232; CHECK:       loop.header:
233; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
234; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
235; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
236; CHECK:       for.body:
237; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
238; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
239; CHECK:       loop.next:
240; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
241; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
242; CHECK:       loop.latch:
243; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
244; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
245; CHECK-NEXT:    br label [[LOOP_HEADER]]
246; CHECK:       exit:
247; CHECK-NEXT:    ret void
248;
249loop.ph:
250  %upper = getelementptr inbounds i8, ptr %start, i16 10
251  br label %loop.header
252
253loop.header:
254  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
255  %c = icmp eq ptr %ptr.iv, %upper
256  br i1 %c, label %exit, label %for.body
257
258for.body:
259  %c.1 = call i1 @cond()
260  br i1 %c.1, label %loop.next, label %exit
261
262loop.next:
263  %t.1 = icmp uge ptr %ptr.iv, %start
264  %t.2 = icmp ult ptr %ptr.iv, %upper
265  %and = and i1 %t.1, %t.2
266  br i1 %and, label %loop.latch, label %exit
267
268loop.latch:
269  call void @use(ptr %ptr.iv)
270  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
271  br label %loop.header
272
273exit:
274  ret void
275}
276
277define void @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_2(ptr %start) {
278; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_2(
279; CHECK-NEXT:  loop.ph:
280; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 10
281; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
282; CHECK:       loop.header:
283; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
284; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
285; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
286; CHECK:       for.body:
287; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
288; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
289; CHECK:       loop.next:
290; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
291; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
292; CHECK:       loop.latch:
293; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
294; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1
295; CHECK-NEXT:    br label [[LOOP_HEADER]]
296; CHECK:       exit:
297; CHECK-NEXT:    ret void
298;
299loop.ph:
300  %upper = getelementptr inbounds i8, ptr %start, i16 10
301  br label %loop.header
302
303loop.header:
304  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
305  %c = icmp eq ptr %ptr.iv, %upper
306  br i1 %c, label %exit, label %for.body
307
308for.body:
309  %c.1 = call i1 @cond()
310  br i1 %c.1, label %loop.next, label %exit
311
312loop.next:
313  %t.1 = icmp uge ptr %ptr.iv, %start
314  %t.2 = icmp ult ptr %ptr.iv, %upper
315  %and = and i1 %t.1, %t.2
316  br i1 %and, label %loop.latch, label %exit
317
318loop.latch:
319  call void @use(ptr %ptr.iv)
320  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1
321  br label %loop.header
322
323exit:
324  ret void
325}
326
327define void @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_3(ptr %start) {
328; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_multiple_with_early_exit_3(
329; CHECK-NEXT:  loop.ph:
330; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i16, ptr [[START:%.*]], i16 16
331; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
332; CHECK:       loop.header:
333; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
334; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
335; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
336; CHECK:       for.body:
337; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
338; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
339; CHECK:       loop.next:
340; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
341; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
342; CHECK:       loop.latch:
343; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
344; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
345; CHECK-NEXT:    br label [[LOOP_HEADER]]
346; CHECK:       exit:
347; CHECK-NEXT:    ret void
348;
349loop.ph:
350  %upper = getelementptr inbounds i16, ptr %start, i16 16
351  br label %loop.header
352
353loop.header:
354  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
355  %c = icmp eq ptr %ptr.iv, %upper
356  br i1 %c, label %exit, label %for.body
357
358for.body:
359  %c.1 = call i1 @cond()
360  br i1 %c.1, label %loop.next, label %exit
361
362loop.next:
363  %t.1 = icmp uge ptr %ptr.iv, %start
364  %t.2 = icmp ult ptr %ptr.iv, %upper
365  %and = and i1 %t.1, %t.2
366  br i1 %and, label %loop.latch, label %exit
367
368loop.latch:
369  call void @use(ptr %ptr.iv)
370  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
371  br label %loop.header
372
373exit:
374  ret void
375}
376
377define void @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_1(ptr %start) {
378; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_1(
379; CHECK-NEXT:  loop.ph:
380; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 10
381; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
382; CHECK:       loop.header:
383; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
384; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
385; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
386; CHECK:       for.body:
387; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
388; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
389; CHECK:       loop.next:
390; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
391; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
392; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
393; CHECK:       loop.latch:
394; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
395; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
396; CHECK-NEXT:    br label [[LOOP_HEADER]]
397; CHECK:       exit:
398; CHECK-NEXT:    ret void
399;
400loop.ph:
401  %upper = getelementptr inbounds i8, ptr %start, i16 10
402  br label %loop.header
403
404loop.header:
405  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
406  %c = icmp eq ptr %ptr.iv, %upper
407  br i1 %c, label %exit, label %for.body
408
409for.body:
410  %c.1 = call i1 @cond()
411  br i1 %c.1, label %loop.next, label %exit
412
413loop.next:
414  %t.1 = icmp uge ptr %ptr.iv, %start
415  %t.2 = icmp ult ptr %ptr.iv, %upper
416  %and = and i1 %t.1, %t.2
417  br i1 %and, label %loop.latch, label %exit
418
419loop.latch:
420  call void @use(ptr %ptr.iv)
421  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
422  br label %loop.header
423
424exit:
425  ret void
426}
427
428define void @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_2(ptr %start) {
429; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_2(
430; CHECK-NEXT:  loop.ph:
431; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 11
432; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
433; CHECK:       loop.header:
434; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
435; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
436; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
437; CHECK:       for.body:
438; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
439; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
440; CHECK:       loop.next:
441; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
442; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
443; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
444; CHECK:       loop.latch:
445; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
446; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1
447; CHECK-NEXT:    br label [[LOOP_HEADER]]
448; CHECK:       exit:
449; CHECK-NEXT:    ret void
450;
451loop.ph:
452  %upper = getelementptr inbounds i8, ptr %start, i16 11
453  br label %loop.header
454
455loop.header:
456  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
457  %c = icmp eq ptr %ptr.iv, %upper
458  br i1 %c, label %exit, label %for.body
459
460for.body:
461  %c.1 = call i1 @cond()
462  br i1 %c.1, label %loop.next, label %exit
463
464loop.next:
465  %t.1 = icmp uge ptr %ptr.iv, %start
466  %t.2 = icmp ult ptr %ptr.iv, %upper
467  %and = and i1 %t.1, %t.2
468  br i1 %and, label %loop.latch, label %exit
469
470loop.latch:
471  call void @use(ptr %ptr.iv)
472  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1
473  br label %loop.header
474
475exit:
476  ret void
477}
478
479define void @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_3(ptr %start) {
480; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_upper_is_no_multiple_with_early_exit_3(
481; CHECK-NEXT:  loop.ph:
482; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i16, ptr [[START:%.*]], i16 9
483; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
484; CHECK:       loop.header:
485; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
486; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
487; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
488; CHECK:       for.body:
489; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
490; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
491; CHECK:       loop.next:
492; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
493; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
494; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
495; CHECK:       loop.latch:
496; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
497; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
498; CHECK-NEXT:    br label [[LOOP_HEADER]]
499; CHECK:       exit:
500; CHECK-NEXT:    ret void
501;
502loop.ph:
503  %upper = getelementptr inbounds i16, ptr %start, i16 9
504  br label %loop.header
505
506loop.header:
507  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
508  %c = icmp eq ptr %ptr.iv, %upper
509  br i1 %c, label %exit, label %for.body
510
511for.body:
512  %c.1 = call i1 @cond()
513  br i1 %c.1, label %loop.next, label %exit
514
515loop.next:
516  %t.1 = icmp uge ptr %ptr.iv, %start
517  %t.2 = icmp ult ptr %ptr.iv, %upper
518  %and = and i1 %t.1, %t.2
519  br i1 %and, label %loop.latch, label %exit
520
521loop.latch:
522  call void @use(ptr %ptr.iv)
523  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
524  br label %loop.header
525
526exit:
527  ret void
528}
529