xref: /llvm-project/llvm/test/Transforms/LoopUnroll/peel-loop-conditions.ll (revision 2d69827c5c754f0eca98e497ecf0e52ed54b4fd3)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -passes=loop-unroll -unroll-peel-max-count=4 -verify-dom-info | FileCheck %s
3
4declare void @f1()
5declare void @f2()
6declare void @f3(i32)
7
8; Check that we can peel off iterations that make conditions true.
9define void @test1(i32 %k) {
10; CHECK-LABEL: @test1(
11; CHECK-NEXT:  for.body.lr.ph:
12; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
13; CHECK:       for.body.peel.begin:
14; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
15; CHECK:       for.body.peel:
16; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
17; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
18; CHECK:       if.else.peel:
19; CHECK-NEXT:    call void @f2()
20; CHECK-NEXT:    br label [[FOR_INC_PEEL:%.*]]
21; CHECK:       if.then.peel:
22; CHECK-NEXT:    call void @f1()
23; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
24; CHECK:       for.inc.peel:
25; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
26; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
27; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
28; Verify that MD_loop metadata is dropped.
29; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
30; CHECK:       for.body.peel.next:
31; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
32; CHECK:       for.body.peel2:
33; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
34; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
35; CHECK:       if.else.peel4:
36; CHECK-NEXT:    call void @f2()
37; CHECK-NEXT:    br label [[FOR_INC_PEEL6:%.*]]
38; CHECK:       if.then.peel5:
39; CHECK-NEXT:    call void @f1()
40; CHECK-NEXT:    br label [[FOR_INC_PEEL6]]
41; CHECK:       for.inc.peel6:
42; CHECK-NEXT:    [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
43; CHECK-NEXT:    [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
44; CHECK-NEXT:    br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
45; Verify that MD_loop metadata is dropped.
46; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
47; CHECK:       for.body.peel.next1:
48; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT9:%.*]]
49; CHECK:       for.body.peel.next9:
50; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
51; CHECK:       for.body.lr.ph.peel.newph:
52; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
53; CHECK:       for.body:
54; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL7]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
55; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
56; CHECK:       if.then:
57; CHECK-NEXT:    call void @f1()
58; CHECK-NEXT:    br label [[FOR_INC]]
59; CHECK:       if.else:
60; CHECK-NEXT:    call void @f2()
61; CHECK-NEXT:    br label [[FOR_INC]]
62; CHECK:       for.inc:
63; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
64; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
65; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
66; CHECK:       for.end.loopexit:
67; CHECK-NEXT:    br label [[FOR_END]]
68; CHECK:       for.end:
69; CHECK-NEXT:    ret void
70;
71for.body.lr.ph:
72  br label %for.body
73
74for.body:
75  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
76  %cmp1 = icmp ult i32 %i.05, 2
77  br i1 %cmp1, label %if.then, label %if.else
78
79if.then:
80  call void @f1()
81  br label %for.inc
82
83if.else:
84  call void @f2()
85  br label %for.inc
86
87for.inc:
88  %inc = add nsw i32 %i.05, 1
89  %cmp = icmp slt i32 %inc, %k
90  br i1 %cmp, label %for.body, label %for.end, !llvm.loop !1
91
92for.end:
93  ret void
94}
95
96!1 = distinct !{!1}
97
98; Check we peel off the maximum number of iterations that make conditions true.
99define void @test2(i32 %k) {
100; CHECK-LABEL: @test2(
101; CHECK-NEXT:  for.body.lr.ph:
102; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
103; CHECK:       for.body.peel.begin:
104; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
105; CHECK:       for.body.peel:
106; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2
107; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
108; CHECK:       if.else.peel:
109; CHECK-NEXT:    call void @f2()
110; CHECK-NEXT:    br label [[IF2_PEEL:%.*]]
111; CHECK:       if.then.peel:
112; CHECK-NEXT:    call void @f1()
113; CHECK-NEXT:    br label [[IF2_PEEL]]
114; CHECK:       if2.peel:
115; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 4
116; CHECK-NEXT:    br i1 [[CMP2_PEEL]], label [[IF_THEN2_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
117; CHECK:       if.then2.peel:
118; CHECK-NEXT:    call void @f1()
119; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
120; CHECK:       for.inc.peel:
121; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
122; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
123; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
124; Verify that MD_loop metadata is dropped.
125; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
126; CHECK:       for.body.peel.next:
127; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
128; CHECK:       for.body.peel2:
129; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2
130; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
131; CHECK:       if.else.peel4:
132; CHECK-NEXT:    call void @f2()
133; CHECK-NEXT:    br label [[IF2_PEEL6:%.*]]
134; CHECK:       if.then.peel5:
135; CHECK-NEXT:    call void @f1()
136; CHECK-NEXT:    br label [[IF2_PEEL6]]
137; CHECK:       if2.peel6:
138; CHECK-NEXT:    [[CMP2_PEEL7:%.*]] = icmp ult i32 [[INC_PEEL]], 4
139; CHECK-NEXT:    br i1 [[CMP2_PEEL7]], label [[IF_THEN2_PEEL8:%.*]], label [[FOR_INC_PEEL9:%.*]]
140; CHECK:       if.then2.peel8:
141; CHECK-NEXT:    call void @f1()
142; CHECK-NEXT:    br label [[FOR_INC_PEEL9]]
143; CHECK:       for.inc.peel9:
144; CHECK-NEXT:    [[INC_PEEL10:%.*]] = add nsw i32 [[INC_PEEL]], 1
145; CHECK-NEXT:    [[CMP_PEEL11:%.*]] = icmp slt i32 [[INC_PEEL10]], [[K]]
146; CHECK-NEXT:    br i1 [[CMP_PEEL11]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
147; Verify that MD_loop metadata is dropped.
148; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
149; CHECK:       for.body.peel.next1:
150; CHECK-NEXT:    br label [[FOR_BODY_PEEL13:%.*]]
151; CHECK:       for.body.peel13:
152; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp ult i32 [[INC_PEEL10]], 2
153; CHECK-NEXT:    br i1 [[CMP1_PEEL14]], label [[IF_THEN_PEEL16:%.*]], label [[IF_ELSE_PEEL15:%.*]]
154; CHECK:       if.else.peel15:
155; CHECK-NEXT:    call void @f2()
156; CHECK-NEXT:    br label [[IF2_PEEL17:%.*]]
157; CHECK:       if.then.peel16:
158; CHECK-NEXT:    call void @f1()
159; CHECK-NEXT:    br label [[IF2_PEEL17]]
160; CHECK:       if2.peel17:
161; CHECK-NEXT:    [[CMP2_PEEL18:%.*]] = icmp ult i32 [[INC_PEEL10]], 4
162; CHECK-NEXT:    br i1 [[CMP2_PEEL18]], label [[IF_THEN2_PEEL19:%.*]], label [[FOR_INC_PEEL20:%.*]]
163; CHECK:       if.then2.peel19:
164; CHECK-NEXT:    call void @f1()
165; CHECK-NEXT:    br label [[FOR_INC_PEEL20]]
166; CHECK:       for.inc.peel20:
167; CHECK-NEXT:    [[INC_PEEL21:%.*]] = add nsw i32 [[INC_PEEL10]], 1
168; CHECK-NEXT:    [[CMP_PEEL22:%.*]] = icmp slt i32 [[INC_PEEL21]], [[K]]
169; CHECK-NEXT:    br i1 [[CMP_PEEL22]], label [[FOR_BODY_PEEL_NEXT12:%.*]], label [[FOR_END]]
170; Verify that MD_loop metadata is dropped.
171; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
172; CHECK:       for.body.peel.next12:
173; CHECK-NEXT:    br label [[FOR_BODY_PEEL24:%.*]]
174; CHECK:       for.body.peel24:
175; CHECK-NEXT:    [[CMP1_PEEL25:%.*]] = icmp ult i32 [[INC_PEEL21]], 2
176; CHECK-NEXT:    br i1 [[CMP1_PEEL25]], label [[IF_THEN_PEEL27:%.*]], label [[IF_ELSE_PEEL26:%.*]]
177; CHECK:       if.else.peel26:
178; CHECK-NEXT:    call void @f2()
179; CHECK-NEXT:    br label [[IF2_PEEL28:%.*]]
180; CHECK:       if.then.peel27:
181; CHECK-NEXT:    call void @f1()
182; CHECK-NEXT:    br label [[IF2_PEEL28]]
183; CHECK:       if2.peel28:
184; CHECK-NEXT:    [[CMP2_PEEL29:%.*]] = icmp ult i32 [[INC_PEEL21]], 4
185; CHECK-NEXT:    br i1 [[CMP2_PEEL29]], label [[IF_THEN2_PEEL30:%.*]], label [[FOR_INC_PEEL31:%.*]]
186; CHECK:       if.then2.peel30:
187; CHECK-NEXT:    call void @f1()
188; CHECK-NEXT:    br label [[FOR_INC_PEEL31]]
189; CHECK:       for.inc.peel31:
190; CHECK-NEXT:    [[INC_PEEL32:%.*]] = add nsw i32 [[INC_PEEL21]], 1
191; CHECK-NEXT:    [[CMP_PEEL33:%.*]] = icmp slt i32 [[INC_PEEL32]], [[K]]
192; CHECK-NEXT:    br i1 [[CMP_PEEL33]], label [[FOR_BODY_PEEL_NEXT23:%.*]], label [[FOR_END]]
193; Verify that MD_loop metadata is dropped.
194; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
195; CHECK:       for.body.peel.next23:
196; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT34:%.*]]
197; CHECK:       for.body.peel.next34:
198; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
199; CHECK:       for.body.lr.ph.peel.newph:
200; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
201; CHECK:       for.body:
202; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL32]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
203; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
204; CHECK:       if.then:
205; CHECK-NEXT:    call void @f1()
206; CHECK-NEXT:    br label [[IF2:%.*]]
207; CHECK:       if.else:
208; CHECK-NEXT:    call void @f2()
209; CHECK-NEXT:    br label [[IF2]]
210; CHECK:       if2:
211; CHECK-NEXT:    br i1 false, label [[IF_THEN2:%.*]], label [[FOR_INC]]
212; CHECK:       if.then2:
213; CHECK-NEXT:    call void @f1()
214; CHECK-NEXT:    br label [[FOR_INC]]
215; CHECK:       for.inc:
216; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
217; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
218; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
219; CHECK:       for.end.loopexit:
220; CHECK-NEXT:    br label [[FOR_END]]
221; CHECK:       for.end:
222; CHECK-NEXT:    ret void
223;
224for.body.lr.ph:
225  br label %for.body
226
227for.body:
228  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
229  %cmp1 = icmp ult i32 %i.05, 2
230  br i1 %cmp1, label %if.then, label %if.else
231
232if.then:
233  call void @f1()
234  br label %if2
235
236if.else:
237  call void @f2()
238  br label %if2
239
240if2:
241  %cmp2 = icmp ult i32 %i.05, 4
242  br i1 %cmp2, label %if.then2, label %for.inc
243
244if.then2:
245  call void @f1()
246  br label %for.inc
247
248for.inc:
249  %inc = add nsw i32 %i.05, 1
250  %cmp = icmp slt i32 %inc, %k
251  br i1 %cmp, label %for.body, label %for.end, !llvm.loop !2
252
253for.end:
254  ret void
255}
256
257!2 = distinct !{!2}
258
259; Check that we can peel off iterations that make a condition false.
260define void @test3(i32 %k) {
261; CHECK-LABEL: @test3(
262; CHECK-NEXT:  for.body.lr.ph:
263; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
264; CHECK:       for.body.peel.begin:
265; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
266; CHECK:       for.body.peel:
267; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ugt i32 0, 2
268; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
269; CHECK:       if.else.peel:
270; CHECK-NEXT:    call void @f2()
271; CHECK-NEXT:    br label [[FOR_INC_PEEL:%.*]]
272; CHECK:       if.then.peel:
273; CHECK-NEXT:    call void @f1()
274; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
275; CHECK:       for.inc.peel:
276; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
277; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
278; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%[^,]*]]
279; Verify that MD_loop metadata is dropped.
280; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
281; CHECK:       for.body.peel.next:
282; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
283; CHECK:       for.body.peel2:
284; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ugt i32 [[INC_PEEL]], 2
285; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
286; CHECK:       if.else.peel4:
287; CHECK-NEXT:    call void @f2()
288; CHECK-NEXT:    br label [[FOR_INC_PEEL6:%.*]]
289; CHECK:       if.then.peel5:
290; CHECK-NEXT:    call void @f1()
291; CHECK-NEXT:    br label [[FOR_INC_PEEL6]]
292; CHECK:       for.inc.peel6:
293; CHECK-NEXT:    [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1
294; CHECK-NEXT:    [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]]
295; CHECK-NEXT:    br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
296; Verify that MD_loop metadata is dropped.
297; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
298; CHECK:       for.body.peel.next1:
299; CHECK-NEXT:    br label [[FOR_BODY_PEEL10:%.*]]
300; CHECK:       for.body.peel10:
301; CHECK-NEXT:    [[CMP1_PEEL11:%.*]] = icmp ugt i32 [[INC_PEEL7]], 2
302; CHECK-NEXT:    br i1 [[CMP1_PEEL11]], label [[IF_THEN_PEEL13:%.*]], label [[IF_ELSE_PEEL12:%.*]]
303; CHECK:       if.else.peel12:
304; CHECK-NEXT:    call void @f2()
305; CHECK-NEXT:    br label [[FOR_INC_PEEL14:%.*]]
306; CHECK:       if.then.peel13:
307; CHECK-NEXT:    call void @f1()
308; CHECK-NEXT:    br label [[FOR_INC_PEEL14]]
309; CHECK:       for.inc.peel14:
310; CHECK-NEXT:    [[INC_PEEL15:%.*]] = add nsw i32 [[INC_PEEL7]], 1
311; CHECK-NEXT:    [[CMP_PEEL16:%.*]] = icmp slt i32 [[INC_PEEL15]], [[K]]
312; CHECK-NEXT:    br i1 [[CMP_PEEL16]], label [[FOR_BODY_PEEL_NEXT9:%.*]], label [[FOR_END]]
313; Verify that MD_loop metadata is dropped.
314; CHECK-NOT:   , !llvm.loop !{{[0-9]*}}
315; CHECK:       for.body.peel.next9:
316; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT17:%.*]]
317; CHECK:       for.body.peel.next17:
318; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
319; CHECK:       for.body.lr.ph.peel.newph:
320; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
321; CHECK:       for.body:
322; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL15]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
323; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
324; CHECK:       if.then:
325; CHECK-NEXT:    call void @f1()
326; CHECK-NEXT:    br label [[FOR_INC]]
327; CHECK:       if.else:
328; CHECK-NEXT:    call void @f2()
329; CHECK-NEXT:    br label [[FOR_INC]]
330; CHECK:       for.inc:
331; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
332; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
333; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !{{.*}}
334; CHECK:       for.end.loopexit:
335; CHECK-NEXT:    br label [[FOR_END]]
336; CHECK:       for.end:
337; CHECK-NEXT:    ret void
338;
339for.body.lr.ph:
340  br label %for.body
341
342for.body:
343  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
344  %cmp1 = icmp ugt i32 %i.05, 2
345  br i1 %cmp1, label %if.then, label %if.else
346
347if.then:
348  call void @f1()
349  br label %for.inc
350
351if.else:
352  call void @f2()
353  br label %for.inc
354
355for.inc:
356  %inc = add nsw i32 %i.05, 1
357  %cmp = icmp slt i32 %inc, %k
358  br i1 %cmp, label %for.body, label %for.end, !llvm.loop !3
359
360for.end:
361  ret void
362}
363
364!3 = distinct !{!3}
365
366; Test that we only peel off iterations if it simplifies a condition in the
367; loop body after peeling at most MaxPeelCount iterations.
368define void @test4(i32 %k) {
369; CHECK-LABEL: @test4(
370; CHECK-NEXT:  for.body.lr.ph:
371; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
372; CHECK:       for.body:
373; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
374; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[I_05]], 9999
375; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
376; CHECK:       if.then:
377; CHECK-NEXT:    call void @f1()
378; CHECK-NEXT:    br label [[FOR_INC]]
379; CHECK:       for.inc:
380; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
381; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
382; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
383; CHECK:       for.end:
384; CHECK-NEXT:    ret void
385;
386for.body.lr.ph:
387  br label %for.body
388
389for.body:
390  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
391  %cmp1 = icmp ugt i32 %i.05, 9999
392  br i1 %cmp1, label %if.then, label %for.inc
393
394if.then:
395  call void @f1()
396  br label %for.inc
397
398for.inc:
399  %inc = add nsw i32 %i.05, 1
400  %cmp = icmp slt i32 %inc, %k
401  br i1 %cmp, label %for.body, label %for.end
402
403for.end:
404  ret void
405}
406
407; In this test, the condition involves 2 AddRecs. Without evaluating both
408; AddRecs, we cannot prove that the condition becomes known in the loop body
409; after peeling.
410define void @test5(i32 %k) {
411; CHECK-LABEL: @test5(
412; CHECK-NEXT:  entry:
413; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
414; CHECK:       for.body:
415; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
416; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 4, [[ENTRY]] ], [ [[J_INC:%.*]], [[FOR_INC]] ]
417; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I_05]], [[J]]
418; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
419; CHECK:       if.then:
420; CHECK-NEXT:    call void @f1()
421; CHECK-NEXT:    br label [[FOR_INC]]
422; CHECK:       if.else:
423; CHECK-NEXT:    call void @f2()
424; CHECK-NEXT:    br label [[FOR_INC]]
425; CHECK:       for.inc:
426; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 2
427; CHECK-NEXT:    [[J_INC]] = add nsw i32 [[J]], 1
428; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
429; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
430; CHECK:       for.end:
431; CHECK-NEXT:    ret void
432;
433entry:
434  br label %for.body
435
436for.body:
437  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
438  %j = phi i32 [ 4, %entry ], [ %j.inc, %for.inc ]
439  %cmp1 = icmp ult i32 %i.05, %j
440  br i1 %cmp1, label %if.then, label %if.else
441
442if.then:
443  call void @f1()
444  br label %for.inc
445
446if.else:
447  call void @f2()
448  br label %for.inc
449
450for.inc:
451  %inc = add nsw i32 %i.05, 2
452  %j.inc = add nsw i32 %j, 1
453  %cmp = icmp slt i32 %inc, %k
454  br i1 %cmp, label %for.body, label %for.end
455
456for.end:
457  ret void
458}
459
460define void @test6(i32 %k) {
461; CHECK-LABEL: @test6(
462; CHECK-NEXT:  for.body.lr.ph:
463; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
464; CHECK:       for.body.peel.begin:
465; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
466; CHECK:       for.body.peel:
467; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ne i32 0, 3
468; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
469; CHECK:       if.then.peel:
470; CHECK-NEXT:    call void @f1()
471; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
472; CHECK:       for.inc.peel:
473; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
474; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
475; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
476; CHECK:       for.body.peel.next:
477; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
478; CHECK:       for.body.peel2:
479; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ne i32 [[INC_PEEL]], 3
480; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL4:%.*]], label [[FOR_INC_PEEL5:%.*]]
481; CHECK:       if.then.peel4:
482; CHECK-NEXT:    call void @f1()
483; CHECK-NEXT:    br label [[FOR_INC_PEEL5]]
484; CHECK:       for.inc.peel5:
485; CHECK-NEXT:    [[INC_PEEL6:%.*]] = add nsw i32 [[INC_PEEL]], 1
486; CHECK-NEXT:    [[CMP_PEEL7:%.*]] = icmp slt i32 [[INC_PEEL6]], [[K]]
487; CHECK-NEXT:    br i1 [[CMP_PEEL7]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
488; CHECK:       for.body.peel.next1:
489; CHECK-NEXT:    br label [[FOR_BODY_PEEL9:%.*]]
490; CHECK:       for.body.peel9:
491; CHECK-NEXT:    [[CMP1_PEEL10:%.*]] = icmp ne i32 [[INC_PEEL6]], 3
492; CHECK-NEXT:    br i1 [[CMP1_PEEL10]], label [[IF_THEN_PEEL11:%.*]], label [[FOR_INC_PEEL12:%.*]]
493; CHECK:       if.then.peel11:
494; CHECK-NEXT:    call void @f1()
495; CHECK-NEXT:    br label [[FOR_INC_PEEL12]]
496; CHECK:       for.inc.peel12:
497; CHECK-NEXT:    [[INC_PEEL13:%.*]] = add nsw i32 [[INC_PEEL6]], 1
498; CHECK-NEXT:    [[CMP_PEEL14:%.*]] = icmp slt i32 [[INC_PEEL13]], [[K]]
499; CHECK-NEXT:    br i1 [[CMP_PEEL14]], label [[FOR_BODY_PEEL_NEXT8:%.*]], label [[FOR_END]]
500; CHECK:       for.body.peel.next8:
501; CHECK-NEXT:    br label [[FOR_BODY_PEEL16:%.*]]
502; CHECK:       for.body.peel16:
503; CHECK-NEXT:    [[CMP1_PEEL17:%.*]] = icmp ne i32 [[INC_PEEL13]], 3
504; CHECK-NEXT:    br i1 [[CMP1_PEEL17]], label [[IF_THEN_PEEL18:%.*]], label [[FOR_INC_PEEL19:%.*]]
505; CHECK:       if.then.peel18:
506; CHECK-NEXT:    call void @f1()
507; CHECK-NEXT:    br label [[FOR_INC_PEEL19]]
508; CHECK:       for.inc.peel19:
509; CHECK-NEXT:    [[INC_PEEL20:%.*]] = add nsw i32 [[INC_PEEL13]], 1
510; CHECK-NEXT:    [[CMP_PEEL21:%.*]] = icmp slt i32 [[INC_PEEL20]], [[K]]
511; CHECK-NEXT:    br i1 [[CMP_PEEL21]], label [[FOR_BODY_PEEL_NEXT15:%.*]], label [[FOR_END]]
512; CHECK:       for.body.peel.next15:
513; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT22:%.*]]
514; CHECK:       for.body.peel.next22:
515; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
516; CHECK:       for.body.lr.ph.peel.newph:
517; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
518; CHECK:       for.body:
519; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL20]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
520; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[FOR_INC]]
521; CHECK:       if.then:
522; CHECK-NEXT:    call void @f1()
523; CHECK-NEXT:    br label [[FOR_INC]]
524; CHECK:       for.inc:
525; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
526; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
527; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !6
528; CHECK:       for.end.loopexit:
529; CHECK-NEXT:    br label [[FOR_END]]
530; CHECK:       for.end:
531; CHECK-NEXT:    ret void
532;
533for.body.lr.ph:
534  br label %for.body
535
536for.body:
537  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
538  %cmp1 = icmp ne i32 %i.05, 3
539  br i1 %cmp1, label %if.then, label %for.inc
540
541if.then:
542  call void @f1()
543  br label %for.inc
544
545for.inc:
546  %inc = add nsw i32 %i.05, 1
547  %cmp = icmp slt i32 %inc, %k
548  br i1 %cmp, label %for.body, label %for.end
549
550for.end:
551  ret void
552}
553
554define void @test7(i32 %k) {
555; CHECK-LABEL: @test7(
556; CHECK-NEXT:  for.body.lr.ph:
557; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
558; CHECK:       for.body.peel.begin:
559; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
560; CHECK:       for.body.peel:
561; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 0, 3
562; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
563; CHECK:       if.then.peel:
564; CHECK-NEXT:    call void @f1()
565; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
566; CHECK:       for.inc.peel:
567; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i32 0, 1
568; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
569; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
570; CHECK:       for.body.peel.next:
571; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
572; CHECK:       for.body.peel2:
573; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp eq i32 [[INC_PEEL]], 3
574; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL4:%.*]], label [[FOR_INC_PEEL5:%.*]]
575; CHECK:       if.then.peel4:
576; CHECK-NEXT:    call void @f1()
577; CHECK-NEXT:    br label [[FOR_INC_PEEL5]]
578; CHECK:       for.inc.peel5:
579; CHECK-NEXT:    [[INC_PEEL6:%.*]] = add nsw i32 [[INC_PEEL]], 1
580; CHECK-NEXT:    [[CMP_PEEL7:%.*]] = icmp slt i32 [[INC_PEEL6]], [[K]]
581; CHECK-NEXT:    br i1 [[CMP_PEEL7]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
582; CHECK:       for.body.peel.next1:
583; CHECK-NEXT:    br label [[FOR_BODY_PEEL9:%.*]]
584; CHECK:       for.body.peel9:
585; CHECK-NEXT:    [[CMP1_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL6]], 3
586; CHECK-NEXT:    br i1 [[CMP1_PEEL10]], label [[IF_THEN_PEEL11:%.*]], label [[FOR_INC_PEEL12:%.*]]
587; CHECK:       if.then.peel11:
588; CHECK-NEXT:    call void @f1()
589; CHECK-NEXT:    br label [[FOR_INC_PEEL12]]
590; CHECK:       for.inc.peel12:
591; CHECK-NEXT:    [[INC_PEEL13:%.*]] = add nsw i32 [[INC_PEEL6]], 1
592; CHECK-NEXT:    [[CMP_PEEL14:%.*]] = icmp slt i32 [[INC_PEEL13]], [[K]]
593; CHECK-NEXT:    br i1 [[CMP_PEEL14]], label [[FOR_BODY_PEEL_NEXT8:%.*]], label [[FOR_END]]
594; CHECK:       for.body.peel.next8:
595; CHECK-NEXT:    br label [[FOR_BODY_PEEL16:%.*]]
596; CHECK:       for.body.peel16:
597; CHECK-NEXT:    [[CMP1_PEEL17:%.*]] = icmp eq i32 [[INC_PEEL13]], 3
598; CHECK-NEXT:    br i1 [[CMP1_PEEL17]], label [[IF_THEN_PEEL18:%.*]], label [[FOR_INC_PEEL19:%.*]]
599; CHECK:       if.then.peel18:
600; CHECK-NEXT:    call void @f1()
601; CHECK-NEXT:    br label [[FOR_INC_PEEL19]]
602; CHECK:       for.inc.peel19:
603; CHECK-NEXT:    [[INC_PEEL20:%.*]] = add nsw i32 [[INC_PEEL13]], 1
604; CHECK-NEXT:    [[CMP_PEEL21:%.*]] = icmp slt i32 [[INC_PEEL20]], [[K]]
605; CHECK-NEXT:    br i1 [[CMP_PEEL21]], label [[FOR_BODY_PEEL_NEXT15:%.*]], label [[FOR_END]]
606; CHECK:       for.body.peel.next15:
607; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT22:%.*]]
608; CHECK:       for.body.peel.next22:
609; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
610; CHECK:       for.body.lr.ph.peel.newph:
611; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
612; CHECK:       for.body:
613; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL20]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
614; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[FOR_INC]]
615; CHECK:       if.then:
616; CHECK-NEXT:    call void @f1()
617; CHECK-NEXT:    br label [[FOR_INC]]
618; CHECK:       for.inc:
619; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
620; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
621; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !7
622; CHECK:       for.end.loopexit:
623; CHECK-NEXT:    br label [[FOR_END]]
624; CHECK:       for.end:
625; CHECK-NEXT:    ret void
626;
627for.body.lr.ph:
628  br label %for.body
629
630for.body:
631  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
632  %cmp1 = icmp eq i32 %i.05, 3
633  br i1 %cmp1, label %if.then, label %for.inc
634
635if.then:
636  call void @f1()
637  br label %for.inc
638
639for.inc:
640  %inc = add nsw i32 %i.05, 1
641  %cmp = icmp slt i32 %inc, %k
642  br i1 %cmp, label %for.body, label %for.end
643
644for.end:
645  ret void
646}
647
648define void @test8(i32 %k) {
649; CHECK-LABEL: @test8(
650; CHECK-NEXT:  for.body.lr.ph:
651; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
652; CHECK:       for.body.peel.begin:
653; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
654; CHECK:       for.body.peel:
655; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp slt i32 0, 3
656; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]]
657; CHECK:       if.then.peel:
658; CHECK-NEXT:    call void @f1()
659; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
660; CHECK:       for.inc.peel:
661; CHECK-NEXT:    [[INC_PEEL:%.*]] = add i32 0, 1
662; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]]
663; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
664; CHECK:       for.body.peel.next:
665; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
666; CHECK:       for.body.peel2:
667; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp slt i32 [[INC_PEEL]], 3
668; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL4:%.*]], label [[FOR_INC_PEEL5:%.*]]
669; CHECK:       if.then.peel4:
670; CHECK-NEXT:    call void @f1()
671; CHECK-NEXT:    br label [[FOR_INC_PEEL5]]
672; CHECK:       for.inc.peel5:
673; CHECK-NEXT:    [[INC_PEEL6:%.*]] = add i32 [[INC_PEEL]], 1
674; CHECK-NEXT:    [[CMP_PEEL7:%.*]] = icmp slt i32 [[INC_PEEL6]], [[K]]
675; CHECK-NEXT:    br i1 [[CMP_PEEL7]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
676; CHECK:       for.body.peel.next1:
677; CHECK-NEXT:    br label [[FOR_BODY_PEEL9:%.*]]
678; CHECK:       for.body.peel9:
679; CHECK-NEXT:    [[CMP1_PEEL10:%.*]] = icmp slt i32 [[INC_PEEL6]], 3
680; CHECK-NEXT:    br i1 [[CMP1_PEEL10]], label [[IF_THEN_PEEL11:%.*]], label [[FOR_INC_PEEL12:%.*]]
681; CHECK:       if.then.peel11:
682; CHECK-NEXT:    call void @f1()
683; CHECK-NEXT:    br label [[FOR_INC_PEEL12]]
684; CHECK:       for.inc.peel12:
685; CHECK-NEXT:    [[INC_PEEL13:%.*]] = add i32 [[INC_PEEL6]], 1
686; CHECK-NEXT:    [[CMP_PEEL14:%.*]] = icmp slt i32 [[INC_PEEL13]], [[K]]
687; CHECK-NEXT:    br i1 [[CMP_PEEL14]], label [[FOR_BODY_PEEL_NEXT8:%.*]], label [[FOR_END]]
688; CHECK:       for.body.peel.next8:
689; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT15:%.*]]
690; CHECK:       for.body.peel.next15:
691; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
692; CHECK:       for.body.lr.ph.peel.newph:
693; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
694; CHECK:       for.body:
695; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ [[INC_PEEL13]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
696; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[FOR_INC]]
697; CHECK:       if.then:
698; CHECK-NEXT:    call void @f1()
699; CHECK-NEXT:    br label [[FOR_INC]]
700; CHECK:       for.inc:
701; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_05]], 1
702; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]]
703; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop [[LOOP8:![0-9]+]]
704; CHECK:       for.end.loopexit:
705; CHECK-NEXT:    br label [[FOR_END]]
706; CHECK:       for.end:
707; CHECK-NEXT:    ret void
708;
709for.body.lr.ph:
710  br label %for.body
711
712for.body:
713  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
714  %cmp1 = icmp slt i32 %i.05, 3
715  br i1 %cmp1, label %if.then, label %for.inc
716
717if.then:
718  call void @f1()
719  br label %for.inc
720
721for.inc:
722  %inc = add i32 %i.05, 1
723  %cmp = icmp slt i32 %inc, %k
724  br i1 %cmp, label %for.body, label %for.end
725
726for.end:
727  ret void
728}
729; CHECK-NOT: llvm.loop.unroll.disable
730
731define void @test_9__peel_first_iter_via_slt_pred(i32 %len) {
732; CHECK-LABEL: @test_9__peel_first_iter_via_slt_pred(
733; CHECK-NEXT:  entry:
734; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
735; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
736; CHECK:       for.body.preheader:
737; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
738; CHECK:       for.body.peel.begin:
739; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
740; CHECK:       for.body.peel:
741; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp slt i32 0, 1
742; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
743; CHECK:       if.then.peel:
744; CHECK-NEXT:    call void @init()
745; CHECK-NEXT:    br label [[IF_END_PEEL]]
746; CHECK:       if.end.peel:
747; CHECK-NEXT:    call void @sink()
748; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
749; CHECK-NEXT:    [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[LEN]]
750; CHECK-NEXT:    br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
751; CHECK:       for.body.peel.next:
752; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT1:%.*]]
753; CHECK:       for.body.peel.next1:
754; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
755; CHECK:       for.body.preheader.peel.newph:
756; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
757; CHECK:       for.cond.cleanup.loopexit.loopexit:
758; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
759; CHECK:       for.cond.cleanup.loopexit:
760; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
761; CHECK:       for.cond.cleanup:
762; CHECK-NEXT:    ret void
763; CHECK:       for.body:
764; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
765; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END]]
766; CHECK:       if.then:
767; CHECK-NEXT:    call void @init()
768; CHECK-NEXT:    br label [[IF_END]]
769; CHECK:       if.end:
770; CHECK-NEXT:    call void @sink()
771; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
772; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
773; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]]
774;
775entry:
776  %cmp5 = icmp sgt i32 %len, 0
777  br i1 %cmp5, label %for.body, label %for.cond.cleanup
778
779for.cond.cleanup:                                 ; preds = %if.end, %entry
780  ret void
781
782for.body:                                         ; preds = %entry, %if.end
783  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
784  %cmp1 = icmp slt i32 %i.06, 1
785  br i1 %cmp1, label %if.then, label %if.end
786
787if.then:                                          ; preds = %for.body
788  call void @init()
789  br label %if.end
790
791if.end:                                           ; preds = %if.then, %for.body
792  call void @sink()
793  %inc = add nuw nsw i32 %i.06, 1
794  %exitcond = icmp eq i32 %inc, %len
795  br i1 %exitcond, label %for.cond.cleanup, label %for.body
796}
797
798define void @test_10__peel_first_iter_via_sgt_pred(i32 %len) {
799; CHECK-LABEL: @test_10__peel_first_iter_via_sgt_pred(
800; CHECK-NEXT:  entry:
801; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
802; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
803; CHECK:       for.body.preheader:
804; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
805; CHECK:       for.body.peel.begin:
806; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
807; CHECK:       for.body.peel:
808; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp sgt i32 0, 0
809; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_END_PEEL:%.*]], label [[IF_THEN_PEEL:%.*]]
810; CHECK:       if.then.peel:
811; CHECK-NEXT:    call void @init()
812; CHECK-NEXT:    br label [[IF_END_PEEL]]
813; CHECK:       if.end.peel:
814; CHECK-NEXT:    call void @sink()
815; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
816; CHECK-NEXT:    [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[LEN]]
817; CHECK-NEXT:    br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
818; CHECK:       for.body.peel.next:
819; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT1:%.*]]
820; CHECK:       for.body.peel.next1:
821; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
822; CHECK:       for.body.preheader.peel.newph:
823; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
824; CHECK:       for.cond.cleanup.loopexit.loopexit:
825; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
826; CHECK:       for.cond.cleanup.loopexit:
827; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
828; CHECK:       for.cond.cleanup:
829; CHECK-NEXT:    ret void
830; CHECK:       for.body:
831; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
832; CHECK-NEXT:    br i1 true, label [[IF_END]], label [[IF_THEN:%.*]]
833; CHECK:       if.then:
834; CHECK-NEXT:    call void @init()
835; CHECK-NEXT:    br label [[IF_END]]
836; CHECK:       if.end:
837; CHECK-NEXT:    call void @sink()
838; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
839; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
840; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]]
841;
842entry:
843  %cmp5 = icmp sgt i32 %len, 0
844  br i1 %cmp5, label %for.body, label %for.cond.cleanup
845
846for.cond.cleanup:                                 ; preds = %if.end, %entry
847  ret void
848
849for.body:                                         ; preds = %entry, %if.end
850  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
851  %cmp1 = icmp sgt i32 %i.06, 0
852  br i1 %cmp1, label %if.end, label %if.then
853
854if.then:                                          ; preds = %for.body
855  call void @init()
856  br label %if.end
857
858if.end:                                           ; preds = %if.then, %for.body
859  call void @sink()
860  %inc = add nuw nsw i32 %i.06, 1
861  %exitcond = icmp eq i32 %inc, %len
862  br i1 %exitcond, label %for.cond.cleanup, label %for.body
863}
864
865; NOTE: here we should only peel the first iteration,
866;       i.e. all calls to sink() must stay in loop.
867define void @test11__peel_first_iter_via_eq_pred(i32 %len) {
868; CHECK-LABEL: @test11__peel_first_iter_via_eq_pred(
869; CHECK-NEXT:  entry:
870; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
871; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
872; CHECK:       for.body.preheader:
873; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
874; CHECK:       for.body.peel.begin:
875; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
876; CHECK:       for.body.peel:
877; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 0, 0
878; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
879; CHECK:       if.then.peel:
880; CHECK-NEXT:    call void @init()
881; CHECK-NEXT:    br label [[IF_END_PEEL]]
882; CHECK:       if.end.peel:
883; CHECK-NEXT:    call void @sink()
884; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
885; CHECK-NEXT:    [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[LEN]]
886; CHECK-NEXT:    br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
887; CHECK:       for.body.peel.next:
888; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT1:%.*]]
889; CHECK:       for.body.peel.next1:
890; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
891; CHECK:       for.body.preheader.peel.newph:
892; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
893; CHECK:       for.cond.cleanup.loopexit.loopexit:
894; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
895; CHECK:       for.cond.cleanup.loopexit:
896; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
897; CHECK:       for.cond.cleanup:
898; CHECK-NEXT:    ret void
899; CHECK:       for.body:
900; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
901; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END]]
902; CHECK:       if.then:
903; CHECK-NEXT:    call void @init()
904; CHECK-NEXT:    br label [[IF_END]]
905; CHECK:       if.end:
906; CHECK-NEXT:    call void @sink()
907; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
908; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
909; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]]
910;
911entry:
912  %cmp5 = icmp sgt i32 %len, 0
913  br i1 %cmp5, label %for.body, label %for.cond.cleanup
914
915for.cond.cleanup:                                 ; preds = %if.end, %entry
916  ret void
917
918for.body:                                         ; preds = %entry, %if.end
919  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
920  %cmp1 = icmp eq i32 %i.06, 0
921  br i1 %cmp1, label %if.then, label %if.end
922
923if.then:                                          ; preds = %for.body
924  call void @init()
925  br label %if.end
926
927if.end:                                           ; preds = %if.then, %for.body
928  call void @sink()
929  %inc = add nuw nsw i32 %i.06, 1
930  %exitcond = icmp eq i32 %inc, %len
931  br i1 %exitcond, label %for.cond.cleanup, label %for.body
932}
933
934; NOTE: here we should only peel the first iteration,
935;       i.e. all calls to sink() must stay in loop.
936define void @test12__peel_first_iter_via_ne_pred(i32 %len) {
937; CHECK-LABEL: @test12__peel_first_iter_via_ne_pred(
938; CHECK-NEXT:  entry:
939; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
940; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
941; CHECK:       for.body.preheader:
942; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
943; CHECK:       for.body.peel.begin:
944; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
945; CHECK:       for.body.peel:
946; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ne i32 0, 0
947; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_END_PEEL:%.*]], label [[IF_THEN_PEEL:%.*]]
948; CHECK:       if.then.peel:
949; CHECK-NEXT:    call void @init()
950; CHECK-NEXT:    br label [[IF_END_PEEL]]
951; CHECK:       if.end.peel:
952; CHECK-NEXT:    call void @sink()
953; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
954; CHECK-NEXT:    [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[LEN]]
955; CHECK-NEXT:    br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
956; CHECK:       for.body.peel.next:
957; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT1:%.*]]
958; CHECK:       for.body.peel.next1:
959; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
960; CHECK:       for.body.preheader.peel.newph:
961; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
962; CHECK:       for.cond.cleanup.loopexit.loopexit:
963; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
964; CHECK:       for.cond.cleanup.loopexit:
965; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
966; CHECK:       for.cond.cleanup:
967; CHECK-NEXT:    ret void
968; CHECK:       for.body:
969; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
970; CHECK-NEXT:    br i1 true, label [[IF_END]], label [[IF_THEN:%.*]]
971; CHECK:       if.then:
972; CHECK-NEXT:    call void @init()
973; CHECK-NEXT:    br label [[IF_END]]
974; CHECK:       if.end:
975; CHECK-NEXT:    call void @sink()
976; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
977; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
978; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP13:![0-9]+]]
979;
980entry:
981  %cmp5 = icmp sgt i32 %len, 0
982  br i1 %cmp5, label %for.body, label %for.cond.cleanup
983
984for.cond.cleanup:                                 ; preds = %if.end, %entry
985  ret void
986
987for.body:                                         ; preds = %entry, %if.end
988  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
989  %cmp1 = icmp ne i32 %i.06, 0
990  br i1 %cmp1, label %if.end, label %if.then
991
992if.then:                                          ; preds = %for.body
993  call void @init()
994  br label %if.end
995
996if.end:                                           ; preds = %if.then, %for.body
997  call void @sink()
998  %inc = add nuw nsw i32 %i.06, 1
999  %exitcond = icmp eq i32 %inc, %len
1000  br i1 %exitcond, label %for.cond.cleanup, label %for.body
1001}
1002
1003; No peeling is profitable here.
1004define void @test13__ivar_mod2_is_1(i32 %len) {
1005; CHECK-LABEL: @test13__ivar_mod2_is_1(
1006; CHECK-NEXT:  entry:
1007; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
1008; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1009; CHECK:       for.body.preheader:
1010; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1011; CHECK:       for.cond.cleanup.loopexit:
1012; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1013; CHECK:       for.cond.cleanup:
1014; CHECK-NEXT:    ret void
1015; CHECK:       for.body:
1016; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1017; CHECK-NEXT:    [[AND:%.*]] = and i32 [[I_06]], 1
1018; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[AND]], 1
1019; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_END]], label [[IF_THEN:%.*]]
1020; CHECK:       if.then:
1021; CHECK-NEXT:    call void @init()
1022; CHECK-NEXT:    br label [[IF_END]]
1023; CHECK:       if.end:
1024; CHECK-NEXT:    call void @sink()
1025; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
1026; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
1027; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
1028;
1029entry:
1030  %cmp5 = icmp sgt i32 %len, 0
1031  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1032
1033for.cond.cleanup:                                 ; preds = %if.end, %entry
1034  ret void
1035
1036for.body:                                         ; preds = %entry, %if.end
1037  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1038  %and = and i32 %i.06, 1
1039  %cmp1 = icmp eq i32 %and, 1
1040  br i1 %cmp1, label %if.end, label %if.then
1041
1042if.then:                                          ; preds = %for.body
1043  call void @init()
1044  br label %if.end
1045
1046if.end:                                           ; preds = %if.then, %for.body
1047  call void @sink()
1048  %inc = add nuw nsw i32 %i.06, 1
1049  %exitcond = icmp eq i32 %inc, %len
1050  br i1 %exitcond, label %for.cond.cleanup, label %for.body
1051}
1052
1053; No peeling is profitable here.
1054define void @test14__ivar_mod2_is_0(i32 %len) {
1055; CHECK-LABEL: @test14__ivar_mod2_is_0(
1056; CHECK-NEXT:  entry:
1057; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[LEN:%.*]], 0
1058; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1059; CHECK:       for.body.preheader:
1060; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1061; CHECK:       for.cond.cleanup.loopexit:
1062; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1063; CHECK:       for.cond.cleanup:
1064; CHECK-NEXT:    ret void
1065; CHECK:       for.body:
1066; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1067; CHECK-NEXT:    [[AND:%.*]] = and i32 [[I_06]], 1
1068; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[AND]], 0
1069; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_END]], label [[IF_THEN:%.*]]
1070; CHECK:       if.then:
1071; CHECK-NEXT:    call void @init()
1072; CHECK-NEXT:    br label [[IF_END]]
1073; CHECK:       if.end:
1074; CHECK-NEXT:    call void @sink()
1075; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
1076; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[LEN]]
1077; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
1078;
1079entry:
1080  %cmp5 = icmp sgt i32 %len, 0
1081  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1082
1083for.cond.cleanup:                                 ; preds = %if.end, %entry
1084  ret void
1085
1086for.body:                                         ; preds = %entry, %if.end
1087  %i.06 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1088  %and = and i32 %i.06, 1
1089  %cmp1 = icmp eq i32 %and, 0
1090  br i1 %cmp1, label %if.end, label %if.then
1091
1092if.then:                                          ; preds = %for.body
1093  call void @init()
1094  br label %if.end
1095
1096if.end:                                           ; preds = %if.then, %for.body
1097  call void @sink()
1098  %inc = add nuw nsw i32 %i.06, 1
1099  %exitcond = icmp eq i32 %inc, %len
1100  br i1 %exitcond, label %for.cond.cleanup, label %for.body
1101}
1102
1103; Similar to @test6, we need to peel one extra iteration, and we can't do that
1104; as per the -unroll-peel-max-count=4, so this shouldn't be peeled at all.
1105define void @test15(i32 %k) {
1106; CHECK-LABEL: @test15(
1107; CHECK-NEXT:  for.body.lr.ph:
1108; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1109; CHECK:       for.body:
1110; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
1111; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[I_05]], 4
1112; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
1113; CHECK:       if.then:
1114; CHECK-NEXT:    call void @f1()
1115; CHECK-NEXT:    br label [[FOR_INC]]
1116; CHECK:       for.inc:
1117; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
1118; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
1119; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
1120; CHECK:       for.end:
1121; CHECK-NEXT:    ret void
1122;
1123for.body.lr.ph:
1124  br label %for.body
1125
1126for.body:
1127  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
1128  %cmp1 = icmp ne i32 %i.05, 4
1129  br i1 %cmp1, label %if.then, label %for.inc
1130
1131if.then:
1132  call void @f1()
1133  br label %for.inc
1134
1135for.inc:
1136  %inc = add nsw i32 %i.05, 1
1137  %cmp = icmp slt i32 %inc, %k
1138  br i1 %cmp, label %for.body, label %for.end
1139
1140for.end:
1141  ret void
1142}
1143
1144; Similar to @test7, we need to peel one extra iteration, and we can't do that
1145; as per the -unroll-peel-max-count=4, so this shouldn't be peeled at all.
1146define void @test16(i32 %k) {
1147; CHECK-LABEL: @test16(
1148; CHECK-NEXT:  for.body.lr.ph:
1149; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1150; CHECK:       for.body:
1151; CHECK-NEXT:    [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
1152; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I_05]], 4
1153; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]
1154; CHECK:       if.then:
1155; CHECK-NEXT:    call void @f1()
1156; CHECK-NEXT:    br label [[FOR_INC]]
1157; CHECK:       for.inc:
1158; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_05]], 1
1159; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]]
1160; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
1161; CHECK:       for.end:
1162; CHECK-NEXT:    ret void
1163;
1164for.body.lr.ph:
1165  br label %for.body
1166
1167for.body:
1168  %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
1169  %cmp1 = icmp eq i32 %i.05, 4
1170  br i1 %cmp1, label %if.then, label %for.inc
1171
1172if.then:
1173  call void @f1()
1174  br label %for.inc
1175
1176for.inc:
1177  %inc = add nsw i32 %i.05, 1
1178  %cmp = icmp slt i32 %inc, %k
1179  br i1 %cmp, label %for.body, label %for.end
1180
1181for.end:
1182  ret void
1183}
1184
1185define void @test17() personality ptr undef{
1186; CHECK-LABEL: @test17(
1187; CHECK-NEXT:  body:
1188; CHECK-NEXT:    br label [[LOOP_PEEL_BEGIN:%.*]]
1189; CHECK:       loop.peel.begin:
1190; CHECK-NEXT:    br label [[LOOP_PEEL:%.*]]
1191; CHECK:       loop.peel:
1192; CHECK-NEXT:    invoke void @f1()
1193; CHECK-NEXT:    to label [[LOOP_PEEL_NEXT:%.*]] unwind label [[EH_UNW_LOOPEXIT_LOOPEXIT_SPLIT_LP:%.*]]
1194; CHECK:       loop.peel.next:
1195; CHECK-NEXT:    br label [[LOOP_PEEL_NEXT1:%.*]]
1196; CHECK:       loop.peel.next1:
1197; CHECK-NEXT:    br label [[BODY_PEEL_NEWPH:%.*]]
1198; CHECK:       body.peel.newph:
1199; CHECK-NEXT:    br label [[LOOP:%.*]]
1200; CHECK:       loop:
1201; CHECK-NEXT:    invoke void @f1()
1202; CHECK-NEXT:    to label [[LOOP]] unwind label [[EH_UNW_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP14:![0-9]+]]
1203; CHECK:       eh.Unw.loopexit.loopexit:
1204; CHECK-NEXT:    [[LPAD_LOOPEXIT2:%.*]] = landingpad { ptr, i32 }
1205; CHECK-NEXT:    catch ptr null
1206; CHECK-NEXT:    br label [[EH_UNW_LOOPEXIT:%.*]]
1207; CHECK:       eh.Unw.loopexit.loopexit.split-lp:
1208; CHECK-NEXT:    [[LPAD_LOOPEXIT_SPLIT_LP:%.*]] = landingpad { ptr, i32 }
1209; CHECK-NEXT:    catch ptr null
1210; CHECK-NEXT:    br label [[EH_UNW_LOOPEXIT]]
1211; CHECK:       eh.Unw.loopexit:
1212; CHECK-NEXT:    ret void
1213;
1214body:
1215  br label %loop
1216
1217loop:
1218  %const = phi i64 [ -33, %loop ], [ -20, %body ]
1219  invoke void @f1()
1220  to label %loop unwind label %eh.Unw.loopexit
1221
1222eh.Unw.loopexit:
1223  %lpad.loopexit = landingpad { ptr, i32 }
1224  catch ptr null
1225  ret void
1226}
1227
1228; Testcase reduced from PR48812.
1229define void @test18(ptr %p) {
1230; CHECK-LABEL: @test18(
1231; CHECK-NEXT:  init:
1232; CHECK-NEXT:    br label [[LOOP_PEEL_BEGIN:%.*]]
1233; CHECK:       loop.peel.begin:
1234; CHECK-NEXT:    br label [[LOOP_PEEL:%.*]]
1235; CHECK:       loop.peel:
1236; CHECK-NEXT:    br label [[LATCH_PEEL:%.*]]
1237; CHECK:       latch.peel:
1238; CHECK-NEXT:    [[CONTROL_PEEL:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
1239; CHECK-NEXT:    switch i32 [[CONTROL_PEEL]], label [[EXIT:%.*]] [
1240; CHECK-NEXT:    i32 2, label [[LOOP_PEEL_NEXT:%.*]]
1241; CHECK-NEXT:    ]
1242; CHECK:       loop.peel.next:
1243; CHECK-NEXT:    br label [[LOOP_PEEL_NEXT1:%.*]]
1244; CHECK:       loop.peel.next1:
1245; CHECK-NEXT:    br label [[INIT_PEEL_NEWPH:%.*]]
1246; CHECK:       init.peel.newph:
1247; CHECK-NEXT:    br label [[LOOP:%.*]]
1248; CHECK:       loop:
1249; CHECK-NEXT:    br label [[LATCH:%.*]]
1250; CHECK:       latch:
1251; CHECK-NEXT:    [[CONTROL:%.*]] = load volatile i32, ptr [[P]], align 4
1252; CHECK-NEXT:    switch i32 [[CONTROL]], label [[EXIT_LOOPEXIT:%.*]] [
1253; CHECK-NEXT:    i32 2, label [[LOOP]]
1254; CHECK-NEXT:    ], !llvm.loop [[LOOP15:![0-9]+]]
1255; CHECK:       exit.loopexit:
1256; CHECK-NEXT:    br label [[EXIT]]
1257; CHECK:       exit:
1258; CHECK-NEXT:    ret void
1259;
1260init:
1261  br label %loop
1262
1263loop:
1264  %const = phi i32 [ 40, %init ], [ 0, %latch ]
1265  br label %latch
1266
1267latch:
1268  %control = load volatile i32, ptr %p
1269  switch i32 %control, label %exit [
1270  i32 2, label %loop
1271  ]
1272
1273exit:
1274  ret void
1275}
1276
1277; Test that we can peel based on a select's condition
1278define void @test19(i32 %num, i32 %a, i32 %b) {
1279; CHECK-LABEL: @test19(
1280; CHECK-NEXT:  entry:
1281; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1282; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1283; CHECK:       for.body.preheader:
1284; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1285; CHECK:       for.body.peel.begin:
1286; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1287; CHECK:       for.body.peel:
1288; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 0, 0
1289; CHECK-NEXT:    [[COND_PEEL:%.*]] = select i1 [[CMP1_PEEL]], i32 [[A:%.*]], i32 [[B:%.*]]
1290; CHECK-NEXT:    tail call void @f3(i32 noundef [[COND_PEEL]])
1291; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1292; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1293; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1294; CHECK:       for.body.peel.next:
1295; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT1:%.*]]
1296; CHECK:       for.body.peel.next1:
1297; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1298; CHECK:       for.body.preheader.peel.newph:
1299; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1300; CHECK:       for.cond.cleanup.loopexit.loopexit:
1301; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1302; CHECK:       for.cond.cleanup.loopexit:
1303; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1304; CHECK:       for.cond.cleanup:
1305; CHECK-NEXT:    ret void
1306; CHECK:       for.body:
1307; CHECK-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[INC_PEEL]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1308; CHECK-NEXT:    tail call void @f3(i32 noundef [[B]])
1309; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_06]], 1
1310; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1311; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]]
1312;
1313entry:
1314  %cmp5 = icmp sgt i32 %num, 0
1315  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1316
1317for.cond.cleanup:                                 ; preds = %for.body, %entry
1318  ret void
1319
1320for.body:                                         ; preds = %entry, %for.body
1321  %i.06 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
1322  %cmp1 = icmp eq i32 %i.06, 0
1323  %cond = select i1 %cmp1, i32 %a, i32 %b
1324  tail call void @f3(i32 noundef %cond) #2
1325  %inc = add nuw nsw i32 %i.06, 1
1326  %exitcond.not = icmp eq i32 %inc, %num
1327  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1328}
1329
1330; Test we can peel based on a and's LHS condition
1331define void @test20(i32 %num, i32 %a, i32 %b) {
1332; CHECK-LABEL: @test20(
1333; CHECK-NEXT:  entry:
1334; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1335; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1336; CHECK:       for.body.preheader:
1337; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1338; CHECK:       for.body.peel.begin:
1339; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1340; CHECK:       for.body.peel:
1341; CHECK-NEXT:    [[REM_PEEL:%.*]] = and i32 0, 1
1342; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 [[REM_PEEL]], 0
1343; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 3
1344; CHECK-NEXT:    [[AND_COND_PEEL:%.*]] = and i1 [[CMP2_PEEL]], [[CMP1_PEEL]]
1345; CHECK-NEXT:    br i1 [[AND_COND_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
1346; CHECK:       if.then.peel:
1347; CHECK-NEXT:    tail call void (...) @f1()
1348; CHECK-NEXT:    br label [[IF_END_PEEL]]
1349; CHECK:       if.end.peel:
1350; CHECK-NEXT:    tail call void (...) @f2()
1351; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1352; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1353; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1354; CHECK:       for.body.peel.next:
1355; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1356; CHECK:       for.body.peel2:
1357; CHECK-NEXT:    [[REM_PEEL3:%.*]] = and i32 [[INC_PEEL]], 1
1358; CHECK-NEXT:    [[CMP1_PEEL4:%.*]] = icmp eq i32 [[REM_PEEL3]], 0
1359; CHECK-NEXT:    [[CMP2_PEEL5:%.*]] = icmp ult i32 [[INC_PEEL]], 3
1360; CHECK-NEXT:    [[AND_COND_PEEL6:%.*]] = and i1 [[CMP2_PEEL5]], [[CMP1_PEEL4]]
1361; CHECK-NEXT:    br i1 [[AND_COND_PEEL6]], label [[IF_THEN_PEEL7:%.*]], label [[IF_END_PEEL8:%.*]]
1362; CHECK:       if.then.peel7:
1363; CHECK-NEXT:    tail call void (...) @f1()
1364; CHECK-NEXT:    br label [[IF_END_PEEL8]]
1365; CHECK:       if.end.peel8:
1366; CHECK-NEXT:    tail call void (...) @f2()
1367; CHECK-NEXT:    [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
1368; CHECK-NEXT:    [[EXITCOND_NOT_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], [[NUM]]
1369; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL10]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
1370; CHECK:       for.body.peel.next1:
1371; CHECK-NEXT:    br label [[FOR_BODY_PEEL12:%.*]]
1372; CHECK:       for.body.peel12:
1373; CHECK-NEXT:    [[REM_PEEL13:%.*]] = and i32 [[INC_PEEL9]], 1
1374; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp eq i32 [[REM_PEEL13]], 0
1375; CHECK-NEXT:    [[CMP2_PEEL15:%.*]] = icmp ult i32 [[INC_PEEL9]], 3
1376; CHECK-NEXT:    [[AND_COND_PEEL16:%.*]] = and i1 [[CMP2_PEEL15]], [[CMP1_PEEL14]]
1377; CHECK-NEXT:    br i1 [[AND_COND_PEEL16]], label [[IF_THEN_PEEL17:%.*]], label [[IF_END_PEEL18:%.*]]
1378; CHECK:       if.then.peel17:
1379; CHECK-NEXT:    tail call void (...) @f1()
1380; CHECK-NEXT:    br label [[IF_END_PEEL18]]
1381; CHECK:       if.end.peel18:
1382; CHECK-NEXT:    tail call void (...) @f2()
1383; CHECK-NEXT:    [[INC_PEEL19:%.*]] = add nuw nsw i32 [[INC_PEEL9]], 1
1384; CHECK-NEXT:    [[EXITCOND_NOT_PEEL20:%.*]] = icmp eq i32 [[INC_PEEL19]], [[NUM]]
1385; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL20]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT11:%.*]]
1386; CHECK:       for.body.peel.next11:
1387; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT21:%.*]]
1388; CHECK:       for.body.peel.next21:
1389; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1390; CHECK:       for.body.preheader.peel.newph:
1391; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1392; CHECK:       for.cond.cleanup.loopexit.loopexit:
1393; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1394; CHECK:       for.cond.cleanup.loopexit:
1395; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1396; CHECK:       for.cond.cleanup:
1397; CHECK-NEXT:    ret void
1398; CHECK:       for.body:
1399; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL19]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1400; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END]]
1401; CHECK:       if.then:
1402; CHECK-NEXT:    tail call void (...) @f1()
1403; CHECK-NEXT:    br label [[IF_END]]
1404; CHECK:       if.end:
1405; CHECK-NEXT:    tail call void (...) @f2()
1406; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1407; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1408; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP17:![0-9]+]]
1409;
1410entry:
1411  %cmp5 = icmp sgt i32 %num, 0
1412  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1413
1414for.cond.cleanup:                                 ; preds = %if.end, %entry
1415  ret void
1416
1417for.body:                                         ; preds = %entry, %if.end
1418  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1419  %rem = and i32 %i.08, 1
1420  %cmp1 = icmp eq i32 %rem, 0
1421  %cmp2 = icmp ult i32 %i.08, 3
1422  %and.cond = and i1 %cmp2, %cmp1
1423  br i1 %and.cond, label %if.then, label %if.end
1424
1425if.then:                                          ; preds = %for.body
1426  tail call void (...) @f1()
1427  br label %if.end
1428
1429if.end:                                           ; preds = %if.then, %for.body
1430  tail call void (...) @f2()
1431  %inc = add nuw nsw i32 %i.08, 1
1432  %exitcond.not = icmp eq i32 %inc, %num
1433  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1434}
1435
1436; Test we can peel based on a and's RHS condition
1437define void @test21(i32 %num, i32 %a, i32 %b) {
1438; CHECK-LABEL: @test21(
1439; CHECK-NEXT:  entry:
1440; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1441; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1442; CHECK:       for.body.preheader:
1443; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1444; CHECK:       for.body.peel.begin:
1445; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1446; CHECK:       for.body.peel:
1447; CHECK-NEXT:    [[REM_PEEL:%.*]] = and i32 0, 1
1448; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 [[REM_PEEL]], 0
1449; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 3
1450; CHECK-NEXT:    [[AND_COND_PEEL:%.*]] = and i1 [[CMP1_PEEL]], [[CMP2_PEEL]]
1451; CHECK-NEXT:    br i1 [[AND_COND_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
1452; CHECK:       if.then.peel:
1453; CHECK-NEXT:    tail call void (...) @f1()
1454; CHECK-NEXT:    br label [[IF_END_PEEL]]
1455; CHECK:       if.end.peel:
1456; CHECK-NEXT:    tail call void (...) @f2()
1457; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1458; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1459; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1460; CHECK:       for.body.peel.next:
1461; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1462; CHECK:       for.body.peel2:
1463; CHECK-NEXT:    [[REM_PEEL3:%.*]] = and i32 [[INC_PEEL]], 1
1464; CHECK-NEXT:    [[CMP1_PEEL4:%.*]] = icmp eq i32 [[REM_PEEL3]], 0
1465; CHECK-NEXT:    [[CMP2_PEEL5:%.*]] = icmp ult i32 [[INC_PEEL]], 3
1466; CHECK-NEXT:    [[AND_COND_PEEL6:%.*]] = and i1 [[CMP1_PEEL4]], [[CMP2_PEEL5]]
1467; CHECK-NEXT:    br i1 [[AND_COND_PEEL6]], label [[IF_THEN_PEEL7:%.*]], label [[IF_END_PEEL8:%.*]]
1468; CHECK:       if.then.peel7:
1469; CHECK-NEXT:    tail call void (...) @f1()
1470; CHECK-NEXT:    br label [[IF_END_PEEL8]]
1471; CHECK:       if.end.peel8:
1472; CHECK-NEXT:    tail call void (...) @f2()
1473; CHECK-NEXT:    [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
1474; CHECK-NEXT:    [[EXITCOND_NOT_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], [[NUM]]
1475; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL10]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
1476; CHECK:       for.body.peel.next1:
1477; CHECK-NEXT:    br label [[FOR_BODY_PEEL12:%.*]]
1478; CHECK:       for.body.peel12:
1479; CHECK-NEXT:    [[REM_PEEL13:%.*]] = and i32 [[INC_PEEL9]], 1
1480; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp eq i32 [[REM_PEEL13]], 0
1481; CHECK-NEXT:    [[CMP2_PEEL15:%.*]] = icmp ult i32 [[INC_PEEL9]], 3
1482; CHECK-NEXT:    [[AND_COND_PEEL16:%.*]] = and i1 [[CMP1_PEEL14]], [[CMP2_PEEL15]]
1483; CHECK-NEXT:    br i1 [[AND_COND_PEEL16]], label [[IF_THEN_PEEL17:%.*]], label [[IF_END_PEEL18:%.*]]
1484; CHECK:       if.then.peel17:
1485; CHECK-NEXT:    tail call void (...) @f1()
1486; CHECK-NEXT:    br label [[IF_END_PEEL18]]
1487; CHECK:       if.end.peel18:
1488; CHECK-NEXT:    tail call void (...) @f2()
1489; CHECK-NEXT:    [[INC_PEEL19:%.*]] = add nuw nsw i32 [[INC_PEEL9]], 1
1490; CHECK-NEXT:    [[EXITCOND_NOT_PEEL20:%.*]] = icmp eq i32 [[INC_PEEL19]], [[NUM]]
1491; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL20]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT11:%.*]]
1492; CHECK:       for.body.peel.next11:
1493; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT21:%.*]]
1494; CHECK:       for.body.peel.next21:
1495; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1496; CHECK:       for.body.preheader.peel.newph:
1497; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1498; CHECK:       for.cond.cleanup.loopexit.loopexit:
1499; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1500; CHECK:       for.cond.cleanup.loopexit:
1501; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1502; CHECK:       for.cond.cleanup:
1503; CHECK-NEXT:    ret void
1504; CHECK:       for.body:
1505; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL19]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1506; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END]]
1507; CHECK:       if.then:
1508; CHECK-NEXT:    tail call void (...) @f1()
1509; CHECK-NEXT:    br label [[IF_END]]
1510; CHECK:       if.end:
1511; CHECK-NEXT:    tail call void (...) @f2()
1512; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1513; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1514; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP18:![0-9]+]]
1515;
1516entry:
1517  %cmp5 = icmp sgt i32 %num, 0
1518  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1519
1520for.cond.cleanup:                                 ; preds = %if.end, %entry
1521  ret void
1522
1523for.body:                                         ; preds = %entry, %if.end
1524  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1525  %rem = and i32 %i.08, 1
1526  %cmp1 = icmp eq i32 %rem, 0
1527  %cmp2 = icmp ult i32 %i.08, 3
1528  %and.cond = and i1 %cmp1, %cmp2
1529  br i1 %and.cond, label %if.then, label %if.end
1530
1531if.then:                                          ; preds = %for.body
1532  tail call void (...) @f1()
1533  br label %if.end
1534
1535if.end:                                           ; preds = %if.then, %for.body
1536  tail call void (...) @f2()
1537  %inc = add nuw nsw i32 %i.08, 1
1538  %exitcond.not = icmp eq i32 %inc, %num
1539  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1540}
1541
1542; Test that we can peel based on a or's LHS condition
1543define void @test22(i32 %num, i32 %a, i32 %b) {
1544; CHECK-LABEL: @test22(
1545; CHECK-NEXT:  entry:
1546; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1547; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1548; CHECK:       for.body.preheader:
1549; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1550; CHECK:       for.body.peel.begin:
1551; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1552; CHECK:       for.body.peel:
1553; CHECK-NEXT:    [[REM_PEEL:%.*]] = and i32 0, 1
1554; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 [[REM_PEEL]], 0
1555; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 3
1556; CHECK-NEXT:    [[OR_COND_PEEL:%.*]] = or i1 [[CMP2_PEEL]], [[CMP1_PEEL]]
1557; CHECK-NEXT:    br i1 [[OR_COND_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
1558; CHECK:       if.then.peel:
1559; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A:%.*]])
1560; CHECK-NEXT:    br label [[IF_END_PEEL]]
1561; CHECK:       if.end.peel:
1562; CHECK-NEXT:    tail call void (...) @f2()
1563; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1564; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1565; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1566; CHECK:       for.body.peel.next:
1567; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1568; CHECK:       for.body.peel2:
1569; CHECK-NEXT:    [[REM_PEEL3:%.*]] = and i32 [[INC_PEEL]], 1
1570; CHECK-NEXT:    [[CMP1_PEEL4:%.*]] = icmp eq i32 [[REM_PEEL3]], 0
1571; CHECK-NEXT:    [[CMP2_PEEL5:%.*]] = icmp ult i32 [[INC_PEEL]], 3
1572; CHECK-NEXT:    [[OR_COND_PEEL6:%.*]] = or i1 [[CMP2_PEEL5]], [[CMP1_PEEL4]]
1573; CHECK-NEXT:    br i1 [[OR_COND_PEEL6]], label [[IF_THEN_PEEL7:%.*]], label [[IF_END_PEEL8:%.*]]
1574; CHECK:       if.then.peel7:
1575; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1576; CHECK-NEXT:    br label [[IF_END_PEEL8]]
1577; CHECK:       if.end.peel8:
1578; CHECK-NEXT:    tail call void (...) @f2()
1579; CHECK-NEXT:    [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
1580; CHECK-NEXT:    [[EXITCOND_NOT_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], [[NUM]]
1581; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL10]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
1582; CHECK:       for.body.peel.next1:
1583; CHECK-NEXT:    br label [[FOR_BODY_PEEL12:%.*]]
1584; CHECK:       for.body.peel12:
1585; CHECK-NEXT:    [[REM_PEEL13:%.*]] = and i32 [[INC_PEEL9]], 1
1586; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp eq i32 [[REM_PEEL13]], 0
1587; CHECK-NEXT:    [[CMP2_PEEL15:%.*]] = icmp ult i32 [[INC_PEEL9]], 3
1588; CHECK-NEXT:    [[OR_COND_PEEL16:%.*]] = or i1 [[CMP2_PEEL15]], [[CMP1_PEEL14]]
1589; CHECK-NEXT:    br i1 [[OR_COND_PEEL16]], label [[IF_THEN_PEEL17:%.*]], label [[IF_END_PEEL18:%.*]]
1590; CHECK:       if.then.peel17:
1591; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1592; CHECK-NEXT:    br label [[IF_END_PEEL18]]
1593; CHECK:       if.end.peel18:
1594; CHECK-NEXT:    tail call void (...) @f2()
1595; CHECK-NEXT:    [[INC_PEEL19:%.*]] = add nuw nsw i32 [[INC_PEEL9]], 1
1596; CHECK-NEXT:    [[EXITCOND_NOT_PEEL20:%.*]] = icmp eq i32 [[INC_PEEL19]], [[NUM]]
1597; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL20]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT11:%.*]]
1598; CHECK:       for.body.peel.next11:
1599; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT21:%.*]]
1600; CHECK:       for.body.peel.next21:
1601; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1602; CHECK:       for.body.preheader.peel.newph:
1603; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1604; CHECK:       for.cond.cleanup.loopexit.loopexit:
1605; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1606; CHECK:       for.cond.cleanup.loopexit:
1607; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1608; CHECK:       for.cond.cleanup:
1609; CHECK-NEXT:    ret void
1610; CHECK:       for.body:
1611; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL19]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1612; CHECK-NEXT:    [[REM:%.*]] = and i32 [[I_08]], 1
1613; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
1614; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_END]]
1615; CHECK:       if.then:
1616; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1617; CHECK-NEXT:    br label [[IF_END]]
1618; CHECK:       if.end:
1619; CHECK-NEXT:    tail call void (...) @f2()
1620; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1621; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1622; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP19:![0-9]+]]
1623;
1624entry:
1625  %cmp5 = icmp sgt i32 %num, 0
1626  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1627
1628for.cond.cleanup:                                 ; preds = %if.end, %entry
1629  ret void
1630
1631for.body:                                         ; preds = %entry, %if.end
1632  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1633  %rem = and i32 %i.08, 1
1634  %cmp1 = icmp eq i32 %rem, 0
1635  %cmp2 = icmp ult i32 %i.08, 3
1636  %or.cond = or i1 %cmp2, %cmp1
1637  br i1 %or.cond, label %if.then, label %if.end
1638
1639if.then:                                          ; preds = %for.body
1640  tail call void (i32, ...) @f1(i32 %a)
1641  br label %if.end
1642
1643if.end:                                           ; preds = %for.body, %if.then
1644  tail call void (...) @f2()
1645  %inc = add nuw nsw i32 %i.08, 1
1646  %exitcond.not = icmp eq i32 %inc, %num
1647  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1648}
1649
1650; Test that we can peel based on a or's RHS condition
1651define void @test23(i32 %num, i32 %a, i32 %b) {
1652; CHECK-LABEL: @test23(
1653; CHECK-NEXT:  entry:
1654; CHECK-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1655; CHECK-NEXT:    br i1 [[CMP5]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1656; CHECK:       for.body.preheader:
1657; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1658; CHECK:       for.body.peel.begin:
1659; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1660; CHECK:       for.body.peel:
1661; CHECK-NEXT:    [[REM_PEEL:%.*]] = and i32 0, 1
1662; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp eq i32 [[REM_PEEL]], 0
1663; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp ult i32 0, 3
1664; CHECK-NEXT:    [[OR_COND_PEEL:%.*]] = or i1 [[CMP1_PEEL]], [[CMP2_PEEL]]
1665; CHECK-NEXT:    br i1 [[OR_COND_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
1666; CHECK:       if.then.peel:
1667; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A:%.*]])
1668; CHECK-NEXT:    br label [[IF_END_PEEL]]
1669; CHECK:       if.end.peel:
1670; CHECK-NEXT:    tail call void (...) @f2()
1671; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1672; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1673; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1674; CHECK:       for.body.peel.next:
1675; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1676; CHECK:       for.body.peel2:
1677; CHECK-NEXT:    [[REM_PEEL3:%.*]] = and i32 [[INC_PEEL]], 1
1678; CHECK-NEXT:    [[CMP1_PEEL4:%.*]] = icmp eq i32 [[REM_PEEL3]], 0
1679; CHECK-NEXT:    [[CMP2_PEEL5:%.*]] = icmp ult i32 [[INC_PEEL]], 3
1680; CHECK-NEXT:    [[OR_COND_PEEL6:%.*]] = or i1 [[CMP1_PEEL4]], [[CMP2_PEEL5]]
1681; CHECK-NEXT:    br i1 [[OR_COND_PEEL6]], label [[IF_THEN_PEEL7:%.*]], label [[IF_END_PEEL8:%.*]]
1682; CHECK:       if.then.peel7:
1683; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1684; CHECK-NEXT:    br label [[IF_END_PEEL8]]
1685; CHECK:       if.end.peel8:
1686; CHECK-NEXT:    tail call void (...) @f2()
1687; CHECK-NEXT:    [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
1688; CHECK-NEXT:    [[EXITCOND_NOT_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], [[NUM]]
1689; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL10]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
1690; CHECK:       for.body.peel.next1:
1691; CHECK-NEXT:    br label [[FOR_BODY_PEEL12:%.*]]
1692; CHECK:       for.body.peel12:
1693; CHECK-NEXT:    [[REM_PEEL13:%.*]] = and i32 [[INC_PEEL9]], 1
1694; CHECK-NEXT:    [[CMP1_PEEL14:%.*]] = icmp eq i32 [[REM_PEEL13]], 0
1695; CHECK-NEXT:    [[CMP2_PEEL15:%.*]] = icmp ult i32 [[INC_PEEL9]], 3
1696; CHECK-NEXT:    [[OR_COND_PEEL16:%.*]] = or i1 [[CMP1_PEEL14]], [[CMP2_PEEL15]]
1697; CHECK-NEXT:    br i1 [[OR_COND_PEEL16]], label [[IF_THEN_PEEL17:%.*]], label [[IF_END_PEEL18:%.*]]
1698; CHECK:       if.then.peel17:
1699; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1700; CHECK-NEXT:    br label [[IF_END_PEEL18]]
1701; CHECK:       if.end.peel18:
1702; CHECK-NEXT:    tail call void (...) @f2()
1703; CHECK-NEXT:    [[INC_PEEL19:%.*]] = add nuw nsw i32 [[INC_PEEL9]], 1
1704; CHECK-NEXT:    [[EXITCOND_NOT_PEEL20:%.*]] = icmp eq i32 [[INC_PEEL19]], [[NUM]]
1705; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL20]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT11:%.*]]
1706; CHECK:       for.body.peel.next11:
1707; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT21:%.*]]
1708; CHECK:       for.body.peel.next21:
1709; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1710; CHECK:       for.body.preheader.peel.newph:
1711; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1712; CHECK:       for.cond.cleanup.loopexit.loopexit:
1713; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1714; CHECK:       for.cond.cleanup.loopexit:
1715; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1716; CHECK:       for.cond.cleanup:
1717; CHECK-NEXT:    ret void
1718; CHECK:       for.body:
1719; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL19]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1720; CHECK-NEXT:    [[REM:%.*]] = and i32 [[I_08]], 1
1721; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[REM]], 0
1722; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_END]]
1723; CHECK:       if.then:
1724; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1725; CHECK-NEXT:    br label [[IF_END]]
1726; CHECK:       if.end:
1727; CHECK-NEXT:    tail call void (...) @f2()
1728; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1729; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1730; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]]
1731;
1732entry:
1733  %cmp5 = icmp sgt i32 %num, 0
1734  br i1 %cmp5, label %for.body, label %for.cond.cleanup
1735
1736for.cond.cleanup:                                 ; preds = %if.end, %entry
1737  ret void
1738
1739for.body:                                         ; preds = %entry, %if.end
1740  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1741  %rem = and i32 %i.08, 1
1742  %cmp1 = icmp eq i32 %rem, 0
1743  %cmp2 = icmp ult i32 %i.08, 3
1744  %or.cond = or i1 %cmp1, %cmp2
1745  br i1 %or.cond, label %if.then, label %if.end
1746
1747if.then:                                          ; preds = %for.body
1748  tail call void (i32, ...) @f1(i32 %a)
1749  br label %if.end
1750
1751if.end:                                           ; preds = %for.body, %if.then
1752  tail call void (...) @f2()
1753  %inc = add nuw nsw i32 %i.08, 1
1754  %exitcond.not = icmp eq i32 %inc, %num
1755  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1756}
1757
1758; Test peeling when the loop is huge, >2^64
1759define void @test24(i128 %k) {
1760; CHECK-LABEL: @test24(
1761; CHECK-NEXT:  for.body.lr.ph:
1762; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1763; CHECK:       for.body.peel.begin:
1764; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1765; CHECK:       for.body.peel:
1766; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i128 0, 2
1767; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]]
1768; CHECK:       if.else.peel:
1769; CHECK-NEXT:    call void @f2()
1770; CHECK-NEXT:    br label [[FOR_INC_PEEL:%.*]]
1771; CHECK:       if.then.peel:
1772; CHECK-NEXT:    call void @f1()
1773; CHECK-NEXT:    br label [[FOR_INC_PEEL]]
1774; CHECK:       for.inc.peel:
1775; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nsw i128 0, 1
1776; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp slt i128 [[INC_PEEL]], [[K:%.*]]
1777; CHECK-NEXT:    br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]]
1778; CHECK:       for.body.peel.next:
1779; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1780; CHECK:       for.body.peel2:
1781; CHECK-NEXT:    [[CMP1_PEEL3:%.*]] = icmp ult i128 [[INC_PEEL]], 2
1782; CHECK-NEXT:    br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]]
1783; CHECK:       if.else.peel4:
1784; CHECK-NEXT:    call void @f2()
1785; CHECK-NEXT:    br label [[FOR_INC_PEEL6:%.*]]
1786; CHECK:       if.then.peel5:
1787; CHECK-NEXT:    call void @f1()
1788; CHECK-NEXT:    br label [[FOR_INC_PEEL6]]
1789; CHECK:       for.inc.peel6:
1790; CHECK-NEXT:    [[INC_PEEL7:%.*]] = add nsw i128 [[INC_PEEL]], 1
1791; CHECK-NEXT:    [[CMP_PEEL8:%.*]] = icmp slt i128 [[INC_PEEL7]], [[K]]
1792; CHECK-NEXT:    br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]]
1793; CHECK:       for.body.peel.next1:
1794; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT9:%.*]]
1795; CHECK:       for.body.peel.next9:
1796; CHECK-NEXT:    br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]]
1797; CHECK:       for.body.lr.ph.peel.newph:
1798; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1799; CHECK:       for.body:
1800; CHECK-NEXT:    [[I_05:%.*]] = phi i128 [ [[INC_PEEL7]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
1801; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1802; CHECK:       if.then:
1803; CHECK-NEXT:    call void @f1()
1804; CHECK-NEXT:    br label [[FOR_INC]]
1805; CHECK:       if.else:
1806; CHECK-NEXT:    call void @f2()
1807; CHECK-NEXT:    br label [[FOR_INC]]
1808; CHECK:       for.inc:
1809; CHECK-NEXT:    [[INC]] = add nuw nsw i128 [[I_05]], 1
1810; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[INC]], [[K]]
1811; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop [[LOOP21:![0-9]+]]
1812; CHECK:       for.end.loopexit:
1813; CHECK-NEXT:    br label [[FOR_END]]
1814; CHECK:       for.end:
1815; CHECK-NEXT:    ret void
1816;
1817for.body.lr.ph:
1818  br label %for.body
1819
1820for.body:
1821  %i.05 = phi i128 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
1822  %cmp1 = icmp ult i128 %i.05, 2
1823  br i1 %cmp1, label %if.then, label %if.else
1824
1825if.then:
1826  call void @f1()
1827  br label %for.inc
1828
1829if.else:
1830  call void @f2()
1831  br label %for.inc
1832
1833for.inc:
1834  %inc = add nsw i128 %i.05, 1
1835  %cmp = icmp slt i128 %inc, %k
1836  br i1 %cmp, label %for.body, label %for.end, !llvm.loop !1
1837
1838for.end:
1839  ret void
1840}
1841
1842; Test peeling just below the recursion limit of 4
1843define void @test25(i32 %num, i32 %a, i32 %b) {
1844; CHECK-LABEL: @test25(
1845; CHECK-NEXT:  entry:
1846; CHECK-NEXT:    [[CMP_ENTRY:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1847; CHECK-NEXT:    br i1 [[CMP_ENTRY]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1848; CHECK:       for.body.preheader:
1849; CHECK-NEXT:    br label [[FOR_BODY_PEEL_BEGIN:%.*]]
1850; CHECK:       for.body.peel.begin:
1851; CHECK-NEXT:    br label [[FOR_BODY_PEEL:%.*]]
1852; CHECK:       for.body.peel:
1853; CHECK-NEXT:    [[REM1_PEEL:%.*]] = and i32 0, 1
1854; CHECK-NEXT:    [[REM2_PEEL:%.*]] = srem i32 0, 3
1855; CHECK-NEXT:    [[REM3_PEEL:%.*]] = srem i32 0, 7
1856; CHECK-NEXT:    [[REM4_PEEL:%.*]] = srem i32 0, 11
1857; CHECK-NEXT:    [[CMP1_PEEL:%.*]] = icmp ult i32 0, 3
1858; CHECK-NEXT:    [[CMP2_PEEL:%.*]] = icmp eq i32 [[REM1_PEEL]], 0
1859; CHECK-NEXT:    [[CMP3_PEEL:%.*]] = icmp eq i32 [[REM2_PEEL]], 0
1860; CHECK-NEXT:    [[CMP4_PEEL:%.*]] = icmp eq i32 [[REM3_PEEL]], 0
1861; CHECK-NEXT:    [[CMP5_PEEL:%.*]] = icmp eq i32 [[REM4_PEEL]], 0
1862; CHECK-NEXT:    [[OR_COND1_PEEL:%.*]] = or i1 [[CMP1_PEEL]], [[CMP2_PEEL]]
1863; CHECK-NEXT:    [[OR_COND2_PEEL:%.*]] = or i1 [[OR_COND1_PEEL]], [[CMP3_PEEL]]
1864; CHECK-NEXT:    [[OR_COND3_PEEL:%.*]] = or i1 [[OR_COND2_PEEL]], [[CMP4_PEEL]]
1865; CHECK-NEXT:    [[OR_COND4_PEEL:%.*]] = or i1 [[OR_COND3_PEEL]], [[CMP5_PEEL]]
1866; CHECK-NEXT:    br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_END_PEEL:%.*]]
1867; CHECK:       if.then.peel:
1868; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A:%.*]])
1869; CHECK-NEXT:    br label [[IF_END_PEEL]]
1870; CHECK:       if.end.peel:
1871; CHECK-NEXT:    tail call void (...) @f2()
1872; CHECK-NEXT:    [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1
1873; CHECK-NEXT:    [[EXITCOND_NOT_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], [[NUM]]
1874; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]]
1875; CHECK:       for.body.peel.next:
1876; CHECK-NEXT:    br label [[FOR_BODY_PEEL2:%.*]]
1877; CHECK:       for.body.peel2:
1878; CHECK-NEXT:    [[REM1_PEEL3:%.*]] = and i32 [[INC_PEEL]], 1
1879; CHECK-NEXT:    [[REM2_PEEL4:%.*]] = srem i32 [[INC_PEEL]], 3
1880; CHECK-NEXT:    [[REM3_PEEL5:%.*]] = srem i32 [[INC_PEEL]], 7
1881; CHECK-NEXT:    [[REM4_PEEL6:%.*]] = srem i32 [[INC_PEEL]], 11
1882; CHECK-NEXT:    [[CMP1_PEEL7:%.*]] = icmp ult i32 [[INC_PEEL]], 3
1883; CHECK-NEXT:    [[CMP2_PEEL8:%.*]] = icmp eq i32 [[REM1_PEEL3]], 0
1884; CHECK-NEXT:    [[CMP3_PEEL9:%.*]] = icmp eq i32 [[REM2_PEEL4]], 0
1885; CHECK-NEXT:    [[CMP4_PEEL10:%.*]] = icmp eq i32 [[REM3_PEEL5]], 0
1886; CHECK-NEXT:    [[CMP5_PEEL11:%.*]] = icmp eq i32 [[REM4_PEEL6]], 0
1887; CHECK-NEXT:    [[OR_COND1_PEEL12:%.*]] = or i1 [[CMP1_PEEL7]], [[CMP2_PEEL8]]
1888; CHECK-NEXT:    [[OR_COND2_PEEL13:%.*]] = or i1 [[OR_COND1_PEEL12]], [[CMP3_PEEL9]]
1889; CHECK-NEXT:    [[OR_COND3_PEEL14:%.*]] = or i1 [[OR_COND2_PEEL13]], [[CMP4_PEEL10]]
1890; CHECK-NEXT:    [[OR_COND4_PEEL15:%.*]] = or i1 [[OR_COND3_PEEL14]], [[CMP5_PEEL11]]
1891; CHECK-NEXT:    br i1 [[CMP1_PEEL7]], label [[IF_THEN_PEEL16:%.*]], label [[IF_END_PEEL17:%.*]]
1892; CHECK:       if.then.peel16:
1893; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1894; CHECK-NEXT:    br label [[IF_END_PEEL17]]
1895; CHECK:       if.end.peel17:
1896; CHECK-NEXT:    tail call void (...) @f2()
1897; CHECK-NEXT:    [[INC_PEEL18:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1
1898; CHECK-NEXT:    [[EXITCOND_NOT_PEEL19:%.*]] = icmp eq i32 [[INC_PEEL18]], [[NUM]]
1899; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL19]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT1:%.*]]
1900; CHECK:       for.body.peel.next1:
1901; CHECK-NEXT:    br label [[FOR_BODY_PEEL21:%.*]]
1902; CHECK:       for.body.peel21:
1903; CHECK-NEXT:    [[REM1_PEEL22:%.*]] = and i32 [[INC_PEEL18]], 1
1904; CHECK-NEXT:    [[REM2_PEEL23:%.*]] = srem i32 [[INC_PEEL18]], 3
1905; CHECK-NEXT:    [[REM3_PEEL24:%.*]] = srem i32 [[INC_PEEL18]], 7
1906; CHECK-NEXT:    [[REM4_PEEL25:%.*]] = srem i32 [[INC_PEEL18]], 11
1907; CHECK-NEXT:    [[CMP1_PEEL26:%.*]] = icmp ult i32 [[INC_PEEL18]], 3
1908; CHECK-NEXT:    [[CMP2_PEEL27:%.*]] = icmp eq i32 [[REM1_PEEL22]], 0
1909; CHECK-NEXT:    [[CMP3_PEEL28:%.*]] = icmp eq i32 [[REM2_PEEL23]], 0
1910; CHECK-NEXT:    [[CMP4_PEEL29:%.*]] = icmp eq i32 [[REM3_PEEL24]], 0
1911; CHECK-NEXT:    [[CMP5_PEEL30:%.*]] = icmp eq i32 [[REM4_PEEL25]], 0
1912; CHECK-NEXT:    [[OR_COND1_PEEL31:%.*]] = or i1 [[CMP1_PEEL26]], [[CMP2_PEEL27]]
1913; CHECK-NEXT:    [[OR_COND2_PEEL32:%.*]] = or i1 [[OR_COND1_PEEL31]], [[CMP3_PEEL28]]
1914; CHECK-NEXT:    [[OR_COND3_PEEL33:%.*]] = or i1 [[OR_COND2_PEEL32]], [[CMP4_PEEL29]]
1915; CHECK-NEXT:    [[OR_COND4_PEEL34:%.*]] = or i1 [[OR_COND3_PEEL33]], [[CMP5_PEEL30]]
1916; CHECK-NEXT:    br i1 [[CMP1_PEEL26]], label [[IF_THEN_PEEL35:%.*]], label [[IF_END_PEEL36:%.*]]
1917; CHECK:       if.then.peel35:
1918; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1919; CHECK-NEXT:    br label [[IF_END_PEEL36]]
1920; CHECK:       if.end.peel36:
1921; CHECK-NEXT:    tail call void (...) @f2()
1922; CHECK-NEXT:    [[INC_PEEL37:%.*]] = add nuw nsw i32 [[INC_PEEL18]], 1
1923; CHECK-NEXT:    [[EXITCOND_NOT_PEEL38:%.*]] = icmp eq i32 [[INC_PEEL37]], [[NUM]]
1924; CHECK-NEXT:    br i1 [[EXITCOND_NOT_PEEL38]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY_PEEL_NEXT20:%.*]]
1925; CHECK:       for.body.peel.next20:
1926; CHECK-NEXT:    br label [[FOR_BODY_PEEL_NEXT39:%.*]]
1927; CHECK:       for.body.peel.next39:
1928; CHECK-NEXT:    br label [[FOR_BODY_PREHEADER_PEEL_NEWPH:%.*]]
1929; CHECK:       for.body.preheader.peel.newph:
1930; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1931; CHECK:       for.cond.cleanup.loopexit.loopexit:
1932; CHECK-NEXT:    br label [[FOR_COND_CLEANUP_LOOPEXIT]]
1933; CHECK:       for.cond.cleanup.loopexit:
1934; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1935; CHECK:       for.cond.cleanup:
1936; CHECK-NEXT:    ret void
1937; CHECK:       for.body:
1938; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ [[INC_PEEL37]], [[FOR_BODY_PREHEADER_PEEL_NEWPH]] ]
1939; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END]]
1940; CHECK:       if.then:
1941; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A]])
1942; CHECK-NEXT:    br label [[IF_END]]
1943; CHECK:       if.end:
1944; CHECK-NEXT:    tail call void (...) @f2()
1945; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
1946; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
1947; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP22:![0-9]+]]
1948;
1949entry:
1950  %cmp_entry = icmp sgt i32 %num, 0
1951  br i1 %cmp_entry, label %for.body, label %for.cond.cleanup
1952
1953for.cond.cleanup:                                 ; preds = %if.end, %entry
1954  ret void
1955
1956for.body:                                         ; preds = %entry, %if.end
1957  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
1958  %rem1 = and i32 %i.08, 1
1959  %rem2 = srem i32 %i.08, 3
1960  %rem3 = srem i32 %i.08, 7
1961  %rem4 = srem i32 %i.08, 11
1962  %cmp1 = icmp ult i32 %i.08, 3
1963  %cmp2 = icmp eq i32 %rem1, 0
1964  %cmp3 = icmp eq i32 %rem2, 0
1965  %cmp4 = icmp eq i32 %rem3, 0
1966  %cmp5 = icmp eq i32 %rem4, 0
1967  %or.cond1 = or i1 %cmp1, %cmp2
1968  %or.cond2 = or i1 %or.cond1, %cmp3
1969  %or.cond3 = or i1 %or.cond2, %cmp4
1970  %or.cond4 = or i1 %or.cond3, %cmp5
1971  br i1 %cmp1, label %if.then, label %if.end
1972
1973if.then:                                          ; preds = %for.body
1974  tail call void (i32, ...) @f1(i32 %a)
1975  br label %if.end
1976
1977if.end:                                           ; preds = %for.body, %if.then
1978  tail call void (...) @f2()
1979  %inc = add nuw nsw i32 %i.08, 1
1980  %exitcond.not = icmp eq i32 %inc, %num
1981  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
1982}
1983
1984; Test peeling past the recursion limit of 4
1985define void @test26(i32 %num, i32 %a, i32 %b) {
1986; CHECK-LABEL: @test26(
1987; CHECK-NEXT:  entry:
1988; CHECK-NEXT:    [[CMP_ENTRY:%.*]] = icmp sgt i32 [[NUM:%.*]], 0
1989; CHECK-NEXT:    br i1 [[CMP_ENTRY]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1990; CHECK:       for.body.preheader:
1991; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
1992; CHECK:       for.cond.cleanup.loopexit:
1993; CHECK-NEXT:    br label [[FOR_COND_CLEANUP]]
1994; CHECK:       for.cond.cleanup:
1995; CHECK-NEXT:    ret void
1996; CHECK:       for.body:
1997; CHECK-NEXT:    [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[IF_END:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
1998; CHECK-NEXT:    [[REM1:%.*]] = and i32 [[I_08]], 1
1999; CHECK-NEXT:    [[REM2:%.*]] = srem i32 [[I_08]], 3
2000; CHECK-NEXT:    [[REM3:%.*]] = srem i32 [[I_08]], 7
2001; CHECK-NEXT:    [[REM4:%.*]] = srem i32 [[I_08]], 11
2002; CHECK-NEXT:    [[REM5:%.*]] = srem i32 [[I_08]], 13
2003; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[I_08]], 3
2004; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[REM1]], 0
2005; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[REM2]], 0
2006; CHECK-NEXT:    [[CMP4:%.*]] = icmp eq i32 [[REM3]], 0
2007; CHECK-NEXT:    [[CMP5:%.*]] = icmp eq i32 [[REM4]], 0
2008; CHECK-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[REM5]], 0
2009; CHECK-NEXT:    [[OR_COND1:%.*]] = or i1 [[CMP1]], [[CMP2]]
2010; CHECK-NEXT:    [[OR_COND2:%.*]] = or i1 [[OR_COND1]], [[CMP3]]
2011; CHECK-NEXT:    [[OR_COND3:%.*]] = or i1 [[OR_COND2]], [[CMP4]]
2012; CHECK-NEXT:    [[OR_COND4:%.*]] = or i1 [[OR_COND3]], [[CMP5]]
2013; CHECK-NEXT:    [[OR_COND5:%.*]] = or i1 [[OR_COND4]], [[CMP6]]
2014; CHECK-NEXT:    br i1 [[OR_COND5]], label [[IF_THEN:%.*]], label [[IF_END]]
2015; CHECK:       if.then:
2016; CHECK-NEXT:    tail call void (i32, ...) @f1(i32 [[A:%.*]])
2017; CHECK-NEXT:    br label [[IF_END]]
2018; CHECK:       if.end:
2019; CHECK-NEXT:    tail call void (...) @f2()
2020; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[I_08]], 1
2021; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]]
2022; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]]
2023;
2024entry:
2025  %cmp_entry = icmp sgt i32 %num, 0
2026  br i1 %cmp_entry, label %for.body, label %for.cond.cleanup
2027
2028for.cond.cleanup:                                 ; preds = %if.end, %entry
2029  ret void
2030
2031for.body:                                         ; preds = %entry, %if.end
2032  %i.08 = phi i32 [ %inc, %if.end ], [ 0, %entry ]
2033  %rem1 = and i32 %i.08, 1
2034  %rem2 = srem i32 %i.08, 3
2035  %rem3 = srem i32 %i.08, 7
2036  %rem4 = srem i32 %i.08, 11
2037  %rem5 = srem i32 %i.08, 13
2038  %cmp1 = icmp ult i32 %i.08, 3
2039  %cmp2 = icmp eq i32 %rem1, 0
2040  %cmp3 = icmp eq i32 %rem2, 0
2041  %cmp4 = icmp eq i32 %rem3, 0
2042  %cmp5 = icmp eq i32 %rem4, 0
2043  %cmp6 = icmp eq i32 %rem5, 0
2044  %or.cond1 = or i1 %cmp1, %cmp2
2045  %or.cond2 = or i1 %or.cond1, %cmp3
2046  %or.cond3 = or i1 %or.cond2, %cmp4
2047  %or.cond4 = or i1 %or.cond3, %cmp5
2048  %or.cond5 = or i1 %or.cond4, %cmp6
2049  br i1 %or.cond5, label %if.then, label %if.end
2050
2051if.then:                                          ; preds = %for.body
2052  tail call void (i32, ...) @f1(i32 %a)
2053  br label %if.end
2054
2055if.end:                                           ; preds = %for.body, %if.then
2056  tail call void (...) @f2()
2057  %inc = add nuw nsw i32 %i.08, 1
2058  %exitcond.not = icmp eq i32 %inc, %num
2059  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
2060}
2061
2062declare void @init()
2063declare void @sink()
2064