xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/outer_phi.ll (revision 864bb84a427de367528d15270790dd152871daf2)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=indvars -S | FileCheck %s
3
4declare i1 @cond()
5declare i32 @llvm.smax.i32(i32, i32)
6
7; FIXME: In all tests in this file, signed_cond is equivalent to unsigned_cond, and therefore
8; one of the checks in the inner loop can be removed. The key to proving it is to prove that
9; %iv starts from something that is non-negative and only goes up. The positivity of its start
10; follows from the fact that %outer.iv also starts from somethign non-negative and only goes
11; up or remains same between iterations.
12define i32 @test_01(i32 %a, i32 %b) {
13; CHECK-LABEL: @test_01(
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0
16; CHECK-NEXT:    br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]]
17; CHECK:       outer.preheader:
18; CHECK-NEXT:    br label [[OUTER:%.*]]
19; CHECK:       outer:
20; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
21; CHECK-NEXT:    br label [[INNER:%.*]]
22; CHECK:       inner:
23; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
24; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
25; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
26; CHECK:       inner.1:
27; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
28; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
29; CHECK:       inner.backedge:
30; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
31; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
32; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
33; CHECK:       outer.backedge:
34; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
35; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
36; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
37; CHECK:       failure:
38; CHECK-NEXT:    unreachable
39; CHECK:       side.exit:
40; CHECK-NEXT:    ret i32 0
41; CHECK:       exit:
42; CHECK-NEXT:    ret i32 1
43;
44entry:
45  %b_is_non_negative = icmp sge i32 %b, 0
46  br i1 %b_is_non_negative, label %outer, label %failure
47
48outer:
49  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
50  br label %inner
51
52
53inner:
54  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
55  %signed_cond = icmp slt i32 %iv, %b
56  br i1 %signed_cond, label %inner.1, label %side.exit
57
58inner.1:
59  %unsigned_cond = icmp ult i32 %iv, %b
60  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
61
62inner.backedge:
63  %iv.next = add nuw nsw i32 %iv, 1
64  %inner.loop.cond = call i1 @cond()
65  br i1 %inner.loop.cond, label %inner, label %outer.backedge
66
67outer.backedge:
68  %outer.loop.cond = call i1 @cond()
69  br i1 %outer.loop.cond, label %outer, label %exit
70
71failure:
72  unreachable
73
74side.exit:
75  ret i32 0
76
77exit:
78  ret i32 1
79}
80
81; FIXME: iv <u b, b >=s 0 --> iv <s b. We should be able to remove the 2nd check.
82define i32 @test_01a(i32 %a, i32 %b) {
83; CHECK-LABEL: @test_01a(
84; CHECK-NEXT:  entry:
85; CHECK-NEXT:    [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0
86; CHECK-NEXT:    br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]]
87; CHECK:       outer.preheader:
88; CHECK-NEXT:    br label [[OUTER:%.*]]
89; CHECK:       outer:
90; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
91; CHECK-NEXT:    br label [[INNER:%.*]]
92; CHECK:       inner:
93; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
94; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
95; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
96; CHECK:       inner.1:
97; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
98; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
99; CHECK:       inner.backedge:
100; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
101; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
102; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
103; CHECK:       outer.backedge:
104; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
105; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
106; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
107; CHECK:       failure:
108; CHECK-NEXT:    unreachable
109; CHECK:       side.exit:
110; CHECK-NEXT:    ret i32 0
111; CHECK:       exit:
112; CHECK-NEXT:    ret i32 1
113;
114entry:
115  %b_is_non_negative = icmp sge i32 %b, 0
116  br i1 %b_is_non_negative, label %outer, label %failure
117
118outer:
119  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
120  br label %inner
121
122
123inner:
124  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
125  %signed_cond = icmp ult i32 %iv, %b
126  br i1 %signed_cond, label %inner.1, label %side.exit
127
128inner.1:
129  %unsigned_cond = icmp slt i32 %iv, %b
130  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
131
132inner.backedge:
133  %iv.next = add nuw nsw i32 %iv, 1
134  %inner.loop.cond = call i1 @cond()
135  br i1 %inner.loop.cond, label %inner, label %outer.backedge
136
137outer.backedge:
138  %outer.loop.cond = call i1 @cond()
139  br i1 %outer.loop.cond, label %outer, label %exit
140
141failure:
142  unreachable
143
144side.exit:
145  ret i32 0
146
147exit:
148  ret i32 1
149}
150
151define i32 @test_02(i32 %a, i32 %b) {
152; CHECK-LABEL: @test_02(
153; CHECK-NEXT:  entry:
154; CHECK-NEXT:    [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0
155; CHECK-NEXT:    br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]]
156; CHECK:       outer.preheader:
157; CHECK-NEXT:    br label [[OUTER:%.*]]
158; CHECK:       outer:
159; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
160; CHECK-NEXT:    br label [[INNER:%.*]]
161; CHECK:       inner:
162; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
163; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
164; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
165; CHECK:       inner.1:
166; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
167; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
168; CHECK:       inner.backedge:
169; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
170; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
171; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
172; CHECK:       outer.backedge:
173; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
174; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
175; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
176; CHECK:       failure:
177; CHECK-NEXT:    unreachable
178; CHECK:       side.exit:
179; CHECK-NEXT:    ret i32 0
180; CHECK:       exit:
181; CHECK-NEXT:    ret i32 1
182;
183entry:
184  %b_is_non_negative = icmp sge i32 %b, 0
185  br i1 %b_is_non_negative, label %outer, label %failure
186
187outer:
188  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
189  br label %inner
190
191
192inner:
193  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
194  %signed_cond = icmp slt i32 %iv, %b
195  br i1 %signed_cond, label %inner.1, label %side.exit
196
197inner.1:
198  %unsigned_cond = icmp ult i32 %iv, %b
199  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
200
201inner.backedge:
202  %iv.next = add nuw nsw i32 %iv, 1
203  %inner.loop.cond = call i1 @cond()
204  br i1 %inner.loop.cond, label %inner, label %outer.backedge
205
206outer.backedge:
207  %outer.merge = phi i32 [%iv.next, %inner.backedge]
208  %outer.loop.cond = call i1 @cond()
209  br i1 %outer.loop.cond, label %outer, label %exit
210
211failure:
212  unreachable
213
214side.exit:
215  ret i32 0
216
217exit:
218  ret i32 1
219}
220
221define i32 @test_03(i32 %a, i32 %b) {
222; CHECK-LABEL: @test_03(
223; CHECK-NEXT:  entry:
224; CHECK-NEXT:    [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0
225; CHECK-NEXT:    br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]]
226; CHECK:       outer.preheader:
227; CHECK-NEXT:    br label [[OUTER:%.*]]
228; CHECK:       outer:
229; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
230; CHECK-NEXT:    [[OUTER_COND_1:%.*]] = call i1 @cond()
231; CHECK-NEXT:    br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]]
232; CHECK:       inner.preheader:
233; CHECK-NEXT:    br label [[INNER:%.*]]
234; CHECK:       no_inner:
235; CHECK-NEXT:    [[OUTER_COND_2:%.*]] = call i1 @cond()
236; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
237; CHECK:       inner:
238; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ]
239; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
240; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
241; CHECK:       inner.1:
242; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
243; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
244; CHECK:       inner.backedge:
245; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
246; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
247; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]]
248; CHECK:       outer.backedge.loopexit:
249; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
250; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
251; CHECK:       outer.backedge:
252; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[OUTER_IV]], [[NO_INNER]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ]
253; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
254; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
255; CHECK:       failure:
256; CHECK-NEXT:    unreachable
257; CHECK:       side.exit:
258; CHECK-NEXT:    ret i32 0
259; CHECK:       exit:
260; CHECK-NEXT:    ret i32 1
261;
262entry:
263  %b_is_non_negative = icmp sge i32 %b, 0
264  br i1 %b_is_non_negative, label %outer, label %failure
265
266outer:
267  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
268  %outer_cond_1 = call i1 @cond()
269  br i1 %outer_cond_1, label %inner, label %no_inner
270
271no_inner:
272  %outer_cond_2 = call i1 @cond()
273  br label %outer.backedge
274
275inner:
276  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
277  %signed_cond = icmp slt i32 %iv, %b
278  br i1 %signed_cond, label %inner.1, label %side.exit
279
280inner.1:
281  %unsigned_cond = icmp ult i32 %iv, %b
282  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
283
284inner.backedge:
285  %iv.next = add nuw nsw i32 %iv, 1
286  %inner.loop.cond = call i1 @cond()
287  br i1 %inner.loop.cond, label %inner, label %outer.backedge
288
289outer.backedge:
290  %outer.merge = phi i32 [%outer.iv, %no_inner], [%iv.next, %inner.backedge]
291  %outer.loop.cond = call i1 @cond()
292  br i1 %outer.loop.cond, label %outer, label %exit
293
294failure:
295  unreachable
296
297side.exit:
298  ret i32 0
299
300exit:
301  ret i32 1
302}
303
304define i32 @test_04(i32 %a, i32 %b) {
305; CHECK-LABEL: @test_04(
306; CHECK-NEXT:  entry:
307; CHECK-NEXT:    [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0
308; CHECK-NEXT:    br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]]
309; CHECK:       outer.preheader:
310; CHECK-NEXT:    br label [[OUTER:%.*]]
311; CHECK:       outer:
312; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ]
313; CHECK-NEXT:    [[OUTER_COND_1:%.*]] = call i1 @cond()
314; CHECK-NEXT:    br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]]
315; CHECK:       inner.preheader:
316; CHECK-NEXT:    br label [[INNER:%.*]]
317; CHECK:       no_inner:
318; CHECK-NEXT:    [[OUTER_COND_2:%.*]] = call i1 @cond()
319; CHECK-NEXT:    br i1 [[OUTER_COND_2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
320; CHECK:       if.true:
321; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 [[OUTER_IV]])
322; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
323; CHECK:       if.false:
324; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
325; CHECK:       inner:
326; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ]
327; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
328; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
329; CHECK:       inner.1:
330; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
331; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
332; CHECK:       inner.backedge:
333; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
334; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
335; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]]
336; CHECK:       outer.backedge.loopexit:
337; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
338; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
339; CHECK:       outer.backedge:
340; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[SMAX]], [[IF_TRUE]] ], [ [[OUTER_IV]], [[IF_FALSE]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ]
341; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
342; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
343; CHECK:       failure:
344; CHECK-NEXT:    unreachable
345; CHECK:       side.exit:
346; CHECK-NEXT:    ret i32 0
347; CHECK:       exit:
348; CHECK-NEXT:    ret i32 1
349;
350entry:
351  %b_is_non_negative = icmp sge i32 %b, 0
352  br i1 %b_is_non_negative, label %outer, label %failure
353
354outer:
355  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
356  %outer_cond_1 = call i1 @cond()
357  br i1 %outer_cond_1, label %inner, label %no_inner
358
359no_inner:
360  %outer_cond_2 = call i1 @cond()
361  br i1 %outer_cond_2, label %if.true, label %if.false
362
363if.true:
364  %smax = call i32 @llvm.smax.i32(i32 %a, i32 %outer.iv)
365  br label %outer.backedge
366
367if.false:
368  br label %outer.backedge
369
370inner:
371  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
372  %signed_cond = icmp slt i32 %iv, %b
373  br i1 %signed_cond, label %inner.1, label %side.exit
374
375inner.1:
376  %unsigned_cond = icmp ult i32 %iv, %b
377  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
378
379inner.backedge:
380  %iv.next = add nuw nsw i32 %iv, 1
381  %inner.loop.cond = call i1 @cond()
382  br i1 %inner.loop.cond, label %inner, label %outer.backedge
383
384outer.backedge:
385  %outer.merge = phi i32 [%smax, %if.true], [%outer.iv, %if.false], [%iv.next, %inner.backedge]
386  %outer.loop.cond = call i1 @cond()
387  br i1 %outer.loop.cond, label %outer, label %exit
388
389failure:
390  unreachable
391
392side.exit:
393  ret i32 0
394
395exit:
396  ret i32 1
397}
398
399; Same as test_01, but non-negativity of %b is known without context.
400; FIXME: We can remove 2nd check in loop.
401define i32 @test_05(i32 %a, ptr %bp) {
402; CHECK-LABEL: @test_05(
403; CHECK-NEXT:  entry:
404; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0:![0-9]+]]
405; CHECK-NEXT:    br label [[OUTER:%.*]]
406; CHECK:       outer:
407; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
408; CHECK-NEXT:    br label [[INNER:%.*]]
409; CHECK:       inner:
410; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
411; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
412; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
413; CHECK:       inner.1:
414; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[OUTER_IV]], [[B]]
415; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
416; CHECK:       inner.backedge:
417; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
418; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
419; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
420; CHECK:       outer.backedge:
421; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
422; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
423; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
424; CHECK:       side.exit:
425; CHECK-NEXT:    ret i32 0
426; CHECK:       exit:
427; CHECK-NEXT:    ret i32 1
428;
429entry:
430  %b = load i32, ptr %bp, !range !0
431  br label %outer
432
433outer:
434  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
435  br label %inner
436
437
438inner:
439  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
440  %signed_cond = icmp slt i32 %iv, %b
441  br i1 %signed_cond, label %inner.1, label %side.exit
442
443inner.1:
444  %unsigned_cond = icmp ult i32 %iv, %b
445  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
446
447inner.backedge:
448  %iv.next = add nuw nsw i32 %iv, 1
449  %inner.loop.cond = call i1 @cond()
450  br i1 %inner.loop.cond, label %inner, label %outer.backedge
451
452outer.backedge:
453  %outer.loop.cond = call i1 @cond()
454  br i1 %outer.loop.cond, label %outer, label %exit
455
456side.exit:
457  ret i32 0
458
459exit:
460  ret i32 1
461}
462
463
464; Same as test_01a, but non-negativity of %b is known without context.
465define i32 @test_05a(i32 %a, ptr %bp) {
466; CHECK-LABEL: @test_05a(
467; CHECK-NEXT:  entry:
468; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
469; CHECK-NEXT:    br label [[OUTER:%.*]]
470; CHECK:       outer:
471; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
472; CHECK-NEXT:    br label [[INNER:%.*]]
473; CHECK:       inner:
474; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
475; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
476; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
477; CHECK:       inner.1:
478; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
479; CHECK:       inner.backedge:
480; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
481; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
482; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
483; CHECK:       outer.backedge:
484; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
485; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
486; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
487; CHECK:       side.exit:
488; CHECK-NEXT:    ret i32 0
489; CHECK:       exit:
490; CHECK-NEXT:    ret i32 1
491;
492entry:
493  %b = load i32, ptr %bp, !range !0
494  br label %outer
495
496outer:
497  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
498  br label %inner
499
500
501inner:
502  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
503  %unsigned_cond = icmp ult i32 %iv, %b
504  br i1 %unsigned_cond, label %inner.1, label %side.exit
505
506inner.1:
507  %signed_cond = icmp slt i32 %iv, %b
508  br i1 %signed_cond, label %inner.backedge, label %side.exit
509
510inner.backedge:
511  %iv.next = add nuw nsw i32 %iv, 1
512  %inner.loop.cond = call i1 @cond()
513  br i1 %inner.loop.cond, label %inner, label %outer.backedge
514
515outer.backedge:
516  %outer.loop.cond = call i1 @cond()
517  br i1 %outer.loop.cond, label %outer, label %exit
518
519side.exit:
520  ret i32 0
521
522exit:
523  ret i32 1
524}
525
526; Similar to test_05a, but inverted 2nd condition.
527define i32 @test_05b(i32 %a, ptr %bp) {
528; CHECK-LABEL: @test_05b(
529; CHECK-NEXT:  entry:
530; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
531; CHECK-NEXT:    br label [[OUTER:%.*]]
532; CHECK:       outer:
533; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
534; CHECK-NEXT:    br label [[INNER:%.*]]
535; CHECK:       inner:
536; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
537; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
538; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
539; CHECK:       inner.1:
540; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
541; CHECK:       inner.backedge:
542; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
543; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
544; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
545; CHECK:       outer.backedge:
546; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
547; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
548; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
549; CHECK:       side.exit:
550; CHECK-NEXT:    ret i32 0
551; CHECK:       exit:
552; CHECK-NEXT:    ret i32 1
553;
554entry:
555  %b = load i32, ptr %bp, !range !0
556  br label %outer
557
558outer:
559  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
560  br label %inner
561
562
563inner:
564  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
565  %unsigned_cond = icmp ult i32 %iv, %b
566  br i1 %unsigned_cond, label %inner.1, label %side.exit
567
568inner.1:
569  %signed_cond = icmp sgt i32 %b, %iv
570  br i1 %signed_cond, label %inner.backedge, label %side.exit
571
572inner.backedge:
573  %iv.next = add nuw nsw i32 %iv, 1
574  %inner.loop.cond = call i1 @cond()
575  br i1 %inner.loop.cond, label %inner, label %outer.backedge
576
577outer.backedge:
578  %outer.loop.cond = call i1 @cond()
579  br i1 %outer.loop.cond, label %outer, label %exit
580
581side.exit:
582  ret i32 0
583
584exit:
585  ret i32 1
586}
587
588; We should prove implication: iv <s b, b <s 0 => iv <u b.
589define i32 @test_05c(i32 %a, ptr %bp) {
590; CHECK-LABEL: @test_05c(
591; CHECK-NEXT:  entry:
592; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG1:![0-9]+]]
593; CHECK-NEXT:    br label [[OUTER:%.*]]
594; CHECK:       outer:
595; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
596; CHECK-NEXT:    br label [[INNER:%.*]]
597; CHECK:       inner:
598; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
599; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
600; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
601; CHECK:       inner.1:
602; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
603; CHECK:       inner.backedge:
604; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
605; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
606; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
607; CHECK:       outer.backedge:
608; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
609; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
610; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
611; CHECK:       side.exit:
612; CHECK-NEXT:    ret i32 0
613; CHECK:       exit:
614; CHECK-NEXT:    ret i32 1
615;
616entry:
617  %b = load i32, ptr %bp, !range !1
618  br label %outer
619
620outer:
621  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
622  br label %inner
623
624
625inner:
626  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
627  %signed_cond = icmp slt i32 %iv, %b
628  br i1 %signed_cond, label %inner.1, label %side.exit
629
630inner.1:
631  %unsigned_cond = icmp ult i32 %iv, %b
632  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
633
634inner.backedge:
635  %iv.next = add nuw nsw i32 %iv, 1
636  %inner.loop.cond = call i1 @cond()
637  br i1 %inner.loop.cond, label %inner, label %outer.backedge
638
639outer.backedge:
640  %outer.loop.cond = call i1 @cond()
641  br i1 %outer.loop.cond, label %outer, label %exit
642
643side.exit:
644  ret i32 0
645
646exit:
647  ret i32 1
648}
649
650; Same as test_05c, but 2nd condition reversed.
651define i32 @test_05d(i32 %a, ptr %bp) {
652; CHECK-LABEL: @test_05d(
653; CHECK-NEXT:  entry:
654; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG1]]
655; CHECK-NEXT:    br label [[OUTER:%.*]]
656; CHECK:       outer:
657; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
658; CHECK-NEXT:    br label [[INNER:%.*]]
659; CHECK:       inner:
660; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
661; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
662; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
663; CHECK:       inner.1:
664; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
665; CHECK:       inner.backedge:
666; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
667; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
668; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
669; CHECK:       outer.backedge:
670; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
671; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
672; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
673; CHECK:       side.exit:
674; CHECK-NEXT:    ret i32 0
675; CHECK:       exit:
676; CHECK-NEXT:    ret i32 1
677;
678entry:
679  %b = load i32, ptr %bp, !range !1
680  br label %outer
681
682outer:
683  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
684  br label %inner
685
686
687inner:
688  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
689  %signed_cond = icmp slt i32 %iv, %b
690  br i1 %signed_cond, label %inner.1, label %side.exit
691
692inner.1:
693  %unsigned_cond = icmp ugt i32 %b, %iv
694  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
695
696inner.backedge:
697  %iv.next = add nuw nsw i32 %iv, 1
698  %inner.loop.cond = call i1 @cond()
699  br i1 %inner.loop.cond, label %inner, label %outer.backedge
700
701outer.backedge:
702  %outer.loop.cond = call i1 @cond()
703  br i1 %outer.loop.cond, label %outer, label %exit
704
705side.exit:
706  ret i32 0
707
708exit:
709  ret i32 1
710}
711
712
713; Same as test_05a, but 1st condition inverted.
714define i32 @test_05e(i32 %a, ptr %bp) {
715; CHECK-LABEL: @test_05e(
716; CHECK-NEXT:  entry:
717; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
718; CHECK-NEXT:    br label [[OUTER:%.*]]
719; CHECK:       outer:
720; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
721; CHECK-NEXT:    br label [[INNER:%.*]]
722; CHECK:       inner:
723; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
724; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
725; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
726; CHECK:       inner.1:
727; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
728; CHECK:       inner.backedge:
729; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
730; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
731; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
732; CHECK:       outer.backedge:
733; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
734; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
735; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
736; CHECK:       side.exit:
737; CHECK-NEXT:    ret i32 0
738; CHECK:       exit:
739; CHECK-NEXT:    ret i32 1
740;
741entry:
742  %b = load i32, ptr %bp, !range !0
743  br label %outer
744
745outer:
746  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
747  br label %inner
748
749
750inner:
751  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
752  %unsigned_cond = icmp ugt i32 %b, %iv
753  br i1 %unsigned_cond, label %inner.1, label %side.exit
754
755inner.1:
756  %signed_cond = icmp slt i32 %iv, %b
757  br i1 %signed_cond, label %inner.backedge, label %side.exit
758
759inner.backedge:
760  %iv.next = add nuw nsw i32 %iv, 1
761  %inner.loop.cond = call i1 @cond()
762  br i1 %inner.loop.cond, label %inner, label %outer.backedge
763
764outer.backedge:
765  %outer.loop.cond = call i1 @cond()
766  br i1 %outer.loop.cond, label %outer, label %exit
767
768side.exit:
769  ret i32 0
770
771exit:
772  ret i32 1
773}
774
775; Same as test_05b, but 1st condition inverted.
776define i32 @test_05f(i32 %a, ptr %bp) {
777; CHECK-LABEL: @test_05f(
778; CHECK-NEXT:  entry:
779; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
780; CHECK-NEXT:    br label [[OUTER:%.*]]
781; CHECK:       outer:
782; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
783; CHECK-NEXT:    br label [[INNER:%.*]]
784; CHECK:       inner:
785; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
786; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
787; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
788; CHECK:       inner.1:
789; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
790; CHECK:       inner.backedge:
791; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
792; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
793; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
794; CHECK:       outer.backedge:
795; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
796; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
797; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
798; CHECK:       side.exit:
799; CHECK-NEXT:    ret i32 0
800; CHECK:       exit:
801; CHECK-NEXT:    ret i32 1
802;
803entry:
804  %b = load i32, ptr %bp, !range !0
805  br label %outer
806
807outer:
808  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
809  br label %inner
810
811
812inner:
813  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
814  %unsigned_cond = icmp ugt i32 %b, %iv
815  br i1 %unsigned_cond, label %inner.1, label %side.exit
816
817inner.1:
818  %signed_cond = icmp sgt i32 %b, %iv
819  br i1 %signed_cond, label %inner.backedge, label %side.exit
820
821inner.backedge:
822  %iv.next = add nuw nsw i32 %iv, 1
823  %inner.loop.cond = call i1 @cond()
824  br i1 %inner.loop.cond, label %inner, label %outer.backedge
825
826outer.backedge:
827  %outer.loop.cond = call i1 @cond()
828  br i1 %outer.loop.cond, label %outer, label %exit
829
830side.exit:
831  ret i32 0
832
833exit:
834  ret i32 1
835}
836
837; Same as test_05c, but 1st condition inverted.
838define i32 @test_05g(i32 %a, ptr %bp) {
839; CHECK-LABEL: @test_05g(
840; CHECK-NEXT:  entry:
841; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG1]]
842; CHECK-NEXT:    br label [[OUTER:%.*]]
843; CHECK:       outer:
844; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
845; CHECK-NEXT:    br label [[INNER:%.*]]
846; CHECK:       inner:
847; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
848; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
849; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
850; CHECK:       inner.1:
851; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
852; CHECK:       inner.backedge:
853; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
854; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
855; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
856; CHECK:       outer.backedge:
857; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
858; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
859; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
860; CHECK:       side.exit:
861; CHECK-NEXT:    ret i32 0
862; CHECK:       exit:
863; CHECK-NEXT:    ret i32 1
864;
865entry:
866  %b = load i32, ptr %bp, !range !1
867  br label %outer
868
869outer:
870  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
871  br label %inner
872
873
874inner:
875  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
876  %signed_cond = icmp sgt i32 %b, %iv
877  br i1 %signed_cond, label %inner.1, label %side.exit
878
879inner.1:
880  %unsigned_cond = icmp ult i32 %iv, %b
881  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
882
883inner.backedge:
884  %iv.next = add nuw nsw i32 %iv, 1
885  %inner.loop.cond = call i1 @cond()
886  br i1 %inner.loop.cond, label %inner, label %outer.backedge
887
888outer.backedge:
889  %outer.loop.cond = call i1 @cond()
890  br i1 %outer.loop.cond, label %outer, label %exit
891
892side.exit:
893  ret i32 0
894
895exit:
896  ret i32 1
897}
898
899; Same as test_05d, but 1st condition inverted.
900define i32 @test_05h(i32 %a, ptr %bp) {
901; CHECK-LABEL: @test_05h(
902; CHECK-NEXT:  entry:
903; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG1]]
904; CHECK-NEXT:    br label [[OUTER:%.*]]
905; CHECK:       outer:
906; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ]
907; CHECK-NEXT:    br label [[INNER:%.*]]
908; CHECK:       inner:
909; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
910; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
911; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
912; CHECK:       inner.1:
913; CHECK-NEXT:    br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
914; CHECK:       inner.backedge:
915; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
916; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
917; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
918; CHECK:       outer.backedge:
919; CHECK-NEXT:    [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
920; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
921; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
922; CHECK:       side.exit:
923; CHECK-NEXT:    ret i32 0
924; CHECK:       exit:
925; CHECK-NEXT:    ret i32 1
926;
927entry:
928  %b = load i32, ptr %bp, !range !1
929  br label %outer
930
931outer:
932  %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge]
933  br label %inner
934
935
936inner:
937  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
938  %signed_cond = icmp sgt i32 %b, %iv
939  br i1 %signed_cond, label %inner.1, label %side.exit
940
941inner.1:
942  %unsigned_cond = icmp ugt i32 %b, %iv
943  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
944
945inner.backedge:
946  %iv.next = add nuw nsw i32 %iv, 1
947  %inner.loop.cond = call i1 @cond()
948  br i1 %inner.loop.cond, label %inner, label %outer.backedge
949
950outer.backedge:
951  %outer.loop.cond = call i1 @cond()
952  br i1 %outer.loop.cond, label %outer, label %exit
953
954side.exit:
955  ret i32 0
956
957exit:
958  ret i32 1
959}
960
961; Same as test_02, but non-negativity of %b is known without context.
962; FIXME: We can remove 2nd check in loop.
963define i32 @test_06(i32 %a, ptr %bp) {
964; CHECK-LABEL: @test_06(
965; CHECK-NEXT:  entry:
966; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
967; CHECK-NEXT:    br label [[OUTER:%.*]]
968; CHECK:       outer:
969; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ]
970; CHECK-NEXT:    br label [[INNER:%.*]]
971; CHECK:       inner:
972; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ]
973; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
974; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
975; CHECK:       inner.1:
976; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[OUTER_IV]], [[B]]
977; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
978; CHECK:       inner.backedge:
979; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
980; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
981; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]]
982; CHECK:       outer.backedge:
983; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
984; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
985; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
986; CHECK:       side.exit:
987; CHECK-NEXT:    ret i32 0
988; CHECK:       exit:
989; CHECK-NEXT:    ret i32 1
990;
991entry:
992  %b = load i32, ptr %bp, !range !0
993  br label %outer
994
995outer:
996  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
997  br label %inner
998
999
1000inner:
1001  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
1002  %signed_cond = icmp slt i32 %iv, %b
1003  br i1 %signed_cond, label %inner.1, label %side.exit
1004
1005inner.1:
1006  %unsigned_cond = icmp ult i32 %iv, %b
1007  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
1008
1009inner.backedge:
1010  %iv.next = add nuw nsw i32 %iv, 1
1011  %inner.loop.cond = call i1 @cond()
1012  br i1 %inner.loop.cond, label %inner, label %outer.backedge
1013
1014outer.backedge:
1015  %outer.merge = phi i32 [%iv.next, %inner.backedge]
1016  %outer.loop.cond = call i1 @cond()
1017  br i1 %outer.loop.cond, label %outer, label %exit
1018
1019side.exit:
1020  ret i32 0
1021
1022exit:
1023  ret i32 1
1024}
1025
1026; Same as test_03, but non-negativity of %b is known without context.
1027; FIXME: We can remove 2nd check in loop.
1028define i32 @test_07(i32 %a, ptr %bp) {
1029; CHECK-LABEL: @test_07(
1030; CHECK-NEXT:  entry:
1031; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
1032; CHECK-NEXT:    br label [[OUTER:%.*]]
1033; CHECK:       outer:
1034; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ]
1035; CHECK-NEXT:    [[OUTER_COND_1:%.*]] = call i1 @cond()
1036; CHECK-NEXT:    br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]]
1037; CHECK:       inner.preheader:
1038; CHECK-NEXT:    br label [[INNER:%.*]]
1039; CHECK:       no_inner:
1040; CHECK-NEXT:    [[OUTER_COND_2:%.*]] = call i1 @cond()
1041; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
1042; CHECK:       inner:
1043; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ]
1044; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
1045; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
1046; CHECK:       inner.1:
1047; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[OUTER_IV]], [[B]]
1048; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
1049; CHECK:       inner.backedge:
1050; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
1051; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
1052; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]]
1053; CHECK:       outer.backedge.loopexit:
1054; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
1055; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
1056; CHECK:       outer.backedge:
1057; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[OUTER_IV]], [[NO_INNER]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ]
1058; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
1059; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
1060; CHECK:       side.exit:
1061; CHECK-NEXT:    ret i32 0
1062; CHECK:       exit:
1063; CHECK-NEXT:    ret i32 1
1064;
1065entry:
1066  %b = load i32, ptr %bp, !range !0
1067  br label %outer
1068
1069outer:
1070  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
1071  %outer_cond_1 = call i1 @cond()
1072  br i1 %outer_cond_1, label %inner, label %no_inner
1073
1074no_inner:
1075  %outer_cond_2 = call i1 @cond()
1076  br label %outer.backedge
1077
1078inner:
1079  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
1080  %signed_cond = icmp slt i32 %iv, %b
1081  br i1 %signed_cond, label %inner.1, label %side.exit
1082
1083inner.1:
1084  %unsigned_cond = icmp ult i32 %iv, %b
1085  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
1086
1087inner.backedge:
1088  %iv.next = add nuw nsw i32 %iv, 1
1089  %inner.loop.cond = call i1 @cond()
1090  br i1 %inner.loop.cond, label %inner, label %outer.backedge
1091
1092outer.backedge:
1093  %outer.merge = phi i32 [%outer.iv, %no_inner], [%iv.next, %inner.backedge]
1094  %outer.loop.cond = call i1 @cond()
1095  br i1 %outer.loop.cond, label %outer, label %exit
1096
1097side.exit:
1098  ret i32 0
1099
1100exit:
1101  ret i32 1
1102}
1103
1104; Same as test_04, but non-negativity of %b is known without context.
1105; FIXME: We can remove 2nd check in loop.
1106define i32 @test_08(i32 %a, ptr %bp) {
1107; CHECK-LABEL: @test_08(
1108; CHECK-NEXT:  entry:
1109; CHECK-NEXT:    [[B:%.*]] = load i32, ptr [[BP:%.*]], align 4, !range [[RNG0]]
1110; CHECK-NEXT:    br label [[OUTER:%.*]]
1111; CHECK:       outer:
1112; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ]
1113; CHECK-NEXT:    [[OUTER_COND_1:%.*]] = call i1 @cond()
1114; CHECK-NEXT:    br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]]
1115; CHECK:       inner.preheader:
1116; CHECK-NEXT:    br label [[INNER:%.*]]
1117; CHECK:       no_inner:
1118; CHECK-NEXT:    [[OUTER_COND_2:%.*]] = call i1 @cond()
1119; CHECK-NEXT:    br i1 [[OUTER_COND_2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
1120; CHECK:       if.true:
1121; CHECK-NEXT:    [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 [[OUTER_IV]])
1122; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
1123; CHECK:       if.false:
1124; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
1125; CHECK:       inner:
1126; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ]
1127; CHECK-NEXT:    [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
1128; CHECK-NEXT:    br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
1129; CHECK:       inner.1:
1130; CHECK-NEXT:    [[UNSIGNED_COND:%.*]] = icmp ult i32 [[OUTER_IV]], [[B]]
1131; CHECK-NEXT:    br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
1132; CHECK:       inner.backedge:
1133; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
1134; CHECK-NEXT:    [[INNER_LOOP_COND:%.*]] = call i1 @cond()
1135; CHECK-NEXT:    br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]]
1136; CHECK:       outer.backedge.loopexit:
1137; CHECK-NEXT:    [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ]
1138; CHECK-NEXT:    br label [[OUTER_BACKEDGE]]
1139; CHECK:       outer.backedge:
1140; CHECK-NEXT:    [[OUTER_MERGE]] = phi i32 [ [[SMAX]], [[IF_TRUE]] ], [ [[OUTER_IV]], [[IF_FALSE]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ]
1141; CHECK-NEXT:    [[OUTER_LOOP_COND:%.*]] = call i1 @cond()
1142; CHECK-NEXT:    br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]]
1143; CHECK:       side.exit:
1144; CHECK-NEXT:    ret i32 0
1145; CHECK:       exit:
1146; CHECK-NEXT:    ret i32 1
1147;
1148entry:
1149  %b = load i32, ptr %bp, !range !0
1150  br label %outer
1151
1152outer:
1153  %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge]
1154  %outer_cond_1 = call i1 @cond()
1155  br i1 %outer_cond_1, label %inner, label %no_inner
1156
1157no_inner:
1158  %outer_cond_2 = call i1 @cond()
1159  br i1 %outer_cond_2, label %if.true, label %if.false
1160
1161if.true:
1162  %smax = call i32 @llvm.smax.i32(i32 %a, i32 %outer.iv)
1163  br label %outer.backedge
1164
1165if.false:
1166  br label %outer.backedge
1167
1168inner:
1169  %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge]
1170  %signed_cond = icmp slt i32 %iv, %b
1171  br i1 %signed_cond, label %inner.1, label %side.exit
1172
1173inner.1:
1174  %unsigned_cond = icmp ult i32 %iv, %b
1175  br i1 %unsigned_cond, label %inner.backedge, label %side.exit
1176
1177inner.backedge:
1178  %iv.next = add nuw nsw i32 %iv, 1
1179  %inner.loop.cond = call i1 @cond()
1180  br i1 %inner.loop.cond, label %inner, label %outer.backedge
1181
1182outer.backedge:
1183  %outer.merge = phi i32 [%smax, %if.true], [%outer.iv, %if.false], [%iv.next, %inner.backedge]
1184  %outer.loop.cond = call i1 @cond()
1185  br i1 %outer.loop.cond, label %outer, label %exit
1186
1187side.exit:
1188  ret i32 0
1189
1190exit:
1191  ret i32 1
1192}
1193
1194!0 = !{i32 0, i32 2147483647}
1195!1 = !{i32 -2147483648, i32 0}
1196