1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -basic-aa -enable-load-pre -enable-pre -lcssa -gvn -S < %s | FileCheck %s 3 4declare void @side_effect() nofree 5declare i1 @side_effect_cond() nofree 6declare void @may_free_memory() 7 8declare i32 @personality_function() 9 10; We can PRE the load from gc-managed memory away from the hot path. 11define i32 @test_load_on_cold_path_gc(i32 addrspace(1)* %p) gc "statepoint-example" personality i32 ()* @"personality_function" { 12; CHECK-LABEL: @test_load_on_cold_path_gc( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[X_PRE1:%.*]] = load i32, i32 addrspace(1)* [[P:%.*]], align 4 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[X_PRE1]], [[ENTRY:%.*]] ], [ [[X2:%.*]], [[BACKEDGE:%.*]] ] 18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE]] ] 19; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 20; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 21; CHECK: hot_path: 22; CHECK-NEXT: br label [[BACKEDGE]] 23; CHECK: cold_path: 24; CHECK-NEXT: call void @may_free_memory() 25; CHECK-NEXT: [[X_PRE:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4 26; CHECK-NEXT: br label [[BACKEDGE]] 27; CHECK: backedge: 28; CHECK-NEXT: [[X2]] = phi i32 [ [[X_PRE]], [[COLD_PATH]] ], [ [[X]], [[HOT_PATH]] ] 29; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 30; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 31; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 32; CHECK: exit: 33; CHECK-NEXT: ret i32 [[X]] 34; 35entry: 36 br label %loop 37 38loop: 39 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 40 %x = load i32, i32 addrspace(1)* %p 41 %cond = icmp ne i32 %x, 0 42 br i1 %cond, label %hot_path, label %cold_path 43 44hot_path: 45 br label %backedge 46 47cold_path: 48 call void @may_free_memory() 49 br label %backedge 50 51backedge: 52 %iv.next = add i32 %iv, %x 53 %loop.cond = icmp ult i32 %iv.next, 1000 54 br i1 %loop.cond, label %loop, label %exit 55 56exit: 57 ret i32 %x 58} 59 60; Do not PRE here because a loop-variant pointer. 61define i32 @test_load_on_cold_path_gc_variant_neg(i32 addrspace(1)* addrspace(1)* %pp) gc "statepoint-example" personality i32 ()* @"personality_function" { 62; CHECK-LABEL: @test_load_on_cold_path_gc_variant_neg( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: br label [[LOOP:%.*]] 65; CHECK: loop: 66; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 67; CHECK-NEXT: [[P:%.*]] = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* [[PP:%.*]], align 8 68; CHECK-NEXT: [[X:%.*]] = load i32, i32 addrspace(1)* [[P]], align 4 69; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 70; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 71; CHECK: hot_path: 72; CHECK-NEXT: br label [[BACKEDGE]] 73; CHECK: cold_path: 74; CHECK-NEXT: call void @may_free_memory() 75; CHECK-NEXT: br label [[BACKEDGE]] 76; CHECK: backedge: 77; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 78; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 79; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 80; CHECK: exit: 81; CHECK-NEXT: ret i32 [[X]] 82; 83entry: 84 br label %loop 85 86loop: 87 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 88 %p = load volatile i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pp 89 %x = load i32, i32 addrspace(1)* %p 90 %cond = icmp ne i32 %x, 0 91 br i1 %cond, label %hot_path, label %cold_path 92 93hot_path: 94 br label %backedge 95 96cold_path: 97 call void @may_free_memory() 98 br label %backedge 99 100backedge: 101 %iv.next = add i32 %iv, %x 102 %loop.cond = icmp ult i32 %iv.next, 1000 103 br i1 %loop.cond, label %loop, label %exit 104 105exit: 106 ret i32 %x 107} 108 109 110; TODO: We can PRE the load away from the hot path. 111define i32 @test_load_on_cold_path(i32* %p) { 112; CHECK-LABEL: @test_load_on_cold_path( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: br label [[LOOP:%.*]] 115; CHECK: loop: 116; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 117; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 118; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 119; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 120; CHECK: hot_path: 121; CHECK-NEXT: br label [[BACKEDGE]] 122; CHECK: cold_path: 123; CHECK-NEXT: call void @side_effect() #[[ATTR0:[0-9]+]] 124; CHECK-NEXT: br label [[BACKEDGE]] 125; CHECK: backedge: 126; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 127; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 128; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 129; CHECK: exit: 130; CHECK-NEXT: ret i32 [[X]] 131; 132entry: 133 br label %loop 134 135loop: 136 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 137 %x = load i32, i32* %p 138 %cond = icmp ne i32 %x, 0 139 br i1 %cond, label %hot_path, label %cold_path 140 141hot_path: 142 br label %backedge 143 144cold_path: 145 call void @side_effect() nofree 146 br label %backedge 147 148backedge: 149 %iv.next = add i32 %iv, %x 150 %loop.cond = icmp ult i32 %iv.next, 1000 151 br i1 %loop.cond, label %loop, label %exit 152 153exit: 154 ret i32 %x 155} 156 157; We should NOT PRE here because the function on the cold path may possibly 158; free the memory under the pointer. 159define i32 @test_load_on_cold_path_may_free_memory_neg(i32* %p) { 160; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_neg( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: br label [[LOOP:%.*]] 163; CHECK: loop: 164; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 165; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 166; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 167; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 168; CHECK: hot_path: 169; CHECK-NEXT: br label [[BACKEDGE]] 170; CHECK: cold_path: 171; CHECK-NEXT: call void @may_free_memory() 172; CHECK-NEXT: br label [[BACKEDGE]] 173; CHECK: backedge: 174; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 175; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 176; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 177; CHECK: exit: 178; CHECK-NEXT: ret i32 [[X]] 179; 180entry: 181 br label %loop 182 183loop: 184 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 185 %x = load i32, i32* %p 186 %cond = icmp ne i32 %x, 0 187 br i1 %cond, label %hot_path, label %cold_path 188 189hot_path: 190 br label %backedge 191 192cold_path: 193 call void @may_free_memory() 194 br label %backedge 195 196backedge: 197 %iv.next = add i32 %iv, %x 198 %loop.cond = icmp ult i32 %iv.next, 1000 199 br i1 %loop.cond, label %loop, label %exit 200 201exit: 202 ret i32 %x 203} 204 205; TODO: Despite the fact that the function may free memory in general, it 206; cannot free memory allocated by alloca. 207define i32 @test_load_on_cold_path_may_free_memory_alloca() { 208; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca( 209; CHECK-NEXT: entry: 210; CHECK-NEXT: [[P:%.*]] = alloca i32, align 4 211; CHECK-NEXT: call void @may_free_memory() 212; CHECK-NEXT: br label [[LOOP:%.*]] 213; CHECK: loop: 214; CHECK-NEXT: br i1 undef, label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 215; CHECK: hot_path: 216; CHECK-NEXT: br label [[BACKEDGE:%.*]] 217; CHECK: cold_path: 218; CHECK-NEXT: call void @may_free_memory() 219; CHECK-NEXT: br label [[BACKEDGE]] 220; CHECK: backedge: 221; CHECK-NEXT: br i1 false, label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[EXIT:%.*]] 222; CHECK: backedge.loop_crit_edge: 223; CHECK-NEXT: br label [[LOOP]] 224; CHECK: exit: 225; CHECK-NEXT: ret i32 undef 226; 227entry: 228 %p = alloca i32 229 call void @may_free_memory() 230 br label %loop 231 232loop: 233 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 234 %x = load i32, i32* %p 235 %cond = icmp ne i32 %x, 0 236 br i1 %cond, label %hot_path, label %cold_path 237 238hot_path: 239 br label %backedge 240 241cold_path: 242 call void @may_free_memory() 243 br label %backedge 244 245backedge: 246 %iv.next = add i32 %iv, %x 247 %loop.cond = icmp ult i32 %iv.next, 1000 248 br i1 %loop.cond, label %loop, label %exit 249 250exit: 251 ret i32 %x 252} 253 254 255; PRE here is meaningless, so we should not do it. 256define i32 @test_load_on_both_paths(i32* %p) { 257; CHECK-LABEL: @test_load_on_both_paths( 258; CHECK-NEXT: entry: 259; CHECK-NEXT: br label [[LOOP:%.*]] 260; CHECK: loop: 261; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 262; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 263; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 264; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 265; CHECK: hot_path: 266; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 267; CHECK-NEXT: br label [[BACKEDGE]] 268; CHECK: cold_path: 269; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 270; CHECK-NEXT: br label [[BACKEDGE]] 271; CHECK: backedge: 272; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 273; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 274; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 275; CHECK: exit: 276; CHECK-NEXT: ret i32 [[X]] 277; 278entry: 279 br label %loop 280 281loop: 282 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 283 %x = load i32, i32* %p 284 %cond = icmp ne i32 %x, 0 285 br i1 %cond, label %hot_path, label %cold_path 286 287hot_path: 288 call void @side_effect() nofree 289 br label %backedge 290 291cold_path: 292 call void @side_effect() nofree 293 br label %backedge 294 295backedge: 296 %iv.next = add i32 %iv, %x 297 %loop.cond = icmp ult i32 %iv.next, 1000 298 br i1 %loop.cond, label %loop, label %exit 299 300exit: 301 ret i32 %x 302} 303 304 305; We could PRE here, but it doesn't seem very profitable. 306define i32 @test_load_on_backedge(i32* %p) { 307; CHECK-LABEL: @test_load_on_backedge( 308; CHECK-NEXT: entry: 309; CHECK-NEXT: br label [[LOOP:%.*]] 310; CHECK: loop: 311; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 312; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 313; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 314; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 315; CHECK: hot_path: 316; CHECK-NEXT: br label [[BACKEDGE]] 317; CHECK: cold_path: 318; CHECK-NEXT: br label [[BACKEDGE]] 319; CHECK: backedge: 320; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 321; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 322; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 323; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 324; CHECK: exit: 325; CHECK-NEXT: ret i32 [[X]] 326; 327entry: 328 br label %loop 329 330loop: 331 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 332 %x = load i32, i32* %p 333 %cond = icmp ne i32 %x, 0 334 br i1 %cond, label %hot_path, label %cold_path 335 336hot_path: 337 br label %backedge 338 339cold_path: 340 br label %backedge 341 342backedge: 343 %iv.next = add i32 %iv, %x 344 call void @side_effect() nofree 345 %loop.cond = icmp ult i32 %iv.next, 1000 346 br i1 %loop.cond, label %loop, label %exit 347 348exit: 349 ret i32 %x 350} 351 352; TODO: We can PRE via splitting of the critical edge in the cold path. 353define i32 @test_load_on_exiting_cold_path_01(i32* %p) { 354; CHECK-LABEL: @test_load_on_exiting_cold_path_01( 355; CHECK-NEXT: entry: 356; CHECK-NEXT: br label [[LOOP:%.*]] 357; CHECK: loop: 358; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 359; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 360; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 361; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 362; CHECK: hot_path: 363; CHECK-NEXT: br label [[BACKEDGE]] 364; CHECK: cold_path: 365; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 366; CHECK-NEXT: br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]] 367; CHECK: backedge: 368; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 369; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 370; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 371; CHECK: exit: 372; CHECK-NEXT: ret i32 [[X]] 373; CHECK: cold_exit: 374; CHECK-NEXT: ret i32 -1 375; 376entry: 377 br label %loop 378 379loop: 380 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 381 %x = load i32, i32* %p 382 %cond = icmp ne i32 %x, 0 383 br i1 %cond, label %hot_path, label %cold_path 384 385hot_path: 386 br label %backedge 387 388cold_path: 389 %side_cond = call i1 @side_effect_cond() nofree 390 br i1 %side_cond, label %backedge, label %cold_exit 391 392backedge: 393 %iv.next = add i32 %iv, %x 394 %loop.cond = icmp ult i32 %iv.next, 1000 395 br i1 %loop.cond, label %loop, label %exit 396 397exit: 398 ret i32 %x 399 400cold_exit: 401 ret i32 -1 402} 403 404; TODO: We can PRE via splitting of the critical edge in the cold path. 405define i32 @test_load_on_exiting_cold_path_02(i32* %p) gc "statepoint-example" personality i32 ()* @personality_function { 406; CHECK-LABEL: @test_load_on_exiting_cold_path_02( 407; CHECK-NEXT: entry: 408; CHECK-NEXT: br label [[LOOP:%.*]] 409; CHECK: loop: 410; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 411; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 412; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 413; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 414; CHECK: hot_path: 415; CHECK-NEXT: br label [[BACKEDGE]] 416; CHECK: cold_path: 417; CHECK-NEXT: invoke void @side_effect() 418; CHECK-NEXT: to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]] 419; CHECK: backedge: 420; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 421; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 422; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 423; CHECK: exit: 424; CHECK-NEXT: ret i32 [[X]] 425; CHECK: cold_exit: 426; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad token 427; CHECK-NEXT: cleanup 428; CHECK-NEXT: ret i32 -1 429; 430entry: 431 br label %loop 432 433loop: 434 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 435 %x = load i32, i32* %p 436 %cond = icmp ne i32 %x, 0 437 br i1 %cond, label %hot_path, label %cold_path 438 439hot_path: 440 br label %backedge 441 442cold_path: 443 invoke void @side_effect() to label %backedge unwind label %cold_exit 444 445backedge: 446 %iv.next = add i32 %iv, %x 447 %loop.cond = icmp ult i32 %iv.next, 1000 448 br i1 %loop.cond, label %loop, label %exit 449 450exit: 451 ret i32 %x 452 453cold_exit: 454 %landing_pad = landingpad token 455 cleanup 456 ret i32 -1 457} 458 459; Make sure we do not insert load into both cold path & backedge. 460define i32 @test_load_on_cold_path_and_backedge(i32* %p) { 461; CHECK-LABEL: @test_load_on_cold_path_and_backedge( 462; CHECK-NEXT: entry: 463; CHECK-NEXT: br label [[LOOP:%.*]] 464; CHECK: loop: 465; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 466; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 467; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 468; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 469; CHECK: hot_path: 470; CHECK-NEXT: br label [[BACKEDGE]] 471; CHECK: cold_path: 472; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 473; CHECK-NEXT: br label [[BACKEDGE]] 474; CHECK: backedge: 475; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 476; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 477; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 478; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 479; CHECK: exit: 480; CHECK-NEXT: ret i32 [[X]] 481; 482entry: 483 br label %loop 484 485loop: 486 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 487 %x = load i32, i32* %p 488 %cond = icmp ne i32 %x, 0 489 br i1 %cond, label %hot_path, label %cold_path 490 491hot_path: 492 br label %backedge 493 494cold_path: 495 call void @side_effect() nofree 496 br label %backedge 497 498backedge: 499 %iv.next = add i32 %iv, %x 500 %loop.cond = icmp ult i32 %iv.next, 1000 501 call void @side_effect() nofree 502 br i1 %loop.cond, label %loop, label %exit 503 504exit: 505 ret i32 %x 506} 507 508; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load. 509define i32 @test_load_multi_block_cold_path(i32* %p) { 510; CHECK-LABEL: @test_load_multi_block_cold_path( 511; CHECK-NEXT: entry: 512; CHECK-NEXT: br label [[LOOP:%.*]] 513; CHECK: loop: 514; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 515; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 516; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 517; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]] 518; CHECK: hot_path: 519; CHECK-NEXT: br label [[BACKEDGE]] 520; CHECK: cold_path.1: 521; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 522; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 523; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 524; CHECK-NEXT: br label [[BACKEDGE]] 525; CHECK: backedge: 526; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 527; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 528; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 529; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 530; CHECK: exit: 531; CHECK-NEXT: ret i32 [[X]] 532; 533entry: 534 br label %loop 535 536loop: 537 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 538 %x = load i32, i32* %p 539 %cond = icmp ne i32 %x, 0 540 br i1 %cond, label %hot_path, label %cold_path.1 541 542hot_path: 543 br label %backedge 544 545cold_path.1: 546 call void @side_effect() nofree 547 br label %cold_path.2 548 549cold_path.2: 550 call void @side_effect() nofree 551 br label %cold_path.3 552 553cold_path.3: 554 call void @side_effect() nofree 555 br label %backedge 556 557backedge: 558 %iv.next = add i32 %iv, %x 559 %loop.cond = icmp ult i32 %iv.next, 1000 560 call void @side_effect() nofree 561 br i1 %loop.cond, label %loop, label %exit 562 563exit: 564 ret i32 %x 565} 566 567; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load. 568define i32 @test_load_on_multi_exiting_cold_path(i32* %p) { 569; CHECK-LABEL: @test_load_on_multi_exiting_cold_path( 570; CHECK-NEXT: entry: 571; CHECK-NEXT: br label [[LOOP:%.*]] 572; CHECK: loop: 573; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 574; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 575; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 576; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]] 577; CHECK: hot_path: 578; CHECK-NEXT: br label [[BACKEDGE]] 579; CHECK: cold_path.1: 580; CHECK-NEXT: [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 581; CHECK-NEXT: br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]] 582; CHECK: cold_path.2: 583; CHECK-NEXT: [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 584; CHECK-NEXT: br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]] 585; CHECK: cold_path.3: 586; CHECK-NEXT: [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 587; CHECK-NEXT: br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]] 588; CHECK: backedge: 589; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 590; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 591; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 592; CHECK: exit: 593; CHECK-NEXT: ret i32 [[X]] 594; CHECK: cold_exit: 595; CHECK-NEXT: ret i32 -1 596; 597entry: 598 br label %loop 599 600loop: 601 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 602 %x = load i32, i32* %p 603 %cond = icmp ne i32 %x, 0 604 br i1 %cond, label %hot_path, label %cold_path.1 605 606hot_path: 607 br label %backedge 608 609cold_path.1: 610 %side_cond.1 = call i1 @side_effect_cond() nofree 611 br i1 %side_cond.1, label %cold_path.2, label %cold_exit 612 613cold_path.2: 614 %side_cond.2 = call i1 @side_effect_cond() nofree 615 br i1 %side_cond.2, label %cold_path.3, label %cold_exit 616 617cold_path.3: 618 %side_cond.3 = call i1 @side_effect_cond() nofree 619 br i1 %side_cond.3, label %backedge, label %cold_exit 620 621backedge: 622 %iv.next = add i32 %iv, %x 623 %loop.cond = icmp ult i32 %iv.next, 1000 624 br i1 %loop.cond, label %loop, label %exit 625 626exit: 627 ret i32 %x 628 629cold_exit: 630 ret i32 -1 631} 632 633; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop. 634define i32 @test_inner_loop(i32* %p) { 635; CHECK-LABEL: @test_inner_loop( 636; CHECK-NEXT: entry: 637; CHECK-NEXT: br label [[LOOP:%.*]] 638; CHECK: loop: 639; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 640; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 641; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 642; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 643; CHECK: hot_path: 644; CHECK-NEXT: br label [[BACKEDGE]] 645; CHECK: cold_path: 646; CHECK-NEXT: br label [[INNER_LOOP:%.*]] 647; CHECK: inner_loop: 648; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 649; CHECK-NEXT: br i1 undef, label [[INNER_LOOP]], label [[BACKEDGE]] 650; CHECK: backedge: 651; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 652; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 653; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 654; CHECK: exit: 655; CHECK-NEXT: ret i32 [[X]] 656; 657entry: 658 br label %loop 659 660loop: 661 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 662 %x = load i32, i32* %p 663 %cond = icmp ne i32 %x, 0 664 br i1 %cond, label %hot_path, label %cold_path 665 666hot_path: 667 br label %backedge 668 669cold_path: 670 br label %inner_loop 671 672inner_loop: 673 call void @side_effect() nofree 674 br i1 undef, label %inner_loop, label %backedge 675 676backedge: 677 %iv.next = add i32 %iv, %x 678 %loop.cond = icmp ult i32 %iv.next, 1000 679 br i1 %loop.cond, label %loop, label %exit 680 681exit: 682 ret i32 %x 683} 684 685; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason. 686define i32 @test_multiple_cold_paths(i32* %p) { 687; CHECK-LABEL: @test_multiple_cold_paths( 688; CHECK-NEXT: entry: 689; CHECK-NEXT: br label [[LOOP:%.*]] 690; CHECK: loop: 691; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 692; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 693; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[X]], 0 694; CHECK-NEXT: br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]] 695; CHECK: hot_path.1: 696; CHECK-NEXT: br label [[DOM_1:%.*]] 697; CHECK: cold_path.1: 698; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 699; CHECK-NEXT: br label [[DOM_1]] 700; CHECK: dom.1: 701; CHECK-NEXT: [[COND_2:%.*]] = icmp ne i32 [[X]], 1 702; CHECK-NEXT: br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]] 703; CHECK: hot_path.2: 704; CHECK-NEXT: br label [[DOM_2:%.*]] 705; CHECK: cold_path.2: 706; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 707; CHECK-NEXT: br label [[DOM_2]] 708; CHECK: dom.2: 709; CHECK-NEXT: [[COND_3:%.*]] = icmp ne i32 [[X]], 2 710; CHECK-NEXT: br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]] 711; CHECK: hot_path.3: 712; CHECK-NEXT: br label [[BACKEDGE]] 713; CHECK: cold_path.3: 714; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 715; CHECK-NEXT: br label [[BACKEDGE]] 716; CHECK: backedge: 717; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 718; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 719; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 720; CHECK: exit: 721; CHECK-NEXT: ret i32 [[X]] 722; 723entry: 724 br label %loop 725 726loop: 727 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 728 %x = load i32, i32* %p 729 %cond.1 = icmp ne i32 %x, 0 730 br i1 %cond.1, label %hot_path.1, label %cold_path.1 731 732hot_path.1: 733 br label %dom.1 734 735cold_path.1: 736 call void @side_effect() nofree 737 br label %dom.1 738 739dom.1: 740 %cond.2 = icmp ne i32 %x, 1 741 br i1 %cond.2, label %hot_path.2, label %cold_path.2 742 743hot_path.2: 744 br label %dom.2 745 746cold_path.2: 747 call void @side_effect() nofree 748 br label %dom.2 749 750dom.2: 751 %cond.3 = icmp ne i32 %x, 2 752 br i1 %cond.3, label %hot_path.3, label %cold_path.3 753 754hot_path.3: 755 br label %backedge 756 757cold_path.3: 758 call void @side_effect() nofree 759 br label %backedge 760 761backedge: 762 %iv.next = add i32 %iv, %x 763 %loop.cond = icmp ult i32 %iv.next, 1000 764 br i1 %loop.cond, label %loop, label %exit 765 766exit: 767 ret i32 %x 768} 769 770; TODO: We can PRE via split of critical edge. 771define i32 @test_side_exit_after_merge(i32* %p) { 772; CHECK-LABEL: @test_side_exit_after_merge( 773; CHECK-NEXT: entry: 774; CHECK-NEXT: br label [[LOOP:%.*]] 775; CHECK: loop: 776; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 777; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 778; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0 779; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 780; CHECK: hot_path: 781; CHECK-NEXT: br label [[BACKEDGE]] 782; CHECK: cold_path: 783; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[IV]], 1 784; CHECK-NEXT: br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]] 785; CHECK: do_call: 786; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]] 787; CHECK-NEXT: br label [[SIDE_EXITING]] 788; CHECK: side_exiting: 789; CHECK-NEXT: [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ] 790; CHECK-NEXT: br i1 [[SIDE_COND_PHI]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]] 791; CHECK: backedge: 792; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 793; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 794; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 795; CHECK: exit: 796; CHECK-NEXT: ret i32 [[X]] 797; CHECK: cold_exit: 798; CHECK-NEXT: ret i32 -1 799; 800entry: 801 br label %loop 802 803loop: 804 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 805 %x = load i32, i32* %p 806 %cond = icmp ne i32 %x, 0 807 br i1 %cond, label %hot_path, label %cold_path 808 809hot_path: 810 br label %backedge 811 812cold_path: 813 %cond.1 = icmp ne i32 %iv, 1 814 br i1 %cond.1, label %do_call, label %side_exiting 815 816do_call: 817 %side_cond = call i1 @side_effect_cond() nofree 818 br label %side_exiting 819 820side_exiting: 821 %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path] 822 br i1 %side_cond_phi, label %backedge, label %cold_exit 823 824backedge: 825 %iv.next = add i32 %iv, %x 826 %loop.cond = icmp ult i32 %iv.next, 1000 827 br i1 %loop.cond, label %loop, label %exit 828 829exit: 830 ret i32 %x 831 832cold_exit: 833 ret i32 -1 834} 835 836declare void @llvm.experimental.guard(i1, ...) 837 838define i32 @test_guard_1(i32* %p, i32 %g) { 839; CHECK-LABEL: @test_guard_1( 840; CHECK-NEXT: entry: 841; CHECK-NEXT: br label [[LOOP:%.*]] 842; CHECK: loop: 843; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 844; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]] 845; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ] 846; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 847; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 848; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 849; CHECK: hot_path: 850; CHECK-NEXT: br label [[BACKEDGE]] 851; CHECK: cold_path: 852; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 853; CHECK-NEXT: br label [[BACKEDGE]] 854; CHECK: backedge: 855; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 856; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 857; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 858; CHECK: exit: 859; CHECK-NEXT: ret i32 [[X]] 860; 861entry: 862 br label %loop 863 864loop: 865 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 866 %guard_cond = icmp ne i32 %iv, %g 867 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ] 868 %x = load i32, i32* %p 869 %cond = icmp ult i32 %x, 100 870 br i1 %cond, label %hot_path, label %cold_path 871 872hot_path: 873 br label %backedge 874 875cold_path: 876 call void @side_effect() nofree 877 br label %backedge 878 879backedge: 880 %iv.next = add i32 %iv, %x 881 %loop.cond = icmp ult i32 %iv.next, 1000 882 br i1 %loop.cond, label %loop, label %exit 883 884exit: 885 ret i32 %x 886} 887 888define i32 @test_guard_2(i32* %p, i32 %g) { 889; CHECK-LABEL: @test_guard_2( 890; CHECK-NEXT: entry: 891; CHECK-NEXT: br label [[LOOP:%.*]] 892; CHECK: loop: 893; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 894; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]] 895; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4 896; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ] 897; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X]], 100 898; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]] 899; CHECK: hot_path: 900; CHECK-NEXT: br label [[BACKEDGE]] 901; CHECK: cold_path: 902; CHECK-NEXT: call void @side_effect() #[[ATTR0]] 903; CHECK-NEXT: br label [[BACKEDGE]] 904; CHECK: backedge: 905; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]] 906; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000 907; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]] 908; CHECK: exit: 909; CHECK-NEXT: ret i32 [[X]] 910; 911entry: 912 br label %loop 913 914loop: 915 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge] 916 %guard_cond = icmp ne i32 %iv, %g 917 %x = load i32, i32* %p 918 call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ] 919 %cond = icmp ult i32 %x, 100 920 br i1 %cond, label %hot_path, label %cold_path 921 922hot_path: 923 br label %backedge 924 925cold_path: 926 call void @side_effect() nofree 927 br label %backedge 928 929backedge: 930 %iv.next = add i32 %iv, %x 931 %loop.cond = icmp ult i32 %iv.next, 1000 932 br i1 %loop.cond, label %loop, label %exit 933 934exit: 935 ret i32 %x 936} 937