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