xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-struct-types.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_struct_type(ptr %start, i16 %len) {
13; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type(
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, 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 {i16, i8, i8}, 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_struct_type_offset_0(ptr %start, i16 %len) {
63; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_0(
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0
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 [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
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 {i16, i8, i8}, ptr %start, i16 %len, i32 0
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 [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
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_struct_type_offset_16(ptr %start, i16 %len) {
113; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_16(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1
116; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
117; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
118; CHECK:       loop.ph:
119; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
120; CHECK:       loop.header:
121; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
122; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
123; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
124; CHECK:       for.body:
125; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
126; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
127; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
128; CHECK:       loop.latch:
129; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
130; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
131; CHECK-NEXT:    br label [[LOOP_HEADER]]
132; CHECK:       exit:
133; CHECK-NEXT:    ret void
134;
135entry:
136  %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 1
137  %len.neg = icmp slt i16 %len, 0
138  br i1 %len.neg, label %exit, label %loop.ph
139
140loop.ph:
141  br label %loop.header
142
143loop.header:
144  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
145  %c = icmp eq ptr %ptr.iv, %upper
146  br i1 %c, label %exit, label %for.body
147
148for.body:
149  %t.1 = icmp uge ptr %ptr.iv, %start
150  %t.2 = icmp ult ptr %ptr.iv, %upper
151  %and = and i1 %t.1, %t.2
152  br i1 %and, label %loop.latch, label %exit
153
154loop.latch:
155  call void @use(ptr %ptr.iv)
156  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
157  br label %loop.header
158
159exit:
160  ret void
161}
162
163define void @test_monotonic_ptr_iv_inc_1_struct_type_with_early_exit(ptr %start, i16 %len) {
164; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_with_early_exit(
165; CHECK-NEXT:  entry:
166; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0
167; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
168; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
169; CHECK:       loop.ph:
170; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
171; CHECK:       loop.header:
172; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
173; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
174; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
175; CHECK:       for.body:
176; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
177; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
178; CHECK:       loop.next:
179; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
180; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
181; CHECK:       loop.latch:
182; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
183; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
184; CHECK-NEXT:    br label [[LOOP_HEADER]]
185; CHECK:       exit:
186; CHECK-NEXT:    ret void
187;
188entry:
189  %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 0
190  %len.neg = icmp slt i16 %len, 0
191  br i1 %len.neg, label %exit, label %loop.ph
192
193loop.ph:
194  br label %loop.header
195
196loop.header:
197  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
198  %c = icmp eq ptr %ptr.iv, %upper
199  br i1 %c, label %exit, label %for.body
200
201for.body:
202  %c.1 = call i1 @cond()
203  br i1 %c.1, label %loop.next, label %exit
204
205loop.next:
206  %t.1 = icmp uge ptr %ptr.iv, %start
207  %t.2 = icmp ult ptr %ptr.iv, %upper
208  %and = and i1 %t.1, %t.2
209  br i1 %and, label %loop.latch, label %exit
210
211loop.latch:
212  call void @use(ptr %ptr.iv)
213  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
214  br label %loop.header
215
216exit:
217  ret void
218}
219
220define void @test_monotonic_ptr_iv_inc_1_struct_type_offset_0_with_early_exit(ptr %start, i16 %len) {
221; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_0_with_early_exit(
222; CHECK-NEXT:  entry:
223; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 0
224; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
225; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
226; CHECK:       loop.ph:
227; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
228; CHECK:       loop.header:
229; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
230; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
231; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
232; CHECK:       for.body:
233; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
234; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
235; CHECK:       loop.next:
236; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
237; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
238; CHECK:       loop.latch:
239; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
240; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
241; CHECK-NEXT:    br label [[LOOP_HEADER]]
242; CHECK:       exit:
243; CHECK-NEXT:    ret void
244;
245entry:
246  %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 0
247  %len.neg = icmp slt i16 %len, 0
248  br i1 %len.neg, label %exit, label %loop.ph
249
250loop.ph:
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 i32, 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_struct_type_offset_16_with_early_exit(ptr %start, i16 %len) {
278; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_struct_type_offset_16_with_early_exit(
279; CHECK-NEXT:  entry:
280; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, i8, i8 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1
281; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
282; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
283; CHECK:       loop.ph:
284; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
285; CHECK:       loop.header:
286; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
287; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
288; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
289; CHECK:       for.body:
290; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
291; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
292; CHECK:       loop.next:
293; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
294; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
295; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
296; CHECK:       loop.latch:
297; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
298; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
299; CHECK-NEXT:    br label [[LOOP_HEADER]]
300; CHECK:       exit:
301; CHECK-NEXT:    ret void
302;
303entry:
304  %upper = getelementptr inbounds {i16, i8, i8}, ptr %start, i16 %len, i32 1
305  %len.neg = icmp slt i16 %len, 0
306  br i1 %len.neg, label %exit, label %loop.ph
307
308loop.ph:
309  br label %loop.header
310
311loop.header:
312  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
313  %c = icmp eq ptr %ptr.iv, %upper
314  br i1 %c, label %exit, label %for.body
315
316for.body:
317  %c.1 = call i1 @cond()
318  br i1 %c.1, label %loop.next, label %exit
319
320loop.next:
321  %t.1 = icmp uge ptr %ptr.iv, %start
322  %t.2 = icmp ult ptr %ptr.iv, %upper
323  %and = and i1 %t.1, %t.2
324  br i1 %and, label %loop.latch, label %exit
325
326loop.latch:
327  call void @use(ptr %ptr.iv)
328  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
329  br label %loop.header
330
331exit:
332  ret void
333}
334
335define void @test_monotonic_ptr_iv_inc_2_struct_type_with_early_exit(ptr %start, i16 %len) {
336; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_with_early_exit(
337; CHECK-NEXT:  entry:
338; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
339; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
340; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
341; CHECK:       loop.ph:
342; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
343; CHECK:       loop.header:
344; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
345; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
346; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
347; CHECK:       for.body:
348; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
349; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
350; CHECK:       loop.next:
351; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
352; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
353; CHECK:       loop.latch:
354; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
355; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1
356; CHECK-NEXT:    br label [[LOOP_HEADER]]
357; CHECK:       exit:
358; CHECK-NEXT:    ret void
359;
360entry:
361  %upper = getelementptr inbounds i32, ptr %start, i16 %len
362  %len.neg = icmp slt i16 %len, 0
363  br i1 %len.neg, label %exit, label %loop.ph
364
365loop.ph:
366  br label %loop.header
367
368loop.header:
369  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
370  %c = icmp eq ptr %ptr.iv, %upper
371  br i1 %c, label %exit, label %for.body
372
373for.body:
374  %c.1 = call i1 @cond()
375  br i1 %c.1, label %loop.next, label %exit
376
377loop.next:
378  %t.1 = icmp uge ptr %ptr.iv, %start
379  %t.2 = icmp ult ptr %ptr.iv, %upper
380  %and = and i1 %t.1, %t.2
381  br i1 %and, label %loop.latch, label %exit
382
383loop.latch:
384  call void @use(ptr %ptr.iv)
385  %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1
386  br label %loop.header
387
388exit:
389  ret void
390}
391
392define void @test_monotonic_ptr_iv_inc_2_struct_type_offset_0_with_early_exit(ptr %start, i16 %len) {
393; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_offset_0_with_early_exit(
394; CHECK-NEXT:  entry:
395; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
396; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
397; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
398; CHECK:       loop.ph:
399; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
400; CHECK:       loop.header:
401; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
402; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
403; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
404; CHECK:       for.body:
405; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
406; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
407; CHECK:       loop.next:
408; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
409; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
410; CHECK:       loop.latch:
411; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
412; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1, i32 0
413; CHECK-NEXT:    br label [[LOOP_HEADER]]
414; CHECK:       exit:
415; CHECK-NEXT:    ret void
416;
417entry:
418  %upper = getelementptr inbounds i32, ptr %start, i16 %len
419  %len.neg = icmp slt i16 %len, 0
420  br i1 %len.neg, label %exit, label %loop.ph
421
422loop.ph:
423  br label %loop.header
424
425loop.header:
426  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
427  %c = icmp eq ptr %ptr.iv, %upper
428  br i1 %c, label %exit, label %for.body
429
430for.body:
431  %c.1 = call i1 @cond()
432  br i1 %c.1, label %loop.next, label %exit
433
434loop.next:
435  %t.1 = icmp uge ptr %ptr.iv, %start
436  %t.2 = icmp ult ptr %ptr.iv, %upper
437  %and = and i1 %t.1, %t.2
438  br i1 %and, label %loop.latch, label %exit
439
440loop.latch:
441  call void @use(ptr %ptr.iv)
442  %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1, i32 0
443  br label %loop.header
444
445exit:
446  ret void
447}
448
449define void @test_monotonic_ptr_iv_inc_2_struct_type_offset_16_with_early_exit(ptr %start, i16 %len) {
450; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_struct_type_offset_16_with_early_exit(
451; CHECK-NEXT:  entry:
452; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
453; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
454; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
455; CHECK:       loop.ph:
456; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
457; CHECK:       loop.header:
458; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
459; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
460; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
461; CHECK:       for.body:
462; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
463; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
464; CHECK:       loop.next:
465; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
466; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
467; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
468; CHECK:       loop.latch:
469; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
470; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i8, i8 }, ptr [[PTR_IV]], i16 1, i32 1
471; CHECK-NEXT:    br label [[LOOP_HEADER]]
472; CHECK:       exit:
473; CHECK-NEXT:    ret void
474;
475entry:
476  %upper = getelementptr inbounds i32, ptr %start, i16 %len
477  %len.neg = icmp slt i16 %len, 0
478  br i1 %len.neg, label %exit, label %loop.ph
479
480loop.ph:
481  br label %loop.header
482
483loop.header:
484  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
485  %c = icmp eq ptr %ptr.iv, %upper
486  br i1 %c, label %exit, label %for.body
487
488for.body:
489  %c.1 = call i1 @cond()
490  br i1 %c.1, label %loop.next, label %exit
491
492loop.next:
493  %t.1 = icmp uge ptr %ptr.iv, %start
494  %t.2 = icmp ult ptr %ptr.iv, %upper
495  %and = and i1 %t.1, %t.2
496  br i1 %and, label %loop.latch, label %exit
497
498loop.latch:
499  call void @use(ptr %ptr.iv)
500  %ptr.iv.next = getelementptr inbounds {i16, i8, i8}, ptr %ptr.iv, i16 1, i32 1
501  br label %loop.header
502
503exit:
504  ret void
505}
506
507define void @test_monotonic_ptr_iv_inc_1_nested_struct(ptr %start, i16 %len) {
508; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct(
509; CHECK-NEXT:  entry:
510; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]]
511; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
512; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
513; CHECK:       loop.ph:
514; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
515; CHECK:       loop.header:
516; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
517; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
518; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
519; CHECK:       for.body:
520; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
521; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
522; CHECK:       loop.next:
523; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
524; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
525; CHECK:       loop.latch:
526; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
527; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1
528; CHECK-NEXT:    br label [[LOOP_HEADER]]
529; CHECK:       exit:
530; CHECK-NEXT:    ret void
531;
532entry:
533  %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len
534  %len.neg = icmp slt i16 %len, 0
535  br i1 %len.neg, label %exit, label %loop.ph
536
537loop.ph:
538  br label %loop.header
539
540loop.header:
541  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
542  %c = icmp eq ptr %ptr.iv, %upper
543  br i1 %c, label %exit, label %for.body
544
545for.body:
546  %c.1 = call i1 @cond()
547  br i1 %c.1, label %loop.next, label %exit
548
549loop.next:
550  %t.1 = icmp uge ptr %ptr.iv, %start
551  %t.2 = icmp ult ptr %ptr.iv, %upper
552  %and = and i1 %t.1, %t.2
553  br i1 %and, label %loop.latch, label %exit
554
555loop.latch:
556  call void @use(ptr %ptr.iv)
557  %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1
558  br label %loop.header
559
560exit:
561  ret void
562}
563
564define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_64(ptr %start, i16 %len) {
565; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_64(
566; CHECK-NEXT:  entry:
567; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1
568; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
569; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
570; CHECK:       loop.ph:
571; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
572; CHECK:       loop.header:
573; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
574; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
575; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
576; CHECK:       for.body:
577; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
578; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
579; CHECK:       loop.next:
580; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
581; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
582; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
583; CHECK:       loop.latch:
584; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
585; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1
586; CHECK-NEXT:    br label [[LOOP_HEADER]]
587; CHECK:       exit:
588; CHECK-NEXT:    ret void
589;
590entry:
591  %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1
592  %len.neg = icmp slt i16 %len, 0
593  br i1 %len.neg, label %exit, label %loop.ph
594
595loop.ph:
596  br label %loop.header
597
598loop.header:
599  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
600  %c = icmp eq ptr %ptr.iv, %upper
601  br i1 %c, label %exit, label %for.body
602
603for.body:
604  %c.1 = call i1 @cond()
605  br i1 %c.1, label %loop.next, label %exit
606
607loop.next:
608  %t.1 = icmp uge ptr %ptr.iv, %start
609  %t.2 = icmp ult ptr %ptr.iv, %upper
610  %and = and i1 %t.1, %t.2
611  br i1 %and, label %loop.latch, label %exit
612
613loop.latch:
614  call void @use(ptr %ptr.iv)
615  %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1
616  br label %loop.header
617
618exit:
619  ret void
620}
621
622define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_32(ptr %start, i16 %len) {
623; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_32(
624; CHECK-NEXT:  entry:
625; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1
626; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
627; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
628; CHECK:       loop.ph:
629; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
630; CHECK:       loop.header:
631; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
632; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
633; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
634; CHECK:       for.body:
635; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
636; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
637; CHECK:       loop.next:
638; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
639; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
640; CHECK:       loop.latch:
641; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
642; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
643; CHECK-NEXT:    br label [[LOOP_HEADER]]
644; CHECK:       exit:
645; CHECK-NEXT:    ret void
646;
647entry:
648  %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1
649  %len.neg = icmp slt i16 %len, 0
650  br i1 %len.neg, label %exit, label %loop.ph
651
652loop.ph:
653  br label %loop.header
654
655loop.header:
656  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
657  %c = icmp eq ptr %ptr.iv, %upper
658  br i1 %c, label %exit, label %for.body
659
660for.body:
661  %c.1 = call i1 @cond()
662  br i1 %c.1, label %loop.next, label %exit
663
664loop.next:
665  %t.1 = icmp uge ptr %ptr.iv, %start
666  %t.2 = icmp ult ptr %ptr.iv, %upper
667  %and = and i1 %t.1, %t.2
668  br i1 %and, label %loop.latch, label %exit
669
670loop.latch:
671  call void @use(ptr %ptr.iv)
672  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
673  br label %loop.header
674
675exit:
676  ret void
677}
678
679define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_16(ptr %start, i16 %len) {
680; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_32_step_16(
681; CHECK-NEXT:  entry:
682; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, { i16, i16 }, i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i32 1
683; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
684; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
685; CHECK:       loop.ph:
686; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
687; CHECK:       loop.header:
688; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
689; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
690; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
691; CHECK:       for.body:
692; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
693; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
694; CHECK:       loop.next:
695; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
696; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
697; CHECK:       loop.latch:
698; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
699; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1
700; CHECK-NEXT:    br label [[LOOP_HEADER]]
701; CHECK:       exit:
702; CHECK-NEXT:    ret void
703;
704entry:
705  %upper = getelementptr inbounds {i16, {i16, i16}, i16}, ptr %start, i16 %len, i32 1, i32 1
706  %len.neg = icmp slt i16 %len, 0
707  br i1 %len.neg, label %exit, label %loop.ph
708
709loop.ph:
710  br label %loop.header
711
712loop.header:
713  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
714  %c = icmp eq ptr %ptr.iv, %upper
715  br i1 %c, label %exit, label %for.body
716
717for.body:
718  %c.1 = call i1 @cond()
719  br i1 %c.1, label %loop.next, label %exit
720
721loop.next:
722  %t.1 = icmp uge ptr %ptr.iv, %start
723  %t.2 = icmp ult ptr %ptr.iv, %upper
724  %and = and i1 %t.1, %t.2
725  br i1 %and, label %loop.latch, label %exit
726
727loop.latch:
728  call void @use(ptr %ptr.iv)
729  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1
730  br label %loop.header
731
732exit:
733  ret void
734}
735
736define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16(ptr %start, i16 %len) {
737; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16(
738; CHECK-NEXT:  entry:
739; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
740; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
741; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
742; CHECK:       loop.ph:
743; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
744; CHECK:       loop.header:
745; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
746; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
747; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
748; CHECK:       for.body:
749; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
750; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
751; CHECK:       loop.next:
752; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
753; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
754; CHECK:       loop.latch:
755; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
756; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 1
757; CHECK-NEXT:    br label [[LOOP_HEADER]]
758; CHECK:       exit:
759; CHECK-NEXT:    ret void
760;
761entry:
762  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
763  %len.neg = icmp slt i16 %len, 0
764  br i1 %len.neg, label %exit, label %loop.ph
765
766loop.ph:
767  br label %loop.header
768
769loop.header:
770  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
771  %c = icmp eq ptr %ptr.iv, %upper
772  br i1 %c, label %exit, label %for.body
773
774for.body:
775  %c.1 = call i1 @cond()
776  br i1 %c.1, label %loop.next, label %exit
777
778loop.next:
779  %t.1 = icmp uge ptr %ptr.iv, %start
780  %t.2 = icmp ult ptr %ptr.iv, %upper
781  %and = and i1 %t.1, %t.2
782  br i1 %and, label %loop.latch, label %exit
783
784loop.latch:
785  call void @use(ptr %ptr.iv)
786  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 1
787  br label %loop.header
788
789exit:
790  ret void
791}
792
793define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16_2(ptr %start, i16 %len) {
794; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_16_2(
795; CHECK-NEXT:  entry:
796; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
797; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
798; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
799; CHECK:       loop.ph:
800; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
801; CHECK:       loop.header:
802; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
803; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
804; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
805; CHECK:       for.body:
806; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
807; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
808; CHECK:       loop.next:
809; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
810; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
811; CHECK:       loop.latch:
812; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
813; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 2
814; CHECK-NEXT:    br label [[LOOP_HEADER]]
815; CHECK:       exit:
816; CHECK-NEXT:    ret void
817;
818entry:
819  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
820  %len.neg = icmp slt i16 %len, 0
821  br i1 %len.neg, label %exit, label %loop.ph
822
823loop.ph:
824  br label %loop.header
825
826loop.header:
827  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
828  %c = icmp eq ptr %ptr.iv, %upper
829  br i1 %c, label %exit, label %for.body
830
831for.body:
832  %c.1 = call i1 @cond()
833  br i1 %c.1, label %loop.next, label %exit
834
835loop.next:
836  %t.1 = icmp uge ptr %ptr.iv, %start
837  %t.2 = icmp ult ptr %ptr.iv, %upper
838  %and = and i1 %t.1, %t.2
839  br i1 %and, label %loop.latch, label %exit
840
841loop.latch:
842  call void @use(ptr %ptr.iv)
843  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 2
844  br label %loop.header
845
846exit:
847  ret void
848}
849
850define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32(ptr %start, i16 %len) {
851; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32(
852; CHECK-NEXT:  entry:
853; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
854; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
855; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
856; CHECK:       loop.ph:
857; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
858; CHECK:       loop.header:
859; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
860; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
861; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
862; CHECK:       for.body:
863; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
864; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
865; CHECK:       loop.next:
866; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
867; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
868; CHECK:       loop.latch:
869; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
870; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
871; CHECK-NEXT:    br label [[LOOP_HEADER]]
872; CHECK:       exit:
873; CHECK-NEXT:    ret void
874;
875entry:
876  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
877  %len.neg = icmp slt i16 %len, 0
878  br i1 %len.neg, label %exit, label %loop.ph
879
880loop.ph:
881  br label %loop.header
882
883loop.header:
884  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
885  %c = icmp eq ptr %ptr.iv, %upper
886  br i1 %c, label %exit, label %for.body
887
888for.body:
889  %c.1 = call i1 @cond()
890  br i1 %c.1, label %loop.next, label %exit
891
892loop.next:
893  %t.1 = icmp uge ptr %ptr.iv, %start
894  %t.2 = icmp ult ptr %ptr.iv, %upper
895  %and = and i1 %t.1, %t.2
896  br i1 %and, label %loop.latch, label %exit
897
898loop.latch:
899  call void @use(ptr %ptr.iv)
900  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
901  br label %loop.header
902
903exit:
904  ret void
905}
906
907define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32_2(ptr %start, i16 %len) {
908; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_32_2(
909; CHECK-NEXT:  entry:
910; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
911; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
912; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
913; CHECK:       loop.ph:
914; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
915; CHECK:       loop.header:
916; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
917; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
918; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
919; CHECK:       for.body:
920; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
921; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
922; CHECK:       loop.next:
923; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
924; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
925; CHECK:       loop.latch:
926; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
927; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 2
928; CHECK-NEXT:    br label [[LOOP_HEADER]]
929; CHECK:       exit:
930; CHECK-NEXT:    ret void
931;
932entry:
933  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
934  %len.neg = icmp slt i16 %len, 0
935  br i1 %len.neg, label %exit, label %loop.ph
936
937loop.ph:
938  br label %loop.header
939
940loop.header:
941  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
942  %c = icmp eq ptr %ptr.iv, %upper
943  br i1 %c, label %exit, label %for.body
944
945for.body:
946  %c.1 = call i1 @cond()
947  br i1 %c.1, label %loop.next, label %exit
948
949loop.next:
950  %t.1 = icmp uge ptr %ptr.iv, %start
951  %t.2 = icmp ult ptr %ptr.iv, %upper
952  %and = and i1 %t.1, %t.2
953  br i1 %and, label %loop.latch, label %exit
954
955loop.latch:
956  call void @use(ptr %ptr.iv)
957  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 2
958  br label %loop.header
959
960exit:
961  ret void
962}
963
964define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_64(ptr %start, i16 %len) {
965; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_64(
966; CHECK-NEXT:  entry:
967; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
968; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
969; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
970; CHECK:       loop.ph:
971; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
972; CHECK:       loop.header:
973; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
974; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
975; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
976; CHECK:       for.body:
977; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
978; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
979; CHECK:       loop.next:
980; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
981; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
982; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
983; CHECK:       loop.latch:
984; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
985; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i64, ptr [[PTR_IV]], i16 1
986; CHECK-NEXT:    br label [[LOOP_HEADER]]
987; CHECK:       exit:
988; CHECK-NEXT:    ret void
989;
990entry:
991  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
992  %len.neg = icmp slt i16 %len, 0
993  br i1 %len.neg, label %exit, label %loop.ph
994
995loop.ph:
996  br label %loop.header
997
998loop.header:
999  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1000  %c = icmp eq ptr %ptr.iv, %upper
1001  br i1 %c, label %exit, label %for.body
1002
1003for.body:
1004  %c.1 = call i1 @cond()
1005  br i1 %c.1, label %loop.next, label %exit
1006
1007loop.next:
1008  %t.1 = icmp uge ptr %ptr.iv, %start
1009  %t.2 = icmp ult ptr %ptr.iv, %upper
1010  %and = and i1 %t.1, %t.2
1011  br i1 %and, label %loop.latch, label %exit
1012
1013loop.latch:
1014  call void @use(ptr %ptr.iv)
1015  %ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i16 1
1016  br label %loop.header
1017
1018exit:
1019  ret void
1020}
1021
1022define void @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_var(ptr %start, i16 %len, i16 %step) {
1023; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_nested_struct_offset_16_plus_32_var_step_var(
1024; CHECK-NEXT:  entry:
1025; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds { i16, [10 x i32], i16 }, ptr [[START:%.*]], i16 [[LEN:%.*]], i32 1, i16 [[LEN]]
1026; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1027; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1028; CHECK:       loop.ph:
1029; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
1030; CHECK:       loop.header:
1031; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1032; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1033; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1034; CHECK:       for.body:
1035; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
1036; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
1037; CHECK:       loop.next:
1038; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
1039; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1040; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
1041; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1042; CHECK:       loop.latch:
1043; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
1044; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i16, ptr [[PTR_IV]], i16 [[STEP:%.*]]
1045; CHECK-NEXT:    br label [[LOOP_HEADER]]
1046; CHECK:       exit:
1047; CHECK-NEXT:    ret void
1048;
1049entry:
1050  %upper = getelementptr inbounds {i16, [10 x i32], i16}, ptr %start, i16 %len, i32 1, i16 %len
1051  %len.neg = icmp slt i16 %len, 0
1052  br i1 %len.neg, label %exit, label %loop.ph
1053
1054loop.ph:
1055  br label %loop.header
1056
1057loop.header:
1058  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1059  %c = icmp eq ptr %ptr.iv, %upper
1060  br i1 %c, label %exit, label %for.body
1061
1062for.body:
1063  %c.1 = call i1 @cond()
1064  br i1 %c.1, label %loop.next, label %exit
1065
1066loop.next:
1067  %t.1 = icmp uge ptr %ptr.iv, %start
1068  %t.2 = icmp ult ptr %ptr.iv, %upper
1069  %and = and i1 %t.1, %t.2
1070  br i1 %and, label %loop.latch, label %exit
1071
1072loop.latch:
1073  call void @use(ptr %ptr.iv)
1074  %ptr.iv.next = getelementptr inbounds i16, ptr %ptr.iv, i16 %step
1075  br label %loop.header
1076
1077exit:
1078  ret void
1079}
1080
1081define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_48(ptr %start, i16 %len) {
1082; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_48(
1083; CHECK-NEXT:  entry:
1084; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
1085; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1086; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1087; CHECK:       loop.ph:
1088; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
1089; CHECK:       loop.header:
1090; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1091; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1092; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1093; CHECK:       for.body:
1094; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
1095; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
1096; CHECK:       loop.next:
1097; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1098; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
1099; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1100; CHECK:       loop.latch:
1101; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
1102; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 0
1103; CHECK-NEXT:    br label [[LOOP_HEADER]]
1104; CHECK:       exit:
1105; CHECK-NEXT:    ret void
1106;
1107entry:
1108  %upper = getelementptr inbounds i64, ptr %start, i16 %len
1109  %len.neg = icmp slt i16 %len, 0
1110  br i1 %len.neg, label %exit, label %loop.ph
1111
1112loop.ph:
1113  br label %loop.header
1114
1115loop.header:
1116  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1117  %c = icmp eq ptr %ptr.iv, %upper
1118  br i1 %c, label %exit, label %for.body
1119
1120for.body:
1121  %c.1 = call i1 @cond()
1122  br i1 %c.1, label %loop.next, label %exit
1123
1124loop.next:
1125  %t.1 = icmp uge ptr %ptr.iv, %start
1126  %t.2 = icmp ult ptr %ptr.iv, %upper
1127  %and = and i1 %t.1, %t.2
1128  br i1 %and, label %loop.latch, label %exit
1129
1130loop.latch:
1131  call void @use(ptr %ptr.iv)
1132  %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 0
1133  br label %loop.header
1134
1135exit:
1136  ret void
1137}
1138
1139define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_64(ptr %start, i16 %len) {
1140; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_64(
1141; CHECK-NEXT:  entry:
1142; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
1143; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1144; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1145; CHECK:       loop.ph:
1146; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
1147; CHECK:       loop.header:
1148; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1149; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1150; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1151; CHECK:       for.body:
1152; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
1153; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
1154; CHECK:       loop.next:
1155; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
1156; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1157; CHECK:       loop.latch:
1158; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
1159; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 1
1160; CHECK-NEXT:    br label [[LOOP_HEADER]]
1161; CHECK:       exit:
1162; CHECK-NEXT:    ret void
1163;
1164entry:
1165  %upper = getelementptr inbounds i64, ptr %start, i16 %len
1166  %len.neg = icmp slt i16 %len, 0
1167  br i1 %len.neg, label %exit, label %loop.ph
1168
1169loop.ph:
1170  br label %loop.header
1171
1172loop.header:
1173  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1174  %c = icmp eq ptr %ptr.iv, %upper
1175  br i1 %c, label %exit, label %for.body
1176
1177for.body:
1178  %c.1 = call i1 @cond()
1179  br i1 %c.1, label %loop.next, label %exit
1180
1181loop.next:
1182  %t.1 = icmp uge ptr %ptr.iv, %start
1183  %t.2 = icmp ult ptr %ptr.iv, %upper
1184  %and = and i1 %t.1, %t.2
1185  br i1 %and, label %loop.latch, label %exit
1186
1187loop.latch:
1188  call void @use(ptr %ptr.iv)
1189  %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 1
1190  br label %loop.header
1191
1192exit:
1193  ret void
1194}
1195
1196define void @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_80(ptr %start, i16 %len) {
1197; CHECK-LABEL: @test_monotonic_ptr_iv_inc_with_struct_type_with_early_exit_offset_80(
1198; CHECK-NEXT:  entry:
1199; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i64, ptr [[START:%.*]], i16 [[LEN:%.*]]
1200; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
1201; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
1202; CHECK:       loop.ph:
1203; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
1204; CHECK:       loop.header:
1205; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1206; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
1207; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
1208; CHECK:       for.body:
1209; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
1210; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
1211; CHECK:       loop.next:
1212; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
1213; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
1214; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
1215; CHECK:       loop.latch:
1216; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
1217; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds { i16, i16, i16 }, ptr [[PTR_IV]], i16 1, i32 2
1218; CHECK-NEXT:    br label [[LOOP_HEADER]]
1219; CHECK:       exit:
1220; CHECK-NEXT:    ret void
1221;
1222entry:
1223  %upper = getelementptr inbounds i64, ptr %start, i16 %len
1224  %len.neg = icmp slt i16 %len, 0
1225  br i1 %len.neg, label %exit, label %loop.ph
1226
1227loop.ph:
1228  br label %loop.header
1229
1230loop.header:
1231  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
1232  %c = icmp eq ptr %ptr.iv, %upper
1233  br i1 %c, label %exit, label %for.body
1234
1235for.body:
1236  %c.1 = call i1 @cond()
1237  br i1 %c.1, label %loop.next, label %exit
1238
1239loop.next:
1240  %t.1 = icmp uge ptr %ptr.iv, %start
1241  %t.2 = icmp ult ptr %ptr.iv, %upper
1242  %and = and i1 %t.1, %t.2
1243  br i1 %and, label %loop.latch, label %exit
1244
1245loop.latch:
1246  call void @use(ptr %ptr.iv)
1247  %ptr.iv.next = getelementptr inbounds { i16, i16, i16 }, ptr %ptr.iv, i16 1, i32 2
1248  br label %loop.header
1249
1250exit:
1251  ret void
1252}
1253