1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=indvars -S | FileCheck %s
3
4declare void @fail(i32)
5declare i1 @cond()
6declare i32 @switch.cond()
7declare i32 @llvm.smax.i32(i32 %a, i32 %b)
8
9; Unsigned comparison here is redundant and can be safely deleted.
10define i32 @trivial.case(i32* %len.ptr) {
11; CHECK-LABEL: @trivial.case(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]]
14; CHECK-NEXT:    br label [[PREHEADER:%.*]]
15; CHECK:       preheader:
16; CHECK-NEXT:    br label [[LOOP:%.*]]
17; CHECK:       loop:
18; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
19; CHECK-NEXT:    [[SIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]]
20; CHECK-NEXT:    br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]]
21; CHECK:       signed.passed:
22; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAILED_SIGNED]]
23; CHECK:       backedge:
24; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
25; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond()
26; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]]
27; CHECK:       failed.signed:
28; CHECK-NEXT:    call void @fail(i32 1)
29; CHECK-NEXT:    unreachable
30; CHECK:       failed.unsigned:
31; CHECK-NEXT:    call void @fail(i32 2)
32; CHECK-NEXT:    unreachable
33; CHECK:       done:
34; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
35; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
36;
37entry:
38  %len = load i32, i32* %len.ptr, !range !0
39  br label %preheader
40
41preheader:
42  br label %loop
43
44loop:
45  %iv = phi i32 [0, %preheader], [%iv.next, %backedge]
46  %signed.cmp = icmp slt i32 %iv, %len
47  br i1 %signed.cmp, label %signed.passed, label %failed.signed
48
49signed.passed:
50  %unsigned.cmp = icmp ult i32 %iv, %len
51  br i1 %unsigned.cmp, label %backedge, label %failed.signed
52
53backedge:
54  %iv.next = add i32 %iv, 1
55  %cond = call i1 @cond()
56  br i1 %cond, label %loop, label %done
57
58failed.signed:
59  call void @fail(i32 1)
60  unreachable
61
62failed.unsigned:
63  call void @fail(i32 2)
64  unreachable
65
66done:
67  ret i32 %iv
68}
69
70; TODO: We should be able to prove that:
71; - %sibling.iv.next is non-negative;
72; - therefore, %iv is non-negative;
73; - therefore, unsigned check can be removed.
74define i32 @start.from.sibling.iv(i32* %len.ptr, i32* %sibling.len.ptr) {
75; CHECK-LABEL: @start.from.sibling.iv(
76; CHECK-NEXT:  entry:
77; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]]
78; CHECK-NEXT:    [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]]
79; CHECK-NEXT:    br label [[SIBLING_LOOP:%.*]]
80; CHECK:       sibling.loop:
81; CHECK-NEXT:    [[SIBLING_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ]
82; CHECK-NEXT:    [[SIBLING_RC:%.*]] = icmp ult i32 [[SIBLING_IV]], [[SIBLING_LEN]]
83; CHECK-NEXT:    br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]]
84; CHECK:       sibling.backedge:
85; CHECK-NEXT:    [[SIBLING_IV_NEXT]] = add nuw nsw i32 [[SIBLING_IV]], 1
86; CHECK-NEXT:    [[SIBLING_COND:%.*]] = call i1 @cond()
87; CHECK-NEXT:    br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[PREHEADER:%.*]]
88; CHECK:       preheader:
89; CHECK-NEXT:    [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i32 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ]
90; CHECK-NEXT:    br label [[LOOP:%.*]]
91; CHECK:       loop:
92; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_LCSSA]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
93; CHECK-NEXT:    [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]]
94; CHECK-NEXT:    br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]]
95; CHECK:       signed.passed:
96; CHECK-NEXT:    [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]]
97; CHECK-NEXT:    br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]]
98; CHECK:       backedge:
99; CHECK-NEXT:    [[IV_NEXT]] = add nuw i32 [[IV]], 1
100; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond()
101; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]]
102; CHECK:       failed.signed:
103; CHECK-NEXT:    call void @fail(i32 1)
104; CHECK-NEXT:    unreachable
105; CHECK:       failed.unsigned:
106; CHECK-NEXT:    call void @fail(i32 2)
107; CHECK-NEXT:    unreachable
108; CHECK:       failed.sibling:
109; CHECK-NEXT:    call void @fail(i32 3)
110; CHECK-NEXT:    unreachable
111; CHECK:       done:
112; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
113; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
114;
115entry:
116  %len = load i32, i32* %len.ptr, !range !0
117  %sibling.len = load i32, i32* %sibling.len.ptr, !range !0
118  br label %sibling.loop
119
120sibling.loop:
121  %sibling.iv = phi i32 [0, %entry], [%sibling.iv.next, %sibling.backedge]
122  %sibling.rc = icmp ult i32 %sibling.iv, %sibling.len
123  br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling
124
125sibling.backedge:
126  %sibling.iv.next = add nuw nsw i32 %sibling.iv, 1
127  %sibling.cond = call i1 @cond()
128  br i1 %sibling.cond, label %sibling.loop, label %preheader
129
130preheader:
131  br label %loop
132
133loop:
134  %iv = phi i32 [%sibling.iv.next, %preheader], [%iv.next, %backedge]
135  %signed.cmp = icmp slt i32 %iv, %len
136  br i1 %signed.cmp, label %signed.passed, label %failed.signed
137
138signed.passed:
139  %unsigned.cmp = icmp ult i32 %iv, %len
140  br i1 %unsigned.cmp, label %backedge, label %failed.signed
141
142backedge:
143  %iv.next = add i32 %iv, 1
144  %cond = call i1 @cond()
145  br i1 %cond, label %loop, label %done
146
147failed.signed:
148  call void @fail(i32 1)
149  unreachable
150
151failed.unsigned:
152  call void @fail(i32 2)
153  unreachable
154
155failed.sibling:
156  call void @fail(i32 3)
157  unreachable
158
159done:
160  ret i32 %iv
161}
162
163; Same as above, but the sibling loop is now wide. We can eliminate the unsigned comparison here.
164define i32 @start.from.sibling.iv.wide(i32* %len.ptr, i32* %sibling.len.ptr) {
165; CHECK-LABEL: @start.from.sibling.iv.wide(
166; CHECK-NEXT:  entry:
167; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]]
168; CHECK-NEXT:    [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]]
169; CHECK-NEXT:    [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64
170; CHECK-NEXT:    br label [[SIBLING_LOOP:%.*]]
171; CHECK:       sibling.loop:
172; CHECK-NEXT:    [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ]
173; CHECK-NEXT:    [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]]
174; CHECK-NEXT:    br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]]
175; CHECK:       sibling.backedge:
176; CHECK-NEXT:    [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1
177; CHECK-NEXT:    [[SIBLING_COND:%.*]] = call i1 @cond()
178; CHECK-NEXT:    br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[PREHEADER:%.*]]
179; CHECK:       preheader:
180; CHECK-NEXT:    [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ]
181; CHECK-NEXT:    [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32
182; CHECK-NEXT:    br label [[LOOP:%.*]]
183; CHECK:       loop:
184; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
185; CHECK-NEXT:    [[SIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]]
186; CHECK-NEXT:    br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]]
187; CHECK:       signed.passed:
188; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAILED_SIGNED]]
189; CHECK:       backedge:
190; CHECK-NEXT:    [[IV_NEXT]] = add nuw i32 [[IV]], 1
191; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond()
192; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]]
193; CHECK:       failed.signed:
194; CHECK-NEXT:    call void @fail(i32 1)
195; CHECK-NEXT:    unreachable
196; CHECK:       failed.unsigned:
197; CHECK-NEXT:    call void @fail(i32 2)
198; CHECK-NEXT:    unreachable
199; CHECK:       failed.sibling:
200; CHECK-NEXT:    call void @fail(i32 3)
201; CHECK-NEXT:    unreachable
202; CHECK:       done:
203; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
204; CHECK-NEXT:    ret i32 [[IV_LCSSA1]]
205;
206entry:
207  %len = load i32, i32* %len.ptr, !range !0
208  %sibling.len = load i32, i32* %sibling.len.ptr, !range !0
209  %sibling.len.wide = zext i32 %sibling.len to i64
210  br label %sibling.loop
211
212sibling.loop:
213  %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge]
214  %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide
215  br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling
216
217sibling.backedge:
218  %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1
219  %sibling.cond = call i1 @cond()
220  br i1 %sibling.cond, label %sibling.loop, label %preheader
221
222preheader:
223  %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32
224  br label %loop
225
226loop:
227  %iv = phi i32 [%sibling.iv.next.trunc, %preheader], [%iv.next, %backedge]
228  %signed.cmp = icmp slt i32 %iv, %len
229  br i1 %signed.cmp, label %signed.passed, label %failed.signed
230
231signed.passed:
232  %unsigned.cmp = icmp ult i32 %iv, %len
233  br i1 %unsigned.cmp, label %backedge, label %failed.signed
234
235backedge:
236  %iv.next = add i32 %iv, 1
237  %cond = call i1 @cond()
238  br i1 %cond, label %loop, label %done
239
240failed.signed:
241  call void @fail(i32 1)
242  unreachable
243
244failed.unsigned:
245  call void @fail(i32 2)
246  unreachable
247
248failed.sibling:
249  call void @fail(i32 3)
250  unreachable
251
252done:
253  ret i32 %iv
254}
255
256; Slightly more complex version of previous one (cycled phis).
257; TODO: remove unsigned comparison by proving non-negativity of iv.start.
258define i32 @start.from.sibling.iv.wide.cycled.phis(i32* %len.ptr, i32* %sibling.len.ptr) {
259; CHECK-LABEL: @start.from.sibling.iv.wide.cycled.phis(
260; CHECK-NEXT:  entry:
261; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]]
262; CHECK-NEXT:    [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]]
263; CHECK-NEXT:    [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64
264; CHECK-NEXT:    br label [[SIBLING_LOOP:%.*]]
265; CHECK:       sibling.loop:
266; CHECK-NEXT:    [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ]
267; CHECK-NEXT:    [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]]
268; CHECK-NEXT:    br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]]
269; CHECK:       sibling.backedge:
270; CHECK-NEXT:    [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1
271; CHECK-NEXT:    [[SIBLING_COND:%.*]] = call i1 @cond()
272; CHECK-NEXT:    br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[OUTER_LOOP_PREHEADER:%.*]]
273; CHECK:       outer.loop.preheader:
274; CHECK-NEXT:    [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ]
275; CHECK-NEXT:    [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32
276; CHECK-NEXT:    br label [[OUTER_LOOP:%.*]]
277; CHECK:       outer.loop:
278; CHECK-NEXT:    [[IV_START:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[OUTER_LOOP_PREHEADER]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_LOOP_BACKEDGE:%.*]] ]
279; CHECK-NEXT:    br label [[PREHEADER:%.*]]
280; CHECK:       preheader:
281; CHECK-NEXT:    br label [[LOOP:%.*]]
282; CHECK:       loop:
283; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_START]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
284; CHECK-NEXT:    [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]]
285; CHECK-NEXT:    br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]]
286; CHECK:       signed.passed:
287; CHECK-NEXT:    [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]]
288; CHECK-NEXT:    br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]]
289; CHECK:       backedge:
290; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
291; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond()
292; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[OUTER_LOOP_BACKEDGE]]
293; CHECK:       outer.loop.backedge:
294; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
295; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
296; CHECK-NEXT:    [[OUTER_COND:%.*]] = call i1 @cond()
297; CHECK-NEXT:    br i1 [[OUTER_COND]], label [[OUTER_LOOP]], label [[DONE:%.*]]
298; CHECK:       failed.signed:
299; CHECK-NEXT:    call void @fail(i32 1)
300; CHECK-NEXT:    unreachable
301; CHECK:       failed.unsigned:
302; CHECK-NEXT:    call void @fail(i32 2)
303; CHECK-NEXT:    unreachable
304; CHECK:       failed.sibling:
305; CHECK-NEXT:    call void @fail(i32 3)
306; CHECK-NEXT:    unreachable
307; CHECK:       done:
308; CHECK-NEXT:    [[IV_LCSSA1_LCSSA:%.*]] = phi i32 [ [[IV_LCSSA1]], [[OUTER_LOOP_BACKEDGE]] ]
309; CHECK-NEXT:    ret i32 [[IV_LCSSA1_LCSSA]]
310;
311entry:
312  %len = load i32, i32* %len.ptr, !range !0
313  %sibling.len = load i32, i32* %sibling.len.ptr, !range !0
314  %sibling.len.wide = zext i32 %sibling.len to i64
315  br label %sibling.loop
316
317sibling.loop:
318  %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge]
319  %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide
320  br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling
321
322sibling.backedge:
323  %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1
324  %sibling.cond = call i1 @cond()
325  br i1 %sibling.cond, label %sibling.loop, label %outer.loop.preheader
326
327outer.loop.preheader:
328  %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32
329  br label %outer.loop
330
331outer.loop:
332  %iv.start = phi i32 [%sibling.iv.next.trunc, %outer.loop.preheader], [%iv.next, %outer.loop.backedge]
333  br label %preheader
334
335preheader:
336  br label %loop
337
338loop:
339  %iv = phi i32 [%iv.start, %preheader], [%iv.next, %backedge]
340  %signed.cmp = icmp slt i32 %iv, %len
341  br i1 %signed.cmp, label %signed.passed, label %failed.signed
342
343signed.passed:
344  %unsigned.cmp = icmp ult i32 %iv, %len
345  br i1 %unsigned.cmp, label %backedge, label %failed.signed
346
347backedge:
348  %iv.next = add i32 %iv, 1
349  %cond = call i1 @cond()
350  br i1 %cond, label %loop, label %outer.loop.backedge
351
352
353outer.loop.backedge:
354  %outer.cond = call i1 @cond()
355  br i1 %outer.cond, label %outer.loop, label %done
356
357failed.signed:
358  call void @fail(i32 1)
359  unreachable
360
361failed.unsigned:
362  call void @fail(i32 2)
363  unreachable
364
365failed.sibling:
366  call void @fail(i32 3)
367  unreachable
368
369done:
370  ret i32 %iv
371}
372
373
374; Even more complex version of previous one (more sophisticated cycled phis).
375; TODO: remove unsigned comparison by proving non-negativity of iv.start.
376define i32 @start.from.sibling.iv.wide.cycled.phis.complex.phis(i32* %len.ptr, i32* %sibling.len.ptr, i32 %some.random.value) {
377; CHECK-LABEL: @start.from.sibling.iv.wide.cycled.phis.complex.phis(
378; CHECK-NEXT:  entry:
379; CHECK-NEXT:    [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]]
380; CHECK-NEXT:    [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]]
381; CHECK-NEXT:    [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64
382; CHECK-NEXT:    br label [[SIBLING_LOOP:%.*]]
383; CHECK:       sibling.loop:
384; CHECK-NEXT:    [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ]
385; CHECK-NEXT:    [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]]
386; CHECK-NEXT:    br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]]
387; CHECK:       sibling.backedge:
388; CHECK-NEXT:    [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1
389; CHECK-NEXT:    [[SIBLING_COND:%.*]] = call i1 @cond()
390; CHECK-NEXT:    br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[OUTER_LOOP_PREHEADER:%.*]]
391; CHECK:       outer.loop.preheader:
392; CHECK-NEXT:    [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ]
393; CHECK-NEXT:    [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32
394; CHECK-NEXT:    br label [[OUTER_LOOP:%.*]]
395; CHECK:       outer.loop:
396; CHECK-NEXT:    [[IV_START:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[OUTER_LOOP_PREHEADER]] ], [ [[IV_START_UPDATED:%.*]], [[OUTER_LOOP_BACKEDGE:%.*]] ]
397; CHECK-NEXT:    br label [[PREHEADER:%.*]]
398; CHECK:       preheader:
399; CHECK-NEXT:    br label [[LOOP:%.*]]
400; CHECK:       loop:
401; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_START]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
402; CHECK-NEXT:    [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]]
403; CHECK-NEXT:    br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]]
404; CHECK:       signed.passed:
405; CHECK-NEXT:    [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]]
406; CHECK-NEXT:    br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]]
407; CHECK:       backedge:
408; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
409; CHECK-NEXT:    [[COND:%.*]] = call i1 @cond()
410; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[OUTER_LOOP_SELECTION:%.*]]
411; CHECK:       outer.loop.selection:
412; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ]
413; CHECK-NEXT:    [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ]
414; CHECK-NEXT:    [[SWITCH_COND:%.*]] = call i32 @switch.cond()
415; CHECK-NEXT:    switch i32 [[SWITCH_COND]], label [[TAKE_SAME:%.*]] [
416; CHECK-NEXT:    i32 1, label [[TAKE_INCREMENT:%.*]]
417; CHECK-NEXT:    i32 2, label [[TAKE_SMAX:%.*]]
418; CHECK-NEXT:    ]
419; CHECK:       take.same:
420; CHECK-NEXT:    br label [[OUTER_LOOP_BACKEDGE]]
421; CHECK:       take.increment:
422; CHECK-NEXT:    br label [[OUTER_LOOP_BACKEDGE]]
423; CHECK:       take.smax:
424; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[IV_START]], i32 [[SOME_RANDOM_VALUE:%.*]])
425; CHECK-NEXT:    br label [[OUTER_LOOP_BACKEDGE]]
426; CHECK:       outer.loop.backedge:
427; CHECK-NEXT:    [[IV_START_UPDATED]] = phi i32 [ [[IV_START]], [[TAKE_SAME]] ], [ [[IV_NEXT_LCSSA]], [[TAKE_INCREMENT]] ], [ [[SMAX]], [[TAKE_SMAX]] ]
428; CHECK-NEXT:    [[OUTER_COND:%.*]] = call i1 @cond()
429; CHECK-NEXT:    br i1 [[OUTER_COND]], label [[OUTER_LOOP]], label [[DONE:%.*]]
430; CHECK:       failed.signed:
431; CHECK-NEXT:    call void @fail(i32 1)
432; CHECK-NEXT:    unreachable
433; CHECK:       failed.unsigned:
434; CHECK-NEXT:    call void @fail(i32 2)
435; CHECK-NEXT:    unreachable
436; CHECK:       failed.sibling:
437; CHECK-NEXT:    call void @fail(i32 3)
438; CHECK-NEXT:    unreachable
439; CHECK:       done:
440; CHECK-NEXT:    [[IV_LCSSA1_LCSSA:%.*]] = phi i32 [ [[IV_LCSSA1]], [[OUTER_LOOP_BACKEDGE]] ]
441; CHECK-NEXT:    ret i32 [[IV_LCSSA1_LCSSA]]
442;
443entry:
444  %len = load i32, i32* %len.ptr, !range !0
445  %sibling.len = load i32, i32* %sibling.len.ptr, !range !0
446  %sibling.len.wide = zext i32 %sibling.len to i64
447  br label %sibling.loop
448
449sibling.loop:
450  %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge]
451  %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide
452  br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling
453
454sibling.backedge:
455  %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1
456  %sibling.cond = call i1 @cond()
457  br i1 %sibling.cond, label %sibling.loop, label %outer.loop.preheader
458
459outer.loop.preheader:
460  %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32
461  br label %outer.loop
462
463outer.loop:
464  %iv.start = phi i32 [%sibling.iv.next.trunc, %outer.loop.preheader], [%iv.start.updated, %outer.loop.backedge]
465  br label %preheader
466
467preheader:
468  br label %loop
469
470loop:
471  %iv = phi i32 [%iv.start, %preheader], [%iv.next, %backedge]
472  %signed.cmp = icmp slt i32 %iv, %len
473  br i1 %signed.cmp, label %signed.passed, label %failed.signed
474
475signed.passed:
476  %unsigned.cmp = icmp ult i32 %iv, %len
477  br i1 %unsigned.cmp, label %backedge, label %failed.signed
478
479backedge:
480  %iv.next = add i32 %iv, 1
481  %cond = call i1 @cond()
482  br i1 %cond, label %loop, label %outer.loop.selection
483
484outer.loop.selection:
485  %switch.cond = call i32 @switch.cond()
486  switch i32 %switch.cond, label %take.same
487  [
488  i32 1, label %take.increment
489  i32 2, label %take.smax
490  ]
491
492take.same:
493  br label %outer.loop.backedge
494
495take.increment:
496  br label %outer.loop.backedge
497
498take.smax:
499  %smax = call i32 @llvm.smax.i32(i32 %iv.start, i32 %some.random.value)
500  br label %outer.loop.backedge
501
502outer.loop.backedge:
503  %iv.start.updated = phi i32 [%iv.start, %take.same],
504  [%iv.next, %take.increment],
505  [%smax, %take.smax]
506  %outer.cond = call i1 @cond()
507  br i1 %outer.cond, label %outer.loop, label %done
508
509failed.signed:
510  call void @fail(i32 1)
511  unreachable
512
513failed.unsigned:
514  call void @fail(i32 2)
515  unreachable
516
517failed.sibling:
518  call void @fail(i32 3)
519  unreachable
520
521done:
522  ret i32 %iv
523}
524
525!0 = !{ i32 0, i32 2147483646 }
526