• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -loop-unroll -verify-dom-info | FileCheck %s
3
4declare void @f1()
5declare void @f2()
6
7; Check that we can peel off iterations that make conditions true.
8define void @test1(i32 %k) {
9; CHECK-LABEL: @test1(
10; CHECK-NEXT:  for.body.lr.ph:
11; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
12; CHECK:       for.body.peel.begin:
13; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
14; CHECK:       for.body.peel:
15; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
16; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
17; CHECK:       if.else.peel:
18; CHECK-NEXT:    call void @f2()
19; CHECK-NEXT:    br label [[FOR_INC_PEEL:%.*]]
20; CHECK:       if.then.peel:
21; CHECK-NEXT:    call void @f1()
22; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
23; CHECK:       for.inc.peel:
24; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
25; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
26; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
27; CHECK:       for.body.peel.next:
28; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
29; CHECK:       for.body.peel2:
30; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
31; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
32; CHECK:       if.else.peel4:
33; CHECK-NEXT:    call void @f2()
34; CHECK-NEXT:    br label [[FOR_INC_PEEL6:%.*]]
35; CHECK:       if.then.peel5:
36; CHECK-NEXT:    call void @f1()
37; CHECK-NEXT:    br label [[FOR_INC_PEEL6]]
38; CHECK:       for.inc.peel6:
39; CHECK-NEXT:    [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
40; CHECK-NEXT:    [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
41; CHECK-NEXT:    br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
42; CHECK:       for.body.peel.next1:
43; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT9:%.*]]
44; CHECK:       for.body.peel.next9:
45; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
46; CHECK:       for.body.lr.ph.peel.newph:
47; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
48; CHECK:       for.body:
49; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL7]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
50; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
51; CHECK:       if.then:
52; CHECK-NEXT:    call void @f1()
53; CHECK-NEXT:    br label [[FOR_INC]]
54; CHECK:       if.else:
55; CHECK-NEXT:    call void @f2()
56; CHECK-NEXT:    br label [[FOR_INC]]
57; CHECK:       for.inc:
58; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
59; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
60; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !0
61; CHECK:       for.end.loopexit:
62; CHECK-NEXT:    br label [[FOR_END]]
63; CHECK:       for.end:
64; CHECK-NEXT:    ret void
65;
66for.body.lr.ph:
67  br label %for.body
68
69for.body:
70  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
71  %cmp1 = icmp ult i32 %i.05, 2
72  br i1 %cmp1, label %if.then, label %if.else
73
74if.then:
75  call void @f1()
76  br label %for.inc
77
78if.else:
79  call void @f2()
80  br label %for.inc
81
82for.inc:
83  %inc = add nsw i32 %i.05, 1
84  %cmp = icmp slt i32 %inc, %k
85  br i1 %cmp, label %for.body, label %for.end
86
87for.end:
88  ret void
89}
90
91; Check we peel off the maximum number of iterations that make conditions true.
92define void @test2(i32 %k) {
93; CHECK-LABEL: @test2(
94; CHECK-NEXT:  for.body.lr.ph:
95; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
96; CHECK:       for.body.peel.begin:
97; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
98; CHECK:       for.body.peel:
99; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
100; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
101; CHECK:       if.else.peel:
102; CHECK-NEXT:    call void @f2()
103; CHECK-NEXT:    br label [[IF2_PEEL:%.*]]
104; CHECK:       if.then.peel:
105; CHECK-NEXT:    call void @f1()
106; CHECK-NEXT:    br label [[IF2_PEEL]]
107; CHECK:       if2.peel:
108; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 4
109; CHECK-NEXT:    br i1 [[CMP2_PEEL]], label [[IF_THEN2_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
110; CHECK:       if.then2.peel:
111; CHECK-NEXT:    call void @f1()
112; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
113; CHECK:       for.inc.peel:
114; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
115; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
116; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
117; CHECK:       for.body.peel.next:
118; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
119; CHECK:       for.body.peel2:
120; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
121; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
122; CHECK:       if.else.peel4:
123; CHECK-NEXT:    call void @f2()
124; CHECK-NEXT:    br label [[IF2_PEEL6:%.*]]
125; CHECK:       if.then.peel5:
126; CHECK-NEXT:    call void @f1()
127; CHECK-NEXT:    br label [[IF2_PEEL6]]
128; CHECK:       if2.peel6:
129; CHECK-NEXT:    [[CMP2_PEEL7:%.*]] = icmp ult i32 [[INC_PEEL]], 4
130; CHECK-NEXT:    br i1 [[CMP2_PEEL7]], label [[IF_THEN2_PEEL8:%.*]], label [[FOR_INC_PEEL9:%.*]]
131; CHECK:       if.then2.peel8:
132; CHECK-NEXT:    call void @f1()
133; CHECK-NEXT:    br label [[FOR_INC_PEEL9]]
134; CHECK:       for.inc.peel9:
135; CHECK-NEXT:    [[INC_PEEL10:%.*]] = add nsw i32 [[INC_PEEL]], 1
136; CHECK-NEXT:    [[CMP_PEEL11:%.*]] = icmp slt i32 [[INC_PEEL10]], [[K]]
137; CHECK-NEXT:    br i1 [[CMP_PEEL11]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
138; CHECK:       for.body.peel.next1:
139; CHECK-NEXT:    br label [[FOR_BODY_PEEL13:%.*]]
140; CHECK:       for.body.peel13:
141; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp ult i32 [[INC_PEEL10]], 2
142; CHECK-NEXT:    br i1 [[CMP1_PEEL14]], label [[IF_THEN_PEEL16:%.*]], label [[IF_ELSE_PEEL15:%.*]]
143; CHECK:       if.else.peel15:
144; CHECK-NEXT:    call void @f2()
145; CHECK-NEXT:    br label [[IF2_PEEL17:%.*]]
146; CHECK:       if.then.peel16:
147; CHECK-NEXT:    call void @f1()
148; CHECK-NEXT:    br label [[IF2_PEEL17]]
149; CHECK:       if2.peel17:
150; CHECK-NEXT:    [[CMP2_PEEL18:%.*]] = icmp ult i32 [[INC_PEEL10]], 4
151; CHECK-NEXT:    br i1 [[CMP2_PEEL18]], label [[IF_THEN2_PEEL19:%.*]], label [[FOR_INC_PEEL20:%.*]]
152; CHECK:       if.then2.peel19:
153; CHECK-NEXT:    call void @f1()
154; CHECK-NEXT:    br label [[FOR_INC_PEEL20]]
155; CHECK:       for.inc.peel20:
156; CHECK-NEXT:    [[INC_PEEL21:%.*]] = add nsw i32 [[INC_PEEL10]], 1
157; CHECK-NEXT:    [[CMP_PEEL22:%.*]] = icmp slt i32 [[INC_PEEL21]], [[K]]
158; CHECK-NEXT:    br i1 [[CMP_PEEL22]], label [[FOR_BODY_PEEL_NEXT12:%.*]], label [[FOR_END]]
159; CHECK:       for.body.peel.next12:
160; CHECK-NEXT:    br label [[FOR_BODY_PEEL24:%.*]]
161; CHECK:       for.body.peel24:
162; CHECK-NEXT:    [[CMP1_PEEL25:%.*]] = icmp ult i32 [[INC_PEEL21]], 2
163; CHECK-NEXT:    br i1 [[CMP1_PEEL25]], label [[IF_THEN_PEEL27:%.*]], label [[IF_ELSE_PEEL26:%.*]]
164; CHECK:       if.else.peel26:
165; CHECK-NEXT:    call void @f2()
166; CHECK-NEXT:    br label [[IF2_PEEL28:%.*]]
167; CHECK:       if.then.peel27:
168; CHECK-NEXT:    call void @f1()
169; CHECK-NEXT:    br label [[IF2_PEEL28]]
170; CHECK:       if2.peel28:
171; CHECK-NEXT:    [[CMP2_PEEL29:%.*]] = icmp ult i32 [[INC_PEEL21]], 4
172; CHECK-NEXT:    br i1 [[CMP2_PEEL29]], label [[IF_THEN2_PEEL30:%.*]], label [[FOR_INC_PEEL31:%.*]]
173; CHECK:       if.then2.peel30:
174; CHECK-NEXT:    call void @f1()
175; CHECK-NEXT:    br label [[FOR_INC_PEEL31]]
176; CHECK:       for.inc.peel31:
177; CHECK-NEXT:    [[INC_PEEL32:%.*]] = add nsw i32 [[INC_PEEL21]], 1
178; CHECK-NEXT:    [[CMP_PEEL33:%.*]] = icmp slt i32 [[INC_PEEL32]], [[K]]
179; CHECK-NEXT:    br i1 [[CMP_PEEL33]], label [[FOR_BODY_PEEL_NEXT23:%.*]], label [[FOR_END]]
180; CHECK:       for.body.peel.next23:
181; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT34:%.*]]
182; CHECK:       for.body.peel.next34:
183; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
184; CHECK:       for.body.lr.ph.peel.newph:
185; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
186; CHECK:       for.body:
187; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL32]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
188; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
189; CHECK:       if.then:
190; CHECK-NEXT:    call void @f1()
191; CHECK-NEXT:    br label [[IF2:%.*]]
192; CHECK:       if.else:
193; CHECK-NEXT:    call void @f2()
194; CHECK-NEXT:    br label [[IF2]]
195; CHECK:       if2:
196; CHECK-NEXT:    br i1 false, label [[IF_THEN2:%.*]], label [[FOR_INC]]
197; CHECK:       if.then2:
198; CHECK-NEXT:    call void @f1()
199; CHECK-NEXT:    br label [[FOR_INC]]
200; CHECK:       for.inc:
201; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
202; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
203; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !2
204; CHECK:       for.end.loopexit:
205; CHECK-NEXT:    br label [[FOR_END]]
206; CHECK:       for.end:
207; CHECK-NEXT:    ret void
208;
209for.body.lr.ph:
210  br label %for.body
211
212for.body:
213  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
214  %cmp1 = icmp ult i32 %i.05, 2
215  br i1 %cmp1, label %if.then, label %if.else
216
217if.then:
218  call void @f1()
219  br label %if2
220
221if.else:
222  call void @f2()
223  br label %if2
224
225if2:
226  %cmp2 = icmp ult i32 %i.05, 4
227  br i1 %cmp2, label %if.then2, label %for.inc
228
229if.then2:
230  call void @f1()
231  br label %for.inc
232
233for.inc:
234  %inc = add nsw i32 %i.05, 1
235  %cmp = icmp slt i32 %inc, %k
236  br i1 %cmp, label %for.body, label %for.end
237
238for.end:
239  ret void
240}
241
242; Check that we can peel off iterations that make a condition false.
243define void @test3(i32 %k) {
244; CHECK-LABEL: @test3(
245; CHECK-NEXT:  for.body.lr.ph:
246; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
247; CHECK:       for.body.peel.begin:
248; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
249; CHECK:       for.body.peel:
250; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ugt i32 0, 2
251; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
252; CHECK:       if.else.peel:
253; CHECK-NEXT:    call void @f2()
254; CHECK-NEXT:    br label [[FOR_INC_PEEL:%.*]]
255; CHECK:       if.then.peel:
256; CHECK-NEXT:    call void @f1()
257; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
258; CHECK:       for.inc.peel:
259; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
260; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
261; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
262; CHECK:       for.body.peel.next:
263; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
264; CHECK:       for.body.peel2:
265; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ugt i32 [[INC_PEEL]], 2
266; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
267; CHECK:       if.else.peel4:
268; CHECK-NEXT:    call void @f2()
269; CHECK-NEXT:    br label [[FOR_INC_PEEL6:%.*]]
270; CHECK:       if.then.peel5:
271; CHECK-NEXT:    call void @f1()
272; CHECK-NEXT:    br label [[FOR_INC_PEEL6]]
273; CHECK:       for.inc.peel6:
274; CHECK-NEXT:    [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
275; CHECK-NEXT:    [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
276; CHECK-NEXT:    br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
277; CHECK:       for.body.peel.next1:
278; CHECK-NEXT:    br label [[FOR_BODY_PEEL10:%.*]]
279; CHECK:       for.body.peel10:
280; CHECK-NEXT:    [[CMP1_PEEL11:%.*]] = icmp ugt i32 [[INC_PEEL7]], 2
281; CHECK-NEXT:    br i1 [[CMP1_PEEL11]], label [[IF_THEN_PEEL13:%.*]], label [[IF_ELSE_PEEL12:%.*]]
282; CHECK:       if.else.peel12:
283; CHECK-NEXT:    call void @f2()
284; CHECK-NEXT:    br label [[FOR_INC_PEEL14:%.*]]
285; CHECK:       if.then.peel13:
286; CHECK-NEXT:    call void @f1()
287; CHECK-NEXT:    br label [[FOR_INC_PEEL14]]
288; CHECK:       for.inc.peel14:
289; CHECK-NEXT:    [[INC_PEEL15:%.*]] = add nsw i32 [[INC_PEEL7]], 1
290; CHECK-NEXT:    [[CMP_PEEL16:%.*]] = icmp slt i32 [[INC_PEEL15]], [[K]]
291; CHECK-NEXT:    br i1 [[CMP_PEEL16]], label [[FOR_BODY_PEEL_NEXT9:%.*]], label [[FOR_END]]
292; CHECK:       for.body.peel.next9:
293; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT17:%.*]]
294; CHECK:       for.body.peel.next17:
295; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
296; CHECK:       for.body.lr.ph.peel.newph:
297; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
298; CHECK:       for.body:
299; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL15]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
300; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
301; CHECK:       if.then:
302; CHECK-NEXT:    call void @f1()
303; CHECK-NEXT:    br label [[FOR_INC]]
304; CHECK:       if.else:
305; CHECK-NEXT:    call void @f2()
306; CHECK-NEXT:    br label [[FOR_INC]]
307; CHECK:       for.inc:
308; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
309; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
310; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !3
311; CHECK:       for.end.loopexit:
312; CHECK-NEXT:    br label [[FOR_END]]
313; CHECK:       for.end:
314; CHECK-NEXT:    ret void
315;
316for.body.lr.ph:
317  br label %for.body
318
319for.body:
320  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
321  %cmp1 = icmp ugt i32 %i.05, 2
322  br i1 %cmp1, label %if.then, label %if.else
323
324if.then:
325  call void @f1()
326  br label %for.inc
327
328if.else:
329  call void @f2()
330  br label %for.inc
331
332for.inc:
333  %inc = add nsw i32 %i.05, 1
334  %cmp = icmp slt i32 %inc, %k
335  br i1 %cmp, label %for.body, label %for.end
336
337for.end:
338  ret void
339}
340
341; Test that we only peel off iterations if it simplifies a condition in the
342; loop body after peeling at most MaxPeelCount iterations.
343define void @test4(i32 %k) {
344; CHECK-LABEL: @test4(
345; CHECK-NEXT:  for.body.lr.ph:
346; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
347; CHECK:       for.body:
348; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
349; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[I_05]], 9999
350; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
351; CHECK:       if.then:
352; CHECK-NEXT:    call void @f1()
353; CHECK-NEXT:    br label [[FOR_INC]]
354; CHECK:       for.inc:
355; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
356; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
357; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
358; CHECK:       for.end:
359; CHECK-NEXT:    ret void
360;
361for.body.lr.ph:
362  br label %for.body
363
364for.body:
365  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
366  %cmp1 = icmp ugt i32 %i.05, 9999
367  br i1 %cmp1, label %if.then, label %for.inc
368
369if.then:
370  call void @f1()
371  br label %for.inc
372
373for.inc:
374  %inc = add nsw i32 %i.05, 1
375  %cmp = icmp slt i32 %inc, %k
376  br i1 %cmp, label %for.body, label %for.end
377
378for.end:
379  ret void
380}
381
382; In this case we cannot peel the inner loop, because the condition involves
383; the outer induction variable.
384define void @test5(i32 %k) {
385; CHECK-LABEL: @test5(
386; CHECK-NEXT:  for.body.lr.ph:
387; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
388; CHECK:       outer.header:
389; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[J_INC:%.*]], [[OUTER_INC:%.*]] ]
390; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
391; CHECK:       for.body:
392; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
393; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[J]], 2
394; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
395; CHECK:       if.then:
396; CHECK-NEXT:    call void @f1()
397; CHECK-NEXT:    br label [[FOR_INC]]
398; CHECK:       if.else:
399; CHECK-NEXT:    call void @f2()
400; CHECK-NEXT:    br label [[FOR_INC]]
401; CHECK:       for.inc:
402; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
403; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
404; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[OUTER_INC]]
405; CHECK:       outer.inc:
406; CHECK-NEXT:    [[J_INC]] = add nsw i32 [[J]], 1
407; CHECK-NEXT:    [[OUTER_CMP:%.*]] = icmp slt i32 [[J_INC]], [[K]]
408; CHECK-NEXT:    br i1 [[OUTER_CMP]], label [[OUTER_HEADER]], label [[FOR_END:%.*]]
409; CHECK:       for.end:
410; CHECK-NEXT:    ret void
411;
412for.body.lr.ph:
413  br label %outer.header
414
415outer.header:
416  %j = phi i32 [ 0, %for.body.lr.ph ], [ %j.inc, %outer.inc ]
417  br label %for.body
418
419for.body:
420  %i.05 = phi i32 [ 0, %outer.header ], [ %inc, %for.inc ]
421  %cmp1 = icmp ult i32 %j, 2
422  br i1 %cmp1, label %if.then, label %if.else
423
424if.then:
425  call void @f1()
426  br label %for.inc
427
428if.else:
429  call void @f2()
430  br label %for.inc
431
432for.inc:
433  %inc = add nsw i32 %i.05, 1
434  %cmp = icmp slt i32 %inc, %k
435  br i1 %cmp, label %for.body, label %outer.inc
436
437outer.inc:
438  %j.inc = add nsw i32 %j, 1
439  %outer.cmp = icmp slt i32 %j.inc, %k
440  br i1 %outer.cmp, label %outer.header, label %for.end
441
442
443for.end:
444  ret void
445}
446
447; In this test, the condition involves 2 AddRecs. Without evaluating both
448; AddRecs, we cannot prove that the condition becomes known in the loop body
449; after peeling.
450define void @test6(i32 %k) {
451; CHECK-LABEL: @test6(
452; CHECK-NEXT:  entry:
453; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
454; CHECK:       for.body:
455; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
456; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 4, [[ENTRY]] ], [ [[J_INC:%.*]], [[FOR_INC]] ]
457; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I_05]], [[J]]
458; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
459; CHECK:       if.then:
460; CHECK-NEXT:    call void @f1()
461; CHECK-NEXT:    br label [[FOR_INC]]
462; CHECK:       if.else:
463; CHECK-NEXT:    call void @f2()
464; CHECK-NEXT:    br label [[FOR_INC]]
465; CHECK:       for.inc:
466; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 2
467; CHECK-NEXT:    [[J_INC]] = add nsw i32 [[J]], 1
468; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
469; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
470; CHECK:       for.end:
471; CHECK-NEXT:    ret void
472;
473entry:
474  br label %for.body
475
476for.body:
477  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
478  %j = phi i32 [ 4, %entry ], [ %j.inc, %for.inc ]
479  %cmp1 = icmp ult i32 %i.05, %j
480  br i1 %cmp1, label %if.then, label %if.else
481
482if.then:
483  call void @f1()
484  br label %for.inc
485
486if.else:
487  call void @f2()
488  br label %for.inc
489
490for.inc:
491  %inc = add nsw i32 %i.05, 2
492  %j.inc = add nsw i32 %j, 1
493  %cmp = icmp slt i32 %inc, %k
494  br i1 %cmp, label %for.body, label %for.end
495
496for.end:
497  ret void
498}
499
500define void @test7(i32 %k) {
501; FIXME: Could simplify loop body by peeling one additional iteration after
502;        i != 3 becomes false
503; CHECK-LABEL: @test7(
504; CHECK-NEXT:  for.body.lr.ph:
505; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
506; CHECK:       for.body:
507; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
508; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[I_05]], 3
509; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
510; CHECK:       if.then:
511; CHECK-NEXT:    call void @f1()
512; CHECK-NEXT:    br label [[FOR_INC]]
513; CHECK:       for.inc:
514; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
515; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
516; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
517; CHECK:       for.end:
518; CHECK-NEXT:    ret void
519;
520for.body.lr.ph:
521  br label %for.body
522
523for.body:
524  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
525  %cmp1 = icmp ne i32 %i.05, 3
526  br i1 %cmp1, label %if.then, label %for.inc
527
528if.then:
529  call void @f1()
530  br label %for.inc
531
532for.inc:
533  %inc = add nsw i32 %i.05, 1
534  %cmp = icmp slt i32 %inc, %k
535  br i1 %cmp, label %for.body, label %for.end
536
537for.end:
538  ret void
539}
540
541define void @test8(i32 %k) {
542; FIXME: Could simplify loop body by peeling one additional iteration after
543;        i == 3 becomes true.
544; CHECK-LABEL: @test8(
545; CHECK-NEXT:  for.body.lr.ph:
546; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
547; CHECK:       for.body:
548; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
549; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I_05]], 3
550; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
551; CHECK:       if.then:
552; CHECK-NEXT:    call void @f1()
553; CHECK-NEXT:    br label [[FOR_INC]]
554; CHECK:       for.inc:
555; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
556; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
557; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
558; CHECK:       for.end:
559; CHECK-NEXT:    ret void
560;
561for.body.lr.ph:
562  br label %for.body
563
564for.body:
565  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
566  %cmp1 = icmp eq i32 %i.05, 3
567  br i1 %cmp1, label %if.then, label %for.inc
568
569if.then:
570  call void @f1()
571  br label %for.inc
572
573for.inc:
574  %inc = add nsw i32 %i.05, 1
575  %cmp = icmp slt i32 %inc, %k
576  br i1 %cmp, label %for.body, label %for.end
577
578for.end:
579  ret void
580}
581
582; Comparison with non-monotonic predicate due to possible wrapping, loop
583; body cannot be simplified.
584define void @test9(i32 %k) {
585; CHECK-LABEL: @test9(
586; CHECK-NEXT:  for.body.lr.ph:
587; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
588; CHECK:       for.body:
589; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
590; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I_05]], 3
591; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
592; CHECK:       if.then:
593; CHECK-NEXT:    call void @f1()
594; CHECK-NEXT:    br label [[FOR_INC]]
595; CHECK:       for.inc:
596; CHECK-NEXT:    [[INC]] = add i32 [[I_05]], 1
597; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
598; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
599; CHECK:       for.end:
600; CHECK-NEXT:    ret void
601;
602for.body.lr.ph:
603  br label %for.body
604
605for.body:
606  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
607  %cmp1 = icmp slt i32 %i.05, 3
608  br i1 %cmp1, label %if.then, label %for.inc
609
610if.then:
611  call void @f1()
612  br label %for.inc
613
614for.inc:
615  %inc = add i32 %i.05, 1
616  %cmp = icmp slt i32 %inc, %k
617  br i1 %cmp, label %for.body, label %for.end
618
619for.end:
620  ret void
621}
622