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