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