1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; REQUIRES: asserts 3; RUN: opt -S -passes=licm -ipt-expensive-asserts=true < %s | FileCheck %s 4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 6 7declare void @f() nounwind 8declare void @llvm.experimental.guard(i1,...) 9 10; constant fold on first ieration 11define 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 4 16; 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]], 2000 21; 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]], 1 25; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 26; 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 -1 33; 34entry: 35 br label %for.body 36 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, 2000 41 br i1 %r.chk, label %continue, label %fail 42continue: 43 %i1 = load i32, ptr %a, align 4 44 %add = add nsw i32 %i1, %acc 45 %inc = add nuw nsw i32 %iv, 1 46 %exitcond = icmp eq i32 %inc, 1000 47 br i1 %exitcond, label %for.cond.cleanup, label %for.body 48 49for.cond.cleanup: 50 ret i32 %add 51 52fail: 53 call void @f() 54 ret i32 -1 55} 56 57; Same as test1, but with a floating point IR and fcmp 58define 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 4 63; 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+03 68; 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+00 72; CHECK-NEXT: [[EXITCOND:%.*]] = fcmp ogt float [[INC]], 1.000000e+03 73; 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 -1 80; 81entry: 82 br label %for.body 83 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.0 88 br i1 %r.chk, label %continue, label %fail 89continue: 90 %i1 = load i32, ptr %a, align 4 91 %add = add nsw i32 %i1, %acc 92 %inc = fadd float %iv, 1.0 93 %exitcond = fcmp ogt float %inc, 1000.0 94 br i1 %exitcond, label %for.cond.cleanup, label %for.body 95 96for.cond.cleanup: 97 ret i32 %add 98 99fail: 100 call void @f() 101 ret i32 -1 102} 103 104; Count down from a.length w/entry guard 105; 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]], 0 113; CHECK-NEXT: br i1 [[IS_NON_POS]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] 114; CHECK: preheader: 115; CHECK-NEXT: [[LENMINUSONE:%.*]] = add nsw i32 [[LEN]], -1 116; 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 4 124; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] 125; CHECK-NEXT: [[DEC]] = add nsw i32 [[IV]], -1 126; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[DEC]], 0 127; 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 -1 136; 137entry: 138 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} 139 %is.non.pos = icmp eq i32 %len, 0 140 br i1 %is.non.pos, label %fail, label %preheader 141preheader: 142 %lenminusone = add nsw i32 %len, -1 143 br label %for.body 144for.body: 145 %iv = phi i32 [ %lenminusone, %preheader ], [ %dec, %continue ] 146 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 147 %r.chk = icmp ule i32 %iv, %len 148 br i1 %r.chk, label %continue, label %fail 149continue: 150 %i1 = load i32, ptr %a, align 4 151 %add = add nsw i32 %i1, %acc 152 %dec = add nsw i32 %iv, -1 153 %exitcond = icmp eq i32 %dec, 0 154 br i1 %exitcond, label %for.cond.cleanup, label %for.body 155 156for.cond.cleanup: 157 ret i32 %add 158 159fail: 160 call void @f() 161 ret i32 -1 162} 163 164; trivially true for zero 165define 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]], 0 171; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] 172; CHECK: preheader: 173; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 174; 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]], 1 183; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 184; 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 -1 193; 194entry: 195 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} 196 %is.zero = icmp eq i32 %len, 0 197 br i1 %is.zero, label %fail, label %preheader 198preheader: 199 br label %for.body 200for.body: 201 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] 202 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 203 %r.chk = icmp ule i32 %iv, %len 204 br i1 %r.chk, label %continue, label %fail 205continue: 206 %i1 = load i32, ptr %a, align 4 207 %add = add nsw i32 %i1, %acc 208 %inc = add nuw nsw i32 %iv, 1 209 %exitcond = icmp eq i32 %inc, 1000 210 br i1 %exitcond, label %for.cond.cleanup, label %for.body 211 212for.cond.cleanup: 213 ret i32 %add 214 215fail: 216 call void @f() 217 ret i32 -1 218} 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]], 0 227; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] 228; CHECK: preheader: 229; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 230; 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]], 1 239; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 240; 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 -1 249; 250entry: 251 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} 252 %is.zero = icmp eq i32 %len, 0 253 br i1 %is.zero, label %fail, label %preheader 254preheader: 255 br label %for.body 256for.body: 257 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] 258 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 259 %r.chk = icmp uge i32 %len, %iv 260 br i1 %r.chk, label %continue, label %fail 261continue: 262 %i1 = load i32, ptr %a, align 4 263 %add = add nsw i32 %i1, %acc 264 %inc = add nuw nsw i32 %iv, 1 265 %exitcond = icmp eq i32 %inc, 1000 266 br i1 %exitcond, label %for.cond.cleanup, label %for.body 267 268for.cond.cleanup: 269 ret i32 %add 270 271fail: 272 call void @f() 273 ret i32 -1 274} 275 276; requires fact length is non-zero 277define 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]], 0 283; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]] 284; CHECK: preheader: 285; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 286; 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]], 1 295; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 296; 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 -1 305; 306entry: 307 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512} 308 %is.zero = icmp eq i32 %len, 0 309 br i1 %is.zero, label %fail, label %preheader 310preheader: 311 br label %for.body 312for.body: 313 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] 314 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 315 %r.chk = icmp ult i32 %iv, %len 316 br i1 %r.chk, label %continue, label %fail 317continue: 318 %i1 = load i32, ptr %a, align 4 319 %add = add nsw i32 %i1, %acc 320 %inc = add nuw nsw i32 %iv, 1 321 %exitcond = icmp eq i32 %inc, 1000 322 br i1 %exitcond, label %for.cond.cleanup, label %for.body 323 324for.cond.cleanup: 325 ret i32 %add 326 327fail: 328 call void @f() 329 ret i32 -1 330} 331 332; variation on test1 with branch swapped 333define 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 4 338; 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]], 2000 343; 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]], 1 347; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 348; 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 -1 355; 356entry: 357 br label %for.body 358 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, 2000 363 br i1 %r.chk, label %fail, label %continue 364continue: 365 %i1 = load i32, ptr %a, align 4 366 %add = add nsw i32 %i1, %acc 367 %inc = add nuw nsw i32 %iv, 1 368 %exitcond = icmp eq i32 %inc, 1000 369 br i1 %exitcond, label %for.cond.cleanup, label %for.body 370 371for.cond.cleanup: 372 ret i32 %add 373 374fail: 375 call void @f() 376 ret i32 -1 377} 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]], 72 388; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[XOR]], 2000 389; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]] 390; CHECK: continue: 391; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 392; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] 393; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 394; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 395; 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 -1 402; 403entry: 404 br label %for.body 405 406for.body: 407 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 408 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 409 %xor = xor i32 %iv, 72 410 %r.chk = icmp ugt i32 %xor, 2000 411 br i1 %r.chk, label %fail, label %continue 412continue: 413 %i1 = load i32, ptr %a, align 4 414 %add = add nsw i32 %i1, %acc 415 %inc = add nuw nsw i32 %iv, 1 416 %exitcond = icmp eq i32 %inc, 1000 417 br i1 %exitcond, label %for.cond.cleanup, label %for.body 418 419for.cond.cleanup: 420 ret i32 %add 421 422fail: 423 call void @f() 424 ret i32 -1 425} 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]], 500 436; 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]], 2000 442; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]] 443; CHECK: continue: 444; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4 445; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]] 446; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1 447; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000 448; 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 -1 455; 456entry: 457 br label %for.body 458 459for.body: 460 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 461 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 462 %cond = icmp ult i32 %iv, 500 463 br i1 %cond, label %dummy_block1, label %dummy_block2 464 465dummy_block1: 466 br label %dummy_block2 467 468dummy_block2: 469 %wrongphi = phi i32 [11, %for.body], [12, %dummy_block1] 470 %r.chk = icmp ugt i32 %wrongphi, 2000 471 br i1 %r.chk, label %fail, label %continue 472continue: 473 %i1 = load i32, ptr %a, align 4 474 %add = add nsw i32 %i1, %acc 475 %inc = add nuw nsw i32 %iv, 1 476 %exitcond = icmp eq i32 %inc, 1000 477 br i1 %exitcond, label %for.cond.cleanup, label %for.body 478 479for.cond.cleanup: 480 ret i32 %add 481 482fail: 483 call void @f() 484 ret i32 -1 485} 486 487; This works because loop-simplify is run implicitly, but test for it anyways 488define 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 4 493; 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]], 2000 498; 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]], 1 502; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], 0 503; 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]], 1000 508; 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 -1 515; 516entry: 517 br label %for.body 518 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, 2000 523 br i1 %r.chk, label %continue1, label %fail 524continue1: 525 %i1 = load i32, ptr %a, align 4 526 %add = add nsw i32 %i1, %acc 527 %inc = add nuw nsw i32 %iv, 1 528 %cmp = icmp eq i32 %add, 0 529 br i1 %cmp, label %continue2, label %for.body 530continue2: 531 %exitcond = icmp eq i32 %inc, 1000 532 br i1 %exitcond, label %for.cond.cleanup, label %for.body 533 534for.cond.cleanup: 535 ret i32 %add 536 537fail: 538 call void @f() 539 ret i32 -1 540} 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 4 547; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 548; 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]], 1 553; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 554; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 555; CHECK: exit: 556; CHECK-NEXT: ret void 557; 558 559entry: 560 br label %loop 561 562loop: 563 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] 564 %iv.next = add i32 %iv, 1 565 %a = load i32, ptr %p 566 %invariant_cond = icmp ne i32 %a, 100 567 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 568 %loop_cond = icmp slt i32 %iv.next, 1000 569 br i1 %loop_cond, label %loop, label %exit 570 571exit: 572 ret void 573} 574 575 576declare void @may_throw() inaccessiblememonly 577 578; Test that we can sink a mustexecute load from loop header even in presence of 579; 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 4 585; 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 void 604; 605 606entry: 607 br label %loop 608 609loop: 610 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 611 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 612 %load = load i32, ptr %p 613 call void @may_throw() 614 %cond = icmp slt i32 %iv, %n 615 br i1 %cond, label %if.true, label %if.false 616 617if.true: 618 %a = add i32 %iv, %iv 619 br label %backedge 620 621if.false: 622 %b = mul i32 %iv, %iv 623 br label %backedge 624 625backedge: 626 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 627 %iv.next = add i32 %iv, %merge 628 %loop.cond = icmp ult i32 %iv.next, %load 629 br i1 %loop.cond, label %loop, label %exit 630 631exit: 632 ret void 633} 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 4 640; 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 void 659; 660 661entry: 662 br label %loop 663 664loop: 665 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 666 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 667 %load = load i32, ptr %p 668 %cond = icmp slt i32 %iv, %n 669 br i1 %cond, label %if.true, label %if.false 670 671if.true: 672 call void @may_throw() 673 %a = add i32 %iv, %iv 674 br label %backedge 675 676if.false: 677 %b = mul i32 %iv, %iv 678 br label %backedge 679 680backedge: 681 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 682 %iv.next = add i32 %iv, %merge 683 %loop.cond = icmp ult i32 %iv.next, %load 684 br i1 %loop.cond, label %loop, label %exit 685 686exit: 687 ret void 688} 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 4 695; 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 void 714; 715 716entry: 717 br label %loop 718 719loop: 720 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 721 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 722 %load = load i32, ptr %p 723 %cond = icmp slt i32 %iv, %n 724 br i1 %cond, label %if.true, label %if.false 725 726if.true: 727 %a = add i32 %iv, %iv 728 br label %backedge 729 730if.false: 731 %b = mul i32 %iv, %iv 732 br label %backedge 733 734backedge: 735 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 736 call void @may_throw() 737 %iv.next = add i32 %iv, %merge 738 %loop.cond = icmp ult i32 %iv.next, %load 739 br i1 %loop.cond, label %loop, label %exit 740 741exit: 742 ret void 743} 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 4 755; 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 void 770; 771 772entry: 773 br label %loop 774 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 %p 780 %cond = icmp slt i32 %iv, %n 781 br i1 %cond, label %if.true, label %if.false 782 783if.true: 784 %a = add i32 %iv, %iv 785 br label %backedge 786 787if.false: 788 %b = mul i32 %iv, %iv 789 br label %backedge 790 791backedge: 792 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 793 %iv.next = add i32 %iv, %merge 794 %loop.cond = icmp ult i32 %iv.next, %load 795 br i1 %loop.cond, label %loop, label %exit 796 797exit: 798 ret void 799} 800 801; Check that we can hoist a mustexecute load from backedge even if something 802; 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 4 808; 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 void 827; 828 829entry: 830 br label %loop 831 832loop: 833 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 834 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 835 %cond = icmp slt i32 %iv, %n 836 br i1 %cond, label %if.true, label %if.false 837 838if.true: 839 %a = add i32 %iv, %iv 840 br label %backedge 841 842if.false: 843 %b = mul i32 %iv, %iv 844 br label %backedge 845 846backedge: 847 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 848 %iv.next = add i32 %iv, %merge 849 %load = load i32, ptr %p 850 call void @may_throw() 851 %loop.cond = icmp ult i32 %iv.next, %load 852 br i1 %loop.cond, label %loop, label %exit 853 854exit: 855 ret void 856} 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 4 879; 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 void 883; 884 885entry: 886 br label %loop 887 888loop: 889 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 890 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 891 %cond = icmp slt i32 %iv, %n 892 br i1 %cond, label %if.true, label %if.false 893 894if.true: 895 %a = add i32 %iv, %iv 896 br label %backedge 897 898if.false: 899 %b = mul i32 %iv, %iv 900 br label %backedge 901 902backedge: 903 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 904 %iv.next = add i32 %iv, %merge 905 call void @may_throw() 906 %load = load i32, ptr %p 907 %loop.cond = icmp ult i32 %iv.next, %load 908 br i1 %loop.cond, label %loop, label %exit 909 910exit: 911 ret void 912} 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 4 934; 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 void 938; 939 940entry: 941 br label %loop 942 943loop: 944 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 945 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ] 946 %cond = icmp slt i32 %iv, %n 947 br i1 %cond, label %if.true, label %if.false 948 949if.true: 950 %a = add i32 %iv, %iv 951 br label %backedge 952 953if.false: 954 %b = mul i32 %iv, %iv 955 call void @may_throw() 956 br label %backedge 957 958backedge: 959 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 960 %iv.next = add i32 %iv, %merge 961 %load = load i32, ptr %p 962 %loop.cond = icmp ult i32 %iv.next, %load 963 br i1 %loop.cond, label %loop, label %exit 964 965exit: 966 ret void 967} 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 4 989; 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 void 993; 994 995entry: 996 br label %loop 997 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, %n 1003 br i1 %cond, label %if.true, label %if.false 1004 1005if.true: 1006 %a = add i32 %iv, %iv 1007 br label %backedge 1008 1009if.false: 1010 %b = mul i32 %iv, %iv 1011 br label %backedge 1012 1013backedge: 1014 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ] 1015 %iv.next = add i32 %iv, %merge 1016 %load = load i32, ptr %p 1017 %loop.cond = icmp ult i32 %iv.next, %load 1018 br i1 %loop.cond, label %loop, label %exit 1019 1020exit: 1021 ret void 1022} 1023;. 1024; CHECK: [[RNG0]] = !{i32 0, i32 512} 1025;. 1026