1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; REQUIRES: asserts 3; RUN: opt -passes=licm -ipt-expensive-asserts=true < %s -S | FileCheck %s 4; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s 5 6; Hoist guard and load. 7define void @test1(i1 %cond, ptr %ptr) { 8; CHECK-LABEL: @test1( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ] 11; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR:%.*]], align 4 12; CHECK-NEXT: br label [[LOOP:%.*]] 13; CHECK: loop: 14; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ] 15; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]] 16; CHECK-NEXT: br label [[LOOP]] 17; 18 19entry: 20 br label %loop 21 22loop: 23 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 24 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)] 25 %val = load i32, ptr %ptr 26 %x.inc = add i32 %x, %val 27 br label %loop 28} 29 30; Can't hoist over a side effect, but can still promote and fold the load. 31define void @test2(i1 %cond, ptr %ptr) { 32; CHECK-LABEL: @test2( 33; CHECK-NEXT: entry: 34; CHECK-NEXT: br label [[LOOP:%.*]] 35; CHECK: loop: 36; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ] 37; CHECK-NEXT: store i32 0, ptr [[PTR:%.*]], align 4 38; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ] 39; CHECK-NEXT: [[X_INC]] = add i32 [[X]], 0 40; CHECK-NEXT: br label [[LOOP]] 41; 42 43entry: 44 br label %loop 45 46loop: 47 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 48 store i32 0, ptr %ptr 49 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)] 50 %val = load i32, ptr %ptr 51 %x.inc = add i32 %x, %val 52 br label %loop 53} 54 55; Can't hoist over a side effect 56define void @test2b(i1 %cond, ptr %ptr) { 57; CHECK-LABEL: @test2b( 58; CHECK-NEXT: entry: 59; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1 60; CHECK-NEXT: br label [[LOOP:%.*]] 61; CHECK: loop: 62; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ] 63; CHECK-NEXT: store i32 [[X]], ptr [[P2]], align 4 64; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ] 65; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR]], align 4 66; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]] 67; CHECK-NEXT: br label [[LOOP]] 68; 69 70entry: 71 br label %loop 72 73loop: 74 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 75 %p2 = getelementptr i32, ptr %ptr, i32 1 76 store i32 %x, ptr %p2 77 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)] 78 %val = load i32, ptr %ptr 79 %x.inc = add i32 %x, %val 80 br label %loop 81} 82 83; But can hoist if the side effect is hoisted with MSSA 84define void @test2b_prime(i1 %cond, ptr noalias %ptr) { 85; CHECK-LABEL: @test2b_prime( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1 88; CHECK-NEXT: store i32 0, ptr [[P2]], align 4 89; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ] 90; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR]], align 4 91; CHECK-NEXT: br label [[LOOP:%.*]] 92; CHECK: loop: 93; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ] 94; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]] 95; CHECK-NEXT: br label [[LOOP]] 96; 97 98entry: 99 br label %loop 100 101loop: 102 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 103 %p2 = getelementptr i32, ptr %ptr, i32 1 104 store i32 0, ptr %p2 105 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)] 106 %val = load i32, ptr %ptr 107 %x.inc = add i32 %x, %val 108 br label %loop 109} 110 111; Hoist guard. Cannot hoist load because of aliasing, but can promote. 112define void @test3(i1 %cond, ptr %ptr) { 113; CHECK-LABEL: @test3( 114; CHECK-NEXT: entry: 115; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ] 116; CHECK-NEXT: [[PTR_PROMOTED:%.*]] = load i32, ptr [[PTR:%.*]], align 4 117; CHECK-NEXT: br label [[LOOP:%.*]] 118; CHECK: loop: 119; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[PTR_PROMOTED]], [[ENTRY:%.*]] ], [ 0, [[LOOP]] ] 120; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[X_INC:%.*]], [[LOOP]] ] 121; CHECK-NEXT: store i32 0, ptr [[PTR]], align 4 122; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[TMP0]] 123; CHECK-NEXT: br label [[LOOP]] 124; 125 126entry: 127 br label %loop 128 129loop: 130 %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ] 131 call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)] 132 %val = load i32, ptr %ptr 133 store i32 0, ptr %ptr 134 %x.inc = add i32 %x, %val 135 br label %loop 136} 137 138; Hoist load and guard. 139define void @test4(i1 %c, ptr %p) { 140; CHECK-LABEL: @test4( 141; CHECK-NEXT: entry: 142; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 143; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 144; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 145; CHECK-NEXT: br label [[LOOP:%.*]] 146; CHECK: loop: 147; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 148; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 149; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 150; CHECK: if.true: 151; CHECK-NEXT: br label [[BACKEDGE]] 152; CHECK: if.false: 153; CHECK-NEXT: br label [[BACKEDGE]] 154; CHECK: backedge: 155; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 156; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 157; CHECK: exit: 158; CHECK-NEXT: ret void 159; 160 161entry: 162 br label %loop 163 164loop: 165 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 166 %iv.next = add i32 %iv, 1 167 br i1 %c, label %if.true, label %if.false 168 169if.true: 170 br label %backedge 171 172if.false: 173 br label %backedge 174 175backedge: 176 %a = load i32, ptr %p 177 %invariant_cond = icmp ne i32 %a, 100 178 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 179 %loop_cond = icmp slt i32 %iv.next, 1000 180 br i1 %loop_cond, label %loop, label %exit 181 182exit: 183 ret void 184} 185 186; Do not hoist across a conditionally executed side effect. 187define void @test4a(i1 %c, ptr %p, ptr %q) { 188; CHECK-LABEL: @test4a( 189; CHECK-NEXT: entry: 190; CHECK-NEXT: br label [[LOOP:%.*]] 191; CHECK: loop: 192; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 193; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 194; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 195; CHECK: if.true: 196; CHECK-NEXT: store i32 123, ptr [[Q:%.*]], align 4 197; CHECK-NEXT: br label [[BACKEDGE]] 198; CHECK: if.false: 199; CHECK-NEXT: br label [[BACKEDGE]] 200; CHECK: backedge: 201; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 202; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 203; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 204; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 205; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 206; CHECK: exit: 207; CHECK-NEXT: ret void 208; 209 210entry: 211 br label %loop 212 213loop: 214 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 215 %iv.next = add i32 %iv, 1 216 br i1 %c, label %if.true, label %if.false 217 218if.true: 219 store i32 123, ptr %q 220 br label %backedge 221 222if.false: 223 br label %backedge 224 225backedge: 226 %a = load i32, ptr %p 227 %invariant_cond = icmp ne i32 %a, 100 228 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 229 %loop_cond = icmp slt i32 %iv.next, 1000 230 br i1 %loop_cond, label %loop, label %exit 231 232exit: 233 ret void 234} 235 236; Do not hoist a conditionally executed guard. 237define void @test4b(i1 %c, ptr %p, ptr %q) { 238; CHECK-LABEL: @test4b( 239; CHECK-NEXT: entry: 240; CHECK-NEXT: br label [[LOOP:%.*]] 241; CHECK: loop: 242; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 243; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 244; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 245; CHECK: if.true: 246; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 247; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 248; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 249; CHECK-NEXT: br label [[BACKEDGE]] 250; CHECK: if.false: 251; CHECK-NEXT: br label [[BACKEDGE]] 252; CHECK: backedge: 253; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 254; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 255; CHECK: exit: 256; CHECK-NEXT: ret void 257; 258 259entry: 260 br label %loop 261 262loop: 263 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 264 %iv.next = add i32 %iv, 1 265 br i1 %c, label %if.true, label %if.false 266 267if.true: 268 %a = load i32, ptr %p 269 %invariant_cond = icmp ne i32 %a, 100 270 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 271 br label %backedge 272 273if.false: 274 br label %backedge 275 276backedge: 277 %loop_cond = icmp slt i32 %iv.next, 1000 278 br i1 %loop_cond, label %loop, label %exit 279 280exit: 281 ret void 282} 283 284; Hoist store, load and guard. 285define void @test4c(i1 %c, ptr %p, ptr noalias %s) { 286; CHECK-LABEL: @test4c( 287; CHECK-NEXT: entry: 288; CHECK-NEXT: store i8 0, ptr [[S:%.*]], align 1 289; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 290; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 291; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 292; CHECK-NEXT: br label [[LOOP:%.*]] 293; CHECK: loop: 294; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 295; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 296; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 297; CHECK: if.true: 298; CHECK-NEXT: br label [[BACKEDGE]] 299; CHECK: if.false: 300; CHECK-NEXT: br label [[BACKEDGE]] 301; CHECK: backedge: 302; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 303; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 304; CHECK: exit: 305; CHECK-NEXT: ret void 306; 307 308entry: 309 br label %loop 310 311loop: 312 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 313 %iv.next = add i32 %iv, 1 314 store i8 0, ptr %s 315 br i1 %c, label %if.true, label %if.false 316 317if.true: 318 br label %backedge 319 320if.false: 321 br label %backedge 322 323backedge: 324 %a = load i32, ptr %p 325 %invariant_cond = icmp ne i32 %a, 100 326 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 327 %loop_cond = icmp slt i32 %iv.next, 1000 328 br i1 %loop_cond, label %loop, label %exit 329 330exit: 331 ret void 332} 333 334; Check that we don't hoist across a store in a conditionally executed block. 335define void @test4d(i1 %c, ptr %p, ptr noalias %s) { 336; CHECK-LABEL: @test4d( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 339; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 340; CHECK-NEXT: br label [[LOOP:%.*]] 341; CHECK: loop: 342; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 343; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 344; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 345; CHECK: if.true: 346; CHECK-NEXT: store i8 0, ptr [[S:%.*]], align 1 347; CHECK-NEXT: br label [[BACKEDGE]] 348; CHECK: if.false: 349; CHECK-NEXT: br label [[BACKEDGE]] 350; CHECK: backedge: 351; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 352; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 353; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 354; CHECK: exit: 355; CHECK-NEXT: ret void 356; 357 358entry: 359 br label %loop 360 361loop: 362 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 363 %iv.next = add i32 %iv, 1 364 br i1 %c, label %if.true, label %if.false 365 366if.true: 367 store i8 0, ptr %s 368 br label %backedge 369 370if.false: 371 br label %backedge 372 373backedge: 374 %a = load i32, ptr %p 375 %invariant_cond = icmp ne i32 %a, 100 376 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 377 %loop_cond = icmp slt i32 %iv.next, 1000 378 br i1 %loop_cond, label %loop, label %exit 379 380exit: 381 ret void 382} 383 384; Check that we don't hoist across a store before the guard in the backedge. 385define void @test4e(i1 %c, ptr %p, ptr noalias %s) { 386; CHECK-LABEL: @test4e( 387; CHECK-NEXT: entry: 388; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 389; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 390; CHECK-NEXT: store i8 0, ptr [[S:%.*]], align 1 391; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 392; CHECK-NEXT: br label [[LOOP:%.*]] 393; CHECK: loop: 394; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 395; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 396; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 397; CHECK: if.true: 398; CHECK-NEXT: br label [[BACKEDGE]] 399; CHECK: if.false: 400; CHECK-NEXT: br label [[BACKEDGE]] 401; CHECK: backedge: 402; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 403; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 404; CHECK: exit: 405; CHECK-NEXT: ret void 406; 407 408entry: 409 br label %loop 410 411loop: 412 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 413 %iv.next = add i32 %iv, 1 414 br i1 %c, label %if.true, label %if.false 415 416if.true: 417 br label %backedge 418 419if.false: 420 br label %backedge 421 422backedge: 423 %a = load i32, ptr %p 424 %invariant_cond = icmp ne i32 %a, 100 425 store i8 0, ptr %s 426 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 427 %loop_cond = icmp slt i32 %iv.next, 1000 428 br i1 %loop_cond, label %loop, label %exit 429 430exit: 431 ret void 432} 433 434; Check that we can hoist the guard in spite of store which happens after. 435define void @test4f(i1 %c, ptr %p, ptr noalias %s) { 436; CHECK-LABEL: @test4f( 437; CHECK-NEXT: entry: 438; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 439; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 440; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 441; CHECK-NEXT: store i8 0, ptr [[S:%.*]], align 1 442; CHECK-NEXT: br label [[LOOP:%.*]] 443; CHECK: loop: 444; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 445; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 446; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 447; CHECK: if.true: 448; CHECK-NEXT: br label [[BACKEDGE]] 449; CHECK: if.false: 450; CHECK-NEXT: br label [[BACKEDGE]] 451; CHECK: backedge: 452; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 453; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 454; CHECK: exit: 455; CHECK-NEXT: ret void 456; 457 458entry: 459 br label %loop 460 461loop: 462 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 463 %iv.next = add i32 %iv, 1 464 br i1 %c, label %if.true, label %if.false 465 466if.true: 467 br label %backedge 468 469if.false: 470 br label %backedge 471 472backedge: 473 %a = load i32, ptr %p 474 %invariant_cond = icmp ne i32 %a, 100 475 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 476 store i8 0, ptr %s 477 %loop_cond = icmp slt i32 %iv.next, 1000 478 br i1 %loop_cond, label %loop, label %exit 479 480exit: 481 ret void 482} 483 484; Do not hoist an invariant guard across a variant guard. 485define void @test5(i1 %c, ptr %p, ptr %q) { 486; CHECK-LABEL: @test5( 487; CHECK-NEXT: entry: 488; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 489; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 490; CHECK-NEXT: br label [[LOOP:%.*]] 491; CHECK: loop: 492; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 493; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 494; CHECK-NEXT: [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]] 495; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ] 496; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 497; CHECK-NEXT: br label [[BACKEDGE]] 498; CHECK: backedge: 499; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 500; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 501; CHECK: exit: 502; CHECK-NEXT: ret void 503; 504 505entry: 506 br label %loop 507 508loop: 509 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 510 %iv.next = add i32 %iv, 1 511 %a = load i32, ptr %p 512 %invariant_cond = icmp ne i32 %a, 100 513 %variant_cond = icmp ne i32 %a, %iv 514 call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ] 515 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 516 br label %backedge 517 518backedge: 519 %loop_cond = icmp slt i32 %iv.next, 1000 520 br i1 %loop_cond, label %loop, label %exit 521 522exit: 523 ret void 524} 525 526; Hoist an invariant guard, leave the following variant guard in the loop. 527define void @test5a(i1 %c, ptr %p, ptr %q) { 528; CHECK-LABEL: @test5a( 529; CHECK-NEXT: entry: 530; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P:%.*]], align 4 531; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100 532; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ] 533; CHECK-NEXT: br label [[LOOP:%.*]] 534; CHECK: loop: 535; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 536; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 537; CHECK-NEXT: [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]] 538; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ] 539; CHECK-NEXT: br label [[BACKEDGE]] 540; CHECK: backedge: 541; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000 542; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 543; CHECK: exit: 544; CHECK-NEXT: ret void 545; 546 547entry: 548 br label %loop 549 550loop: 551 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ] 552 %iv.next = add i32 %iv, 1 553 %a = load i32, ptr %p 554 %invariant_cond = icmp ne i32 %a, 100 555 %variant_cond = icmp ne i32 %a, %iv 556 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ] 557 call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ] 558 br label %backedge 559 560backedge: 561 %loop_cond = icmp slt i32 %iv.next, 1000 562 br i1 %loop_cond, label %loop, label %exit 563 564exit: 565 ret void 566} 567 568declare void @llvm.experimental.guard(i1, ...) 569