1026 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 42; REQUIRES: asserts3; RUN: opt -S -passes=licm -ipt-expensive-asserts=true < %s | FileCheck %s4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6 7declare void @f() nounwind8declare void @llvm.experimental.guard(i1,...)9 10; constant fold on first ieration11define i32 @test1(ptr noalias nocapture readonly %a) nounwind uwtable {12; CHECK-LABEL: define i32 @test1(13; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1:[0-9]+]] {14; CHECK-NEXT: entry:15; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 416; CHECK-NEXT: br label [[FOR_BODY:%.*]]17; CHECK: for.body:18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]19; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]20; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 200021; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]]22; CHECK: continue:23; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]24; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 125; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 100026; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]27; CHECK: for.cond.cleanup:28; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]29; CHECK-NEXT: ret i32 [[ADD_LCSSA]]30; CHECK: fail:31; CHECK-NEXT: call void @f()32; CHECK-NEXT: ret i32 -133;34entry:35 br label %for.body36 37for.body:38 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]39 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]40 %r.chk = icmp ult i32 %iv, 200041 br i1 %r.chk, label %continue, label %fail42continue:43 %i1 = load i32, ptr %a, align 444 %add = add nsw i32 %i1, %acc45 %inc = add nuw nsw i32 %iv, 146 %exitcond = icmp eq i32 %inc, 100047 br i1 %exitcond, label %for.cond.cleanup, label %for.body48 49for.cond.cleanup:50 ret i32 %add51 52fail:53 call void @f()54 ret i32 -155}56 57; Same as test1, but with a floating point IR and fcmp58define i32 @test_fcmp(ptr noalias nocapture readonly %a) nounwind uwtable {59; CHECK-LABEL: define i32 @test_fcmp(60; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {61; CHECK-NEXT: entry:62; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 463; CHECK-NEXT: br label [[FOR_BODY:%.*]]64; CHECK: for.body:65; CHECK-NEXT: [[IV:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]66; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]67; CHECK-NEXT: [[R_CHK:%.*]] = fcmp olt float [[IV]], 2.000000e+0368; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]]69; CHECK: continue:70; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]71; CHECK-NEXT: [[INC]] = fadd float [[IV]], 1.000000e+0072; CHECK-NEXT: [[EXITCOND:%.*]] = fcmp ogt float [[INC]], 1.000000e+0373; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]74; CHECK: for.cond.cleanup:75; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]76; CHECK-NEXT: ret i32 [[ADD_LCSSA]]77; CHECK: fail:78; CHECK-NEXT: call void @f()79; CHECK-NEXT: ret i32 -180;81entry:82 br label %for.body83 84for.body:85 %iv = phi float [ 0.0, %entry ], [ %inc, %continue ]86 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]87 %r.chk = fcmp olt float %iv, 2000.088 br i1 %r.chk, label %continue, label %fail89continue:90 %i1 = load i32, ptr %a, align 491 %add = add nsw i32 %i1, %acc92 %inc = fadd float %iv, 1.093 %exitcond = fcmp ogt float %inc, 1000.094 br i1 %exitcond, label %for.cond.cleanup, label %for.body95 96for.cond.cleanup:97 ret i32 %add98 99fail:100 call void @f()101 ret i32 -1102}103 104; Count down from a.length w/entry guard105; TODO: currently unable to prove the following:106; ule i32 (add nsw i32 %len, -1), %len where len is [0, 512]107define i32 @test2(ptr noalias nocapture readonly %a) nounwind uwtable {108; CHECK-LABEL: define i32 @test2(109; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {110; CHECK-NEXT: entry:111; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0:![0-9]+]]112; CHECK-NEXT: [[IS_NON_POS:%.*]] = icmp eq i32 [[LEN]], 0113; CHECK-NEXT: br i1 [[IS_NON_POS]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]114; CHECK: preheader:115; CHECK-NEXT: [[LENMINUSONE:%.*]] = add nsw i32 [[LEN]], -1116; CHECK-NEXT: br label [[FOR_BODY:%.*]]117; CHECK: for.body:118; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LENMINUSONE]], [[PREHEADER]] ], [ [[DEC:%.*]], [[CONTINUE:%.*]] ]119; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]120; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]]121; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]122; CHECK: continue:123; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4124; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]125; CHECK-NEXT: [[DEC]] = add nsw i32 [[IV]], -1126; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[DEC]], 0127; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]128; CHECK: for.cond.cleanup:129; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]130; CHECK-NEXT: ret i32 [[ADD_LCSSA]]131; CHECK: fail.loopexit:132; CHECK-NEXT: br label [[FAIL]]133; CHECK: fail:134; CHECK-NEXT: call void @f()135; CHECK-NEXT: ret i32 -1136;137entry:138 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}139 %is.non.pos = icmp eq i32 %len, 0140 br i1 %is.non.pos, label %fail, label %preheader141preheader:142 %lenminusone = add nsw i32 %len, -1143 br label %for.body144for.body:145 %iv = phi i32 [ %lenminusone, %preheader ], [ %dec, %continue ]146 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]147 %r.chk = icmp ule i32 %iv, %len148 br i1 %r.chk, label %continue, label %fail149continue:150 %i1 = load i32, ptr %a, align 4151 %add = add nsw i32 %i1, %acc152 %dec = add nsw i32 %iv, -1153 %exitcond = icmp eq i32 %dec, 0154 br i1 %exitcond, label %for.cond.cleanup, label %for.body155 156for.cond.cleanup:157 ret i32 %add158 159fail:160 call void @f()161 ret i32 -1162}163 164; trivially true for zero165define i32 @test3(ptr noalias nocapture readonly %a) nounwind uwtable {166; CHECK-LABEL: define i32 @test3(167; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {168; CHECK-NEXT: entry:169; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]170; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0171; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]172; CHECK: preheader:173; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4174; CHECK-NEXT: br label [[FOR_BODY:%.*]]175; CHECK: for.body:176; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]177; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]178; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]]179; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]180; CHECK: continue:181; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]182; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1183; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000184; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]185; CHECK: for.cond.cleanup:186; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]187; CHECK-NEXT: ret i32 [[ADD_LCSSA]]188; CHECK: fail.loopexit:189; CHECK-NEXT: br label [[FAIL]]190; CHECK: fail:191; CHECK-NEXT: call void @f()192; CHECK-NEXT: ret i32 -1193;194entry:195 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}196 %is.zero = icmp eq i32 %len, 0197 br i1 %is.zero, label %fail, label %preheader198preheader:199 br label %for.body200for.body:201 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]202 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]203 %r.chk = icmp ule i32 %iv, %len204 br i1 %r.chk, label %continue, label %fail205continue:206 %i1 = load i32, ptr %a, align 4207 %add = add nsw i32 %i1, %acc208 %inc = add nuw nsw i32 %iv, 1209 %exitcond = icmp eq i32 %inc, 1000210 br i1 %exitcond, label %for.cond.cleanup, label %for.body211 212for.cond.cleanup:213 ret i32 %add214 215fail:216 call void @f()217 ret i32 -1218}219 220; Same as previous case, with commuted icmp.221define i32 @test3_commuted(ptr noalias nocapture readonly %a) nounwind uwtable {222; CHECK-LABEL: define i32 @test3_commuted(223; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {224; CHECK-NEXT: entry:225; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]226; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0227; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]228; CHECK: preheader:229; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4230; CHECK-NEXT: br label [[FOR_BODY:%.*]]231; CHECK: for.body:232; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]233; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]234; CHECK-NEXT: [[R_CHK:%.*]] = icmp uge i32 [[LEN]], [[IV]]235; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]236; CHECK: continue:237; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]238; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1239; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000240; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]241; CHECK: for.cond.cleanup:242; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]243; CHECK-NEXT: ret i32 [[ADD_LCSSA]]244; CHECK: fail.loopexit:245; CHECK-NEXT: br label [[FAIL]]246; CHECK: fail:247; CHECK-NEXT: call void @f()248; CHECK-NEXT: ret i32 -1249;250entry:251 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}252 %is.zero = icmp eq i32 %len, 0253 br i1 %is.zero, label %fail, label %preheader254preheader:255 br label %for.body256for.body:257 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]258 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]259 %r.chk = icmp uge i32 %len, %iv260 br i1 %r.chk, label %continue, label %fail261continue:262 %i1 = load i32, ptr %a, align 4263 %add = add nsw i32 %i1, %acc264 %inc = add nuw nsw i32 %iv, 1265 %exitcond = icmp eq i32 %inc, 1000266 br i1 %exitcond, label %for.cond.cleanup, label %for.body267 268for.cond.cleanup:269 ret i32 %add270 271fail:272 call void @f()273 ret i32 -1274}275 276; requires fact length is non-zero277define i32 @test4(ptr noalias nocapture readonly %a) nounwind uwtable {278; CHECK-LABEL: define i32 @test4(279; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {280; CHECK-NEXT: entry:281; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]282; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0283; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]284; CHECK: preheader:285; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4286; CHECK-NEXT: br label [[FOR_BODY:%.*]]287; CHECK: for.body:288; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]289; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]290; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], [[LEN]]291; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]292; CHECK: continue:293; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]294; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1295; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000296; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]297; CHECK: for.cond.cleanup:298; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]299; CHECK-NEXT: ret i32 [[ADD_LCSSA]]300; CHECK: fail.loopexit:301; CHECK-NEXT: br label [[FAIL]]302; CHECK: fail:303; CHECK-NEXT: call void @f()304; CHECK-NEXT: ret i32 -1305;306entry:307 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}308 %is.zero = icmp eq i32 %len, 0309 br i1 %is.zero, label %fail, label %preheader310preheader:311 br label %for.body312for.body:313 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]314 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]315 %r.chk = icmp ult i32 %iv, %len316 br i1 %r.chk, label %continue, label %fail317continue:318 %i1 = load i32, ptr %a, align 4319 %add = add nsw i32 %i1, %acc320 %inc = add nuw nsw i32 %iv, 1321 %exitcond = icmp eq i32 %inc, 1000322 br i1 %exitcond, label %for.cond.cleanup, label %for.body323 324for.cond.cleanup:325 ret i32 %add326 327fail:328 call void @f()329 ret i32 -1330}331 332; variation on test1 with branch swapped333define i32 @test-brswap(ptr noalias nocapture readonly %a) nounwind uwtable {334; CHECK-LABEL: define i32 @test-brswap(335; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {336; CHECK-NEXT: entry:337; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4338; CHECK-NEXT: br label [[FOR_BODY:%.*]]339; CHECK: for.body:340; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]341; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]342; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[IV]], 2000343; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]344; CHECK: continue:345; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]346; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1347; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000348; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]349; CHECK: for.cond.cleanup:350; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]351; CHECK-NEXT: ret i32 [[ADD_LCSSA]]352; CHECK: fail:353; CHECK-NEXT: call void @f()354; CHECK-NEXT: ret i32 -1355;356entry:357 br label %for.body358 359for.body:360 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]361 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]362 %r.chk = icmp ugt i32 %iv, 2000363 br i1 %r.chk, label %fail, label %continue364continue:365 %i1 = load i32, ptr %a, align 4366 %add = add nsw i32 %i1, %acc367 %inc = add nuw nsw i32 %iv, 1368 %exitcond = icmp eq i32 %inc, 1000369 br i1 %exitcond, label %for.cond.cleanup, label %for.body370 371for.cond.cleanup:372 ret i32 %add373 374fail:375 call void @f()376 ret i32 -1377}378 379define i32 @test-nonphi(ptr noalias nocapture readonly %a) nounwind uwtable {380; CHECK-LABEL: define i32 @test-nonphi(381; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {382; CHECK-NEXT: entry:383; CHECK-NEXT: br label [[FOR_BODY:%.*]]384; CHECK: for.body:385; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]386; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]387; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[IV]], 72388; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[XOR]], 2000389; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]390; CHECK: continue:391; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4392; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]393; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1394; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000395; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]396; CHECK: for.cond.cleanup:397; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]398; CHECK-NEXT: ret i32 [[ADD_LCSSA]]399; CHECK: fail:400; CHECK-NEXT: call void @f()401; CHECK-NEXT: ret i32 -1402;403entry:404 br label %for.body405 406for.body:407 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]408 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]409 %xor = xor i32 %iv, 72410 %r.chk = icmp ugt i32 %xor, 2000411 br i1 %r.chk, label %fail, label %continue412continue:413 %i1 = load i32, ptr %a, align 4414 %add = add nsw i32 %i1, %acc415 %inc = add nuw nsw i32 %iv, 1416 %exitcond = icmp eq i32 %inc, 1000417 br i1 %exitcond, label %for.cond.cleanup, label %for.body418 419for.cond.cleanup:420 ret i32 %add421 422fail:423 call void @f()424 ret i32 -1425}426 427define i32 @test-wrongphi(ptr noalias nocapture readonly %a) nounwind uwtable {428; CHECK-LABEL: define i32 @test-wrongphi(429; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {430; CHECK-NEXT: entry:431; CHECK-NEXT: br label [[FOR_BODY:%.*]]432; CHECK: for.body:433; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]434; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]435; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[IV]], 500436; CHECK-NEXT: br i1 [[COND]], label [[DUMMY_BLOCK1:%.*]], label [[DUMMY_BLOCK2:%.*]]437; CHECK: dummy_block1:438; CHECK-NEXT: br label [[DUMMY_BLOCK2]]439; CHECK: dummy_block2:440; CHECK-NEXT: [[WRONGPHI:%.*]] = phi i32 [ 11, [[FOR_BODY]] ], [ 12, [[DUMMY_BLOCK1]] ]441; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[WRONGPHI]], 2000442; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]443; CHECK: continue:444; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4445; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]446; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1447; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000448; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]449; CHECK: for.cond.cleanup:450; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]451; CHECK-NEXT: ret i32 [[ADD_LCSSA]]452; CHECK: fail:453; CHECK-NEXT: call void @f()454; CHECK-NEXT: ret i32 -1455;456entry:457 br label %for.body458 459for.body:460 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]461 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]462 %cond = icmp ult i32 %iv, 500463 br i1 %cond, label %dummy_block1, label %dummy_block2464 465dummy_block1:466 br label %dummy_block2467 468dummy_block2:469 %wrongphi = phi i32 [11, %for.body], [12, %dummy_block1]470 %r.chk = icmp ugt i32 %wrongphi, 2000471 br i1 %r.chk, label %fail, label %continue472continue:473 %i1 = load i32, ptr %a, align 4474 %add = add nsw i32 %i1, %acc475 %inc = add nuw nsw i32 %iv, 1476 %exitcond = icmp eq i32 %inc, 1000477 br i1 %exitcond, label %for.cond.cleanup, label %for.body478 479for.cond.cleanup:480 ret i32 %add481 482fail:483 call void @f()484 ret i32 -1485}486 487; This works because loop-simplify is run implicitly, but test for it anyways488define i32 @test-multiple-latch(ptr noalias nocapture readonly %a) nounwind uwtable {489; CHECK-LABEL: define i32 @test-multiple-latch(490; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {491; CHECK-NEXT: entry:492; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4493; CHECK-NEXT: br label [[FOR_BODY:%.*]]494; CHECK: for.body:495; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]496; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY_BACKEDGE]] ]497; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 2000498; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE1:%.*]], label [[FAIL:%.*]]499; CHECK: continue1:500; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]501; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1502; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], 0503; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE2:%.*]], label [[FOR_BODY_BACKEDGE]]504; CHECK: for.body.backedge:505; CHECK-NEXT: br label [[FOR_BODY]]506; CHECK: continue2:507; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000508; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_BACKEDGE]]509; CHECK: for.cond.cleanup:510; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE2]] ]511; CHECK-NEXT: ret i32 [[ADD_LCSSA]]512; CHECK: fail:513; CHECK-NEXT: call void @f()514; CHECK-NEXT: ret i32 -1515;516entry:517 br label %for.body518 519for.body:520 %iv = phi i32 [ 0, %entry ], [ %inc, %continue1 ], [ %inc, %continue2 ]521 %acc = phi i32 [ 0, %entry ], [ %add, %continue1 ], [ %add, %continue2 ]522 %r.chk = icmp ult i32 %iv, 2000523 br i1 %r.chk, label %continue1, label %fail524continue1:525 %i1 = load i32, ptr %a, align 4526 %add = add nsw i32 %i1, %acc527 %inc = add nuw nsw i32 %iv, 1528 %cmp = icmp eq i32 %add, 0529 br i1 %cmp, label %continue2, label %for.body530continue2:531 %exitcond = icmp eq i32 %inc, 1000532 br i1 %exitcond, label %for.cond.cleanup, label %for.body533 534for.cond.cleanup:535 ret i32 %add536 537fail:538 call void @f()539 ret i32 -1540}541 542define void @test-hoisting-in-presence-of-guards(i1 %c, ptr %p) {543; CHECK-LABEL: define void @test-hoisting-in-presence-of-guards(544; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {545; CHECK-NEXT: entry:546; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4547; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100548; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]549; CHECK-NEXT: br label [[LOOP:%.*]]550; CHECK: loop:551; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]552; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1553; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000554; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]555; CHECK: exit:556; CHECK-NEXT: ret void557;558 559entry:560 br label %loop561 562loop:563 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]564 %iv.next = add i32 %iv, 1565 %a = load i32, ptr %p566 %invariant_cond = icmp ne i32 %a, 100567 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]568 %loop_cond = icmp slt i32 %iv.next, 1000569 br i1 %loop_cond, label %loop, label %exit570 571exit:572 ret void573}574 575 576declare void @may_throw() inaccessiblememonly577 578; Test that we can sink a mustexecute load from loop header even in presence of579; throwing instructions after it.580define void @test_hoist_from_header_01(ptr %p, i32 %n) {581; CHECK-LABEL: define void @test_hoist_from_header_01(582; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {583; CHECK-NEXT: entry:584; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4585; CHECK-NEXT: br label [[LOOP:%.*]]586; CHECK: loop:587; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]588; CHECK-NEXT: call void @may_throw()589; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]590; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]591; CHECK: if.true:592; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]593; CHECK-NEXT: br label [[BACKEDGE]]594; CHECK: if.false:595; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]596; CHECK-NEXT: br label [[BACKEDGE]]597; CHECK: backedge:598; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]599; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]600; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]601; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]602; CHECK: exit:603; CHECK-NEXT: ret void604;605 606entry:607 br label %loop608 609loop:610 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]611 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]612 %load = load i32, ptr %p613 call void @may_throw()614 %cond = icmp slt i32 %iv, %n615 br i1 %cond, label %if.true, label %if.false616 617if.true:618 %a = add i32 %iv, %iv619 br label %backedge620 621if.false:622 %b = mul i32 %iv, %iv623 br label %backedge624 625backedge:626 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]627 %iv.next = add i32 %iv, %merge628 %loop.cond = icmp ult i32 %iv.next, %load629 br i1 %loop.cond, label %loop, label %exit630 631exit:632 ret void633}634 635define void @test_hoist_from_header_02(ptr %p, i32 %n) {636; CHECK-LABEL: define void @test_hoist_from_header_02(637; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {638; CHECK-NEXT: entry:639; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4640; CHECK-NEXT: br label [[LOOP:%.*]]641; CHECK: loop:642; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]643; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]644; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]645; CHECK: if.true:646; CHECK-NEXT: call void @may_throw()647; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]648; CHECK-NEXT: br label [[BACKEDGE]]649; CHECK: if.false:650; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]651; CHECK-NEXT: br label [[BACKEDGE]]652; CHECK: backedge:653; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]654; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]655; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]656; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]657; CHECK: exit:658; CHECK-NEXT: ret void659;660 661entry:662 br label %loop663 664loop:665 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]666 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]667 %load = load i32, ptr %p668 %cond = icmp slt i32 %iv, %n669 br i1 %cond, label %if.true, label %if.false670 671if.true:672 call void @may_throw()673 %a = add i32 %iv, %iv674 br label %backedge675 676if.false:677 %b = mul i32 %iv, %iv678 br label %backedge679 680backedge:681 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]682 %iv.next = add i32 %iv, %merge683 %loop.cond = icmp ult i32 %iv.next, %load684 br i1 %loop.cond, label %loop, label %exit685 686exit:687 ret void688}689 690define void @test_hoist_from_header_03(ptr %p, i32 %n) {691; CHECK-LABEL: define void @test_hoist_from_header_03(692; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {693; CHECK-NEXT: entry:694; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4695; CHECK-NEXT: br label [[LOOP:%.*]]696; CHECK: loop:697; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]698; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]699; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]700; CHECK: if.true:701; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]702; CHECK-NEXT: br label [[BACKEDGE]]703; CHECK: if.false:704; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]705; CHECK-NEXT: br label [[BACKEDGE]]706; CHECK: backedge:707; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]708; CHECK-NEXT: call void @may_throw()709; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]710; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]711; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]712; CHECK: exit:713; CHECK-NEXT: ret void714;715 716entry:717 br label %loop718 719loop:720 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]721 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]722 %load = load i32, ptr %p723 %cond = icmp slt i32 %iv, %n724 br i1 %cond, label %if.true, label %if.false725 726if.true:727 %a = add i32 %iv, %iv728 br label %backedge729 730if.false:731 %b = mul i32 %iv, %iv732 br label %backedge733 734backedge:735 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]736 call void @may_throw()737 %iv.next = add i32 %iv, %merge738 %loop.cond = icmp ult i32 %iv.next, %load739 br i1 %loop.cond, label %loop, label %exit740 741exit:742 ret void743}744 745; Check that a throwing instruction prohibits hoisting across it.746define void @test_hoist_from_header_04(ptr %p, i32 %n) {747; CHECK-LABEL: define void @test_hoist_from_header_04(748; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {749; CHECK-NEXT: entry:750; CHECK-NEXT: br label [[LOOP:%.*]]751; CHECK: loop:752; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]753; CHECK-NEXT: call void @may_throw()754; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4755; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]756; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]757; CHECK: if.true:758; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]759; CHECK-NEXT: br label [[BACKEDGE]]760; CHECK: if.false:761; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]762; CHECK-NEXT: br label [[BACKEDGE]]763; CHECK: backedge:764; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]765; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]766; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]767; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]768; CHECK: exit:769; CHECK-NEXT: ret void770;771 772entry:773 br label %loop774 775loop:776 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]777 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]778 call void @may_throw()779 %load = load i32, ptr %p780 %cond = icmp slt i32 %iv, %n781 br i1 %cond, label %if.true, label %if.false782 783if.true:784 %a = add i32 %iv, %iv785 br label %backedge786 787if.false:788 %b = mul i32 %iv, %iv789 br label %backedge790 791backedge:792 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]793 %iv.next = add i32 %iv, %merge794 %loop.cond = icmp ult i32 %iv.next, %load795 br i1 %loop.cond, label %loop, label %exit796 797exit:798 ret void799}800 801; Check that we can hoist a mustexecute load from backedge even if something802; throws after it.803define void @test_hoist_from_backedge_01(ptr %p, i32 %n) {804; CHECK-LABEL: define void @test_hoist_from_backedge_01(805; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {806; CHECK-NEXT: entry:807; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4808; CHECK-NEXT: br label [[LOOP:%.*]]809; CHECK: loop:810; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]811; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]812; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]813; CHECK: if.true:814; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]815; CHECK-NEXT: br label [[BACKEDGE]]816; CHECK: if.false:817; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]818; CHECK-NEXT: br label [[BACKEDGE]]819; CHECK: backedge:820; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]821; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]822; CHECK-NEXT: call void @may_throw()823; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]824; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]825; CHECK: exit:826; CHECK-NEXT: ret void827;828 829entry:830 br label %loop831 832loop:833 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]834 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]835 %cond = icmp slt i32 %iv, %n836 br i1 %cond, label %if.true, label %if.false837 838if.true:839 %a = add i32 %iv, %iv840 br label %backedge841 842if.false:843 %b = mul i32 %iv, %iv844 br label %backedge845 846backedge:847 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]848 %iv.next = add i32 %iv, %merge849 %load = load i32, ptr %p850 call void @may_throw()851 %loop.cond = icmp ult i32 %iv.next, %load852 br i1 %loop.cond, label %loop, label %exit853 854exit:855 ret void856}857 858; Check that we don't hoist the load if something before it can throw.859define void @test_hoist_from_backedge_02(ptr %p, i32 %n) {860; CHECK-LABEL: define void @test_hoist_from_backedge_02(861; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {862; CHECK-NEXT: entry:863; CHECK-NEXT: br label [[LOOP:%.*]]864; CHECK: loop:865; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]866; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]867; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]868; CHECK: if.true:869; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]870; CHECK-NEXT: br label [[BACKEDGE]]871; CHECK: if.false:872; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]873; CHECK-NEXT: br label [[BACKEDGE]]874; CHECK: backedge:875; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]876; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]877; CHECK-NEXT: call void @may_throw()878; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4879; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]880; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]881; CHECK: exit:882; CHECK-NEXT: ret void883;884 885entry:886 br label %loop887 888loop:889 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]890 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]891 %cond = icmp slt i32 %iv, %n892 br i1 %cond, label %if.true, label %if.false893 894if.true:895 %a = add i32 %iv, %iv896 br label %backedge897 898if.false:899 %b = mul i32 %iv, %iv900 br label %backedge901 902backedge:903 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]904 %iv.next = add i32 %iv, %merge905 call void @may_throw()906 %load = load i32, ptr %p907 %loop.cond = icmp ult i32 %iv.next, %load908 br i1 %loop.cond, label %loop, label %exit909 910exit:911 ret void912}913 914define void @test_hoist_from_backedge_03(ptr %p, i32 %n) {915; CHECK-LABEL: define void @test_hoist_from_backedge_03(916; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {917; CHECK-NEXT: entry:918; CHECK-NEXT: br label [[LOOP:%.*]]919; CHECK: loop:920; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]921; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]922; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]923; CHECK: if.true:924; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]925; CHECK-NEXT: br label [[BACKEDGE]]926; CHECK: if.false:927; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]928; CHECK-NEXT: call void @may_throw()929; CHECK-NEXT: br label [[BACKEDGE]]930; CHECK: backedge:931; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]932; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]933; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4934; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]935; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]936; CHECK: exit:937; CHECK-NEXT: ret void938;939 940entry:941 br label %loop942 943loop:944 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]945 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]946 %cond = icmp slt i32 %iv, %n947 br i1 %cond, label %if.true, label %if.false948 949if.true:950 %a = add i32 %iv, %iv951 br label %backedge952 953if.false:954 %b = mul i32 %iv, %iv955 call void @may_throw()956 br label %backedge957 958backedge:959 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]960 %iv.next = add i32 %iv, %merge961 %load = load i32, ptr %p962 %loop.cond = icmp ult i32 %iv.next, %load963 br i1 %loop.cond, label %loop, label %exit964 965exit:966 ret void967}968 969define void @test_hoist_from_backedge_04(ptr %p, i32 %n) {970; CHECK-LABEL: define void @test_hoist_from_backedge_04(971; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {972; CHECK-NEXT: entry:973; CHECK-NEXT: br label [[LOOP:%.*]]974; CHECK: loop:975; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]976; CHECK-NEXT: call void @may_throw()977; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]978; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]979; CHECK: if.true:980; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]981; CHECK-NEXT: br label [[BACKEDGE]]982; CHECK: if.false:983; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]984; CHECK-NEXT: br label [[BACKEDGE]]985; CHECK: backedge:986; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]987; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]988; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4989; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]990; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]991; CHECK: exit:992; CHECK-NEXT: ret void993;994 995entry:996 br label %loop997 998loop:999 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]1000 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]1001 call void @may_throw()1002 %cond = icmp slt i32 %iv, %n1003 br i1 %cond, label %if.true, label %if.false1004 1005if.true:1006 %a = add i32 %iv, %iv1007 br label %backedge1008 1009if.false:1010 %b = mul i32 %iv, %iv1011 br label %backedge1012 1013backedge:1014 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]1015 %iv.next = add i32 %iv, %merge1016 %load = load i32, ptr %p1017 %loop.cond = icmp ult i32 %iv.next, %load1018 br i1 %loop.cond, label %loop, label %exit1019 1020exit:1021 ret void1022}1023;.1024; CHECK: [[RNG0]] = !{i32 0, i32 512}1025;.1026