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