1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4; NOTE: The custom datalayout defines i32 to be 64 bit aligned.
5
6target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i32:64:64-f80:128-n8:16:32:64-S128"
7
8declare void @use(ptr)
9declare i1 @cond()
10
11define void @test_monotonic_ptr_iv_inc_1_element_types_with_different_alloc_type_sizes(ptr %start, i16 %len) {
12; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_element_types_with_different_alloc_type_sizes(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
15; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
16; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
17; CHECK:       loop.ph:
18; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
19; CHECK:       loop.header:
20; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
21; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
22; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
23; CHECK:       for.body:
24; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
25; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
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 float, 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_2_element_types_with_different_alloc_type_sizes(ptr %start, i16 %len) {
63; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_element_types_with_different_alloc_type_sizes(
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
66; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
67; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
68; CHECK:       loop.ph:
69; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
70; CHECK:       loop.header:
71; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[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 float, ptr [[PTR_IV]], i16 1
80; CHECK-NEXT:    br label [[LOOP_HEADER]]
81; CHECK:       exit:
82; CHECK-NEXT:    ret void
83;
84entry:
85  %upper = getelementptr inbounds i32, ptr %start, i16 %len
86  %len.neg = icmp slt i16 %len, 0
87  br i1 %len.neg, label %exit, label %loop.ph
88
89loop.ph:
90  br label %loop.header
91
92loop.header:
93  %ptr.iv = phi ptr [ %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 float, 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_different_element_types_with_same_alloc_type_sizes(ptr %start, i16 %len) {
113; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_with_same_alloc_type_sizes(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i5, ptr [[START:%.*]], i16 [[LEN:%.*]]
116; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
117; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_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:    [[AND:%.*]] = and i1 true, true
126; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
127; CHECK:       loop.latch:
128; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
129; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i7, ptr [[PTR_IV]], i16 1
130; CHECK-NEXT:    br label [[LOOP_HEADER]]
131; CHECK:       exit:
132; CHECK-NEXT:    ret void
133;
134entry:
135  %upper = getelementptr inbounds i5, ptr %start, i16 %len
136  %len.neg = icmp slt i16 %len, 0
137  br i1 %len.neg, label %exit, label %loop.ph
138
139loop.ph:
140  br label %loop.header
141
142loop.header:
143  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
144  %c = icmp eq ptr %ptr.iv, %upper
145  br i1 %c, label %exit, label %for.body
146
147for.body:
148  %t.1 = icmp uge ptr %ptr.iv, %start
149  %t.2 = icmp ult ptr %ptr.iv, %upper
150  %and = and i1 %t.1, %t.2
151  br i1 %and, label %loop.latch, label %exit
152
153loop.latch:
154  call void @use(ptr %ptr.iv)
155  %ptr.iv.next = getelementptr inbounds i7, ptr %ptr.iv, i16 1
156  br label %loop.header
157
158exit:
159  ret void
160}
161
162define void @test_monotonic_ptr_iv_inc_2_different_element_types_with_same_alloc_type_sizes(ptr %start, i16 %len) {
163; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_with_same_alloc_type_sizes(
164; CHECK-NEXT:  entry:
165; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i31, ptr [[START:%.*]], i16 [[LEN:%.*]]
166; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
167; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
168; CHECK:       loop.ph:
169; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
170; CHECK:       loop.header:
171; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
172; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
173; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
174; CHECK:       for.body:
175; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
176; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
177; CHECK:       loop.latch:
178; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
179; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i30, ptr [[PTR_IV]], i16 1
180; CHECK-NEXT:    br label [[LOOP_HEADER]]
181; CHECK:       exit:
182; CHECK-NEXT:    ret void
183;
184entry:
185  %upper = getelementptr inbounds i31, ptr %start, i16 %len
186  %len.neg = icmp slt i16 %len, 0
187  br i1 %len.neg, label %exit, label %loop.ph
188
189loop.ph:
190  br label %loop.header
191
192loop.header:
193  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
194  %c = icmp eq ptr %ptr.iv, %upper
195  br i1 %c, label %exit, label %for.body
196
197for.body:
198  %t.1 = icmp uge ptr %ptr.iv, %start
199  %t.2 = icmp ult ptr %ptr.iv, %upper
200  %and = and i1 %t.1, %t.2
201  br i1 %and, label %loop.latch, label %exit
202
203loop.latch:
204  call void @use(ptr %ptr.iv)
205  %ptr.iv.next = getelementptr inbounds i30, ptr %ptr.iv, i16 1
206  br label %loop.header
207
208exit:
209  ret void
210}
211
212define void @test_monotonic_ptr_iv_inc_1_element_types_with_different_alloc_type_sizes_with_early_exit(ptr %start, i16 %len) {
213; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_element_types_with_different_alloc_type_sizes_with_early_exit(
214; CHECK-NEXT:  entry:
215; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
216; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
217; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
218; CHECK:       loop.ph:
219; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
220; CHECK:       loop.header:
221; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
222; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
223; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
224; CHECK:       for.body:
225; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
226; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
227; CHECK:       loop.next:
228; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
229; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[T_2]]
230; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
231; CHECK:       loop.latch:
232; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
233; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
234; CHECK-NEXT:    br label [[LOOP_HEADER]]
235; CHECK:       exit:
236; CHECK-NEXT:    ret void
237;
238entry:
239  %upper = getelementptr inbounds float, ptr %start, i16 %len
240  %len.neg = icmp slt i16 %len, 0
241  br i1 %len.neg, label %exit, label %loop.ph
242
243loop.ph:
244  br label %loop.header
245
246loop.header:
247  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
248  %c = icmp eq ptr %ptr.iv, %upper
249  br i1 %c, label %exit, label %for.body
250
251for.body:
252  %c.1 = call i1 @cond()
253  br i1 %c.1, label %loop.next, label %exit
254
255loop.next:
256  %t.1 = icmp uge ptr %ptr.iv, %start
257  %t.2 = icmp ult ptr %ptr.iv, %upper
258  %and = and i1 %t.1, %t.2
259  br i1 %and, label %loop.latch, label %exit
260
261loop.latch:
262  call void @use(ptr %ptr.iv)
263  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
264  br label %loop.header
265
266exit:
267  ret void
268}
269
270define void @test_monotonic_ptr_iv_inc_2_element_types_with_different_alloc_type_sizes_with_early_exit(ptr %start, i16 %len) {
271; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_element_types_with_different_alloc_type_sizes_with_early_exit(
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
274; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
275; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
276; CHECK:       loop.ph:
277; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
278; CHECK:       loop.header:
279; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
280; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
281; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
282; CHECK:       for.body:
283; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
284; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
285; CHECK:       loop.next:
286; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
287; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
288; CHECK:       loop.latch:
289; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
290; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1
291; CHECK-NEXT:    br label [[LOOP_HEADER]]
292; CHECK:       exit:
293; CHECK-NEXT:    ret void
294;
295entry:
296  %upper = getelementptr inbounds i32, ptr %start, i16 %len
297  %len.neg = icmp slt i16 %len, 0
298  br i1 %len.neg, label %exit, label %loop.ph
299
300loop.ph:
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 float, 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_different_element_types_with_same_alloc_type_sizes_with_early_exit(ptr %start, i16 %len) {
328; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_with_same_alloc_type_sizes_with_early_exit(
329; CHECK-NEXT:  entry:
330; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i5, ptr [[START:%.*]], i16 [[LEN:%.*]]
331; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
332; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
333; CHECK:       loop.ph:
334; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
335; CHECK:       loop.header:
336; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
337; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
338; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
339; CHECK:       for.body:
340; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
341; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
342; CHECK:       loop.next:
343; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
344; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
345; CHECK:       loop.latch:
346; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
347; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i7, ptr [[PTR_IV]], i16 1
348; CHECK-NEXT:    br label [[LOOP_HEADER]]
349; CHECK:       exit:
350; CHECK-NEXT:    ret void
351;
352entry:
353  %upper = getelementptr inbounds i5, ptr %start, i16 %len
354  %len.neg = icmp slt i16 %len, 0
355  br i1 %len.neg, label %exit, label %loop.ph
356
357loop.ph:
358  br label %loop.header
359
360loop.header:
361  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
362  %c = icmp eq ptr %ptr.iv, %upper
363  br i1 %c, label %exit, label %for.body
364
365for.body:
366  %c.1 = call i1 @cond()
367  br i1 %c.1, label %loop.next, label %exit
368
369loop.next:
370  %t.1 = icmp uge ptr %ptr.iv, %start
371  %t.2 = icmp ult ptr %ptr.iv, %upper
372  %and = and i1 %t.1, %t.2
373  br i1 %and, label %loop.latch, label %exit
374
375loop.latch:
376  call void @use(ptr %ptr.iv)
377  %ptr.iv.next = getelementptr inbounds i7, ptr %ptr.iv, i16 1
378  br label %loop.header
379
380exit:
381  ret void
382}
383
384define void @test_monotonic_ptr_iv_inc_2_different_element_types_with_same_alloc_type_sizes_with_early_exit(ptr %start, i16 %len) {
385; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_with_same_alloc_type_sizes_with_early_exit(
386; CHECK-NEXT:  entry:
387; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i31, ptr [[START:%.*]], i16 [[LEN:%.*]]
388; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
389; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
390; CHECK:       loop.ph:
391; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
392; CHECK:       loop.header:
393; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
394; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
395; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
396; CHECK:       for.body:
397; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
398; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
399; CHECK:       loop.next:
400; CHECK-NEXT:    [[AND:%.*]] = and i1 true, true
401; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
402; CHECK:       loop.latch:
403; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
404; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i30, ptr [[PTR_IV]], i16 1
405; CHECK-NEXT:    br label [[LOOP_HEADER]]
406; CHECK:       exit:
407; CHECK-NEXT:    ret void
408;
409entry:
410  %upper = getelementptr inbounds i31, ptr %start, i16 %len
411  %len.neg = icmp slt i16 %len, 0
412  br i1 %len.neg, label %exit, label %loop.ph
413
414loop.ph:
415  br label %loop.header
416
417loop.header:
418  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
419  %c = icmp eq ptr %ptr.iv, %upper
420  br i1 %c, label %exit, label %for.body
421
422for.body:
423  %c.1 = call i1 @cond()
424  br i1 %c.1, label %loop.next, label %exit
425
426loop.next:
427  %t.1 = icmp uge ptr %ptr.iv, %start
428  %t.2 = icmp ult ptr %ptr.iv, %upper
429  %and = and i1 %t.1, %t.2
430  br i1 %and, label %loop.latch, label %exit
431
432loop.latch:
433  call void @use(ptr %ptr.iv)
434  %ptr.iv.next = getelementptr inbounds i30, ptr %ptr.iv, i16 1
435  br label %loop.header
436
437exit:
438  ret void
439}
440