brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.3 KiB · a9b69a4 Raw
942 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -enable-load-pre -enable-pre -passes=lcssa,gvn -S < %s | FileCheck %s3 4declare void @side_effect() nofree5declare i1 @side_effect_cond() nofree6declare 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(ptr addrspace(1) %p) gc "statepoint-example" personality ptr @"personality_function" {12; CHECK-LABEL: @test_load_on_cold_path_gc(13; CHECK-NEXT:  entry:14; CHECK-NEXT:    [[X_PRE1:%.*]] = load i32, ptr addrspace(1) [[P:%.*]], align 415; 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]], 020; 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, ptr addrspace(1) [[P]], align 426; 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]], 100031; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]32; CHECK:       exit:33; CHECK-NEXT:    ret i32 [[X]]34;35entry:36  br label %loop37 38loop:39  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]40  %x = load i32, ptr addrspace(1) %p41  %cond = icmp ne i32 %x, 042  br i1 %cond, label %hot_path, label %cold_path43 44hot_path:45  br label %backedge46 47cold_path:48  call void @may_free_memory()49  br label %backedge50 51backedge:52  %iv.next = add i32 %iv, %x53  %loop.cond = icmp ult i32 %iv.next, 100054  br i1 %loop.cond, label %loop, label %exit55 56exit:57  ret i32 %x58}59 60; Do not PRE here because a loop-variant pointer.61define i32 @test_load_on_cold_path_gc_variant_neg(ptr addrspace(1) %pp) gc "statepoint-example" personality ptr @"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 ptr addrspace(1), ptr addrspace(1) [[PP:%.*]], align 868; CHECK-NEXT:    [[X:%.*]] = load i32, ptr addrspace(1) [[P]], align 469; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 070; 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]], 100079; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]80; CHECK:       exit:81; CHECK-NEXT:    ret i32 [[X]]82;83entry:84  br label %loop85 86loop:87  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]88  %p = load volatile ptr addrspace(1), ptr addrspace(1) %pp89  %x = load i32, ptr addrspace(1) %p90  %cond = icmp ne i32 %x, 091  br i1 %cond, label %hot_path, label %cold_path92 93hot_path:94  br label %backedge95 96cold_path:97  call void @may_free_memory()98  br label %backedge99 100backedge:101  %iv.next = add i32 %iv, %x102  %loop.cond = icmp ult i32 %iv.next, 1000103  br i1 %loop.cond, label %loop, label %exit104 105exit:106  ret i32 %x107}108 109 110; TODO: We can PRE the load away from the hot path.111define i32 @test_load_on_cold_path(ptr %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, ptr [[P:%.*]], align 4118; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0119; 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]], 1000128; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]129; CHECK:       exit:130; CHECK-NEXT:    ret i32 [[X]]131;132entry:133  br label %loop134 135loop:136  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]137  %x = load i32, ptr %p138  %cond = icmp ne i32 %x, 0139  br i1 %cond, label %hot_path, label %cold_path140 141hot_path:142  br label %backedge143 144cold_path:145  call void @side_effect() nofree146  br label %backedge147 148backedge:149  %iv.next = add i32 %iv, %x150  %loop.cond = icmp ult i32 %iv.next, 1000151  br i1 %loop.cond, label %loop, label %exit152 153exit:154  ret i32 %x155}156 157; We should NOT PRE here because the function on the cold path may possibly158; free the memory under the pointer.159define i32 @test_load_on_cold_path_may_free_memory_neg(ptr %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, ptr [[P:%.*]], align 4166; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0167; 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]], 1000176; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]177; CHECK:       exit:178; CHECK-NEXT:    ret i32 [[X]]179;180entry:181  br label %loop182 183loop:184  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]185  %x = load i32, ptr %p186  %cond = icmp ne i32 %x, 0187  br i1 %cond, label %hot_path, label %cold_path188 189hot_path:190  br label %backedge191 192cold_path:193  call void @may_free_memory()194  br label %backedge195 196backedge:197  %iv.next = add i32 %iv, %x198  %loop.cond = icmp ult i32 %iv.next, 1000199  br i1 %loop.cond, label %loop, label %exit200 201exit:202  ret i32 %x203}204 205declare void @may_modify_or_free_pointer(ptr %p)206 207; TODO: Despite the fact that the function may free memory in general, it208; cannot free memory allocated by alloca.209define i32 @test_load_on_cold_path_may_free_memory_alloca() {210; CHECK-LABEL: @test_load_on_cold_path_may_free_memory_alloca(211; CHECK-NEXT:  entry:212; CHECK-NEXT:    [[P:%.*]] = alloca i32, align 4213; CHECK-NEXT:    call void @may_modify_or_free_pointer(ptr [[P]])214; CHECK-NEXT:    br label [[LOOP:%.*]]215; CHECK:       loop:216; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]217; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P]], align 4218; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0219; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]220; CHECK:       hot_path:221; CHECK-NEXT:    br label [[BACKEDGE]]222; CHECK:       cold_path:223; CHECK-NEXT:    call void @may_modify_or_free_pointer(ptr [[P]])224; CHECK-NEXT:    br label [[BACKEDGE]]225; CHECK:       backedge:226; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]227; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000228; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]229; CHECK:       exit:230; CHECK-NEXT:    ret i32 [[X]]231;232entry:233  %p = alloca i32234  call void @may_modify_or_free_pointer(ptr %p)235  br label %loop236 237loop:238  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]239  %x = load i32, ptr %p240  %cond = icmp ne i32 %x, 0241  br i1 %cond, label %hot_path, label %cold_path242 243hot_path:244  br label %backedge245 246cold_path:247  call void @may_modify_or_free_pointer(ptr %p)248  br label %backedge249 250backedge:251  %iv.next = add i32 %iv, %x252  %loop.cond = icmp ult i32 %iv.next, 1000253  br i1 %loop.cond, label %loop, label %exit254 255exit:256  ret i32 %x257}258 259 260; PRE here is meaningless, so we should not do it.261define i32 @test_load_on_both_paths(ptr %p) {262; CHECK-LABEL: @test_load_on_both_paths(263; CHECK-NEXT:  entry:264; CHECK-NEXT:    br label [[LOOP:%.*]]265; CHECK:       loop:266; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]267; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4268; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0269; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]270; CHECK:       hot_path:271; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]272; CHECK-NEXT:    br label [[BACKEDGE]]273; CHECK:       cold_path:274; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]275; CHECK-NEXT:    br label [[BACKEDGE]]276; CHECK:       backedge:277; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]278; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000279; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]280; CHECK:       exit:281; CHECK-NEXT:    ret i32 [[X]]282;283entry:284  br label %loop285 286loop:287  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]288  %x = load i32, ptr %p289  %cond = icmp ne i32 %x, 0290  br i1 %cond, label %hot_path, label %cold_path291 292hot_path:293  call void @side_effect() nofree294  br label %backedge295 296cold_path:297  call void @side_effect() nofree298  br label %backedge299 300backedge:301  %iv.next = add i32 %iv, %x302  %loop.cond = icmp ult i32 %iv.next, 1000303  br i1 %loop.cond, label %loop, label %exit304 305exit:306  ret i32 %x307}308 309 310; We could PRE here, but it doesn't seem very profitable.311define i32 @test_load_on_backedge(ptr %p) {312; CHECK-LABEL: @test_load_on_backedge(313; CHECK-NEXT:  entry:314; CHECK-NEXT:    br label [[LOOP:%.*]]315; CHECK:       loop:316; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]317; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4318; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0319; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]320; CHECK:       hot_path:321; CHECK-NEXT:    br label [[BACKEDGE]]322; CHECK:       cold_path:323; CHECK-NEXT:    br label [[BACKEDGE]]324; CHECK:       backedge:325; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]326; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]327; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000328; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]329; CHECK:       exit:330; CHECK-NEXT:    ret i32 [[X]]331;332entry:333  br label %loop334 335loop:336  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]337  %x = load i32, ptr %p338  %cond = icmp ne i32 %x, 0339  br i1 %cond, label %hot_path, label %cold_path340 341hot_path:342  br label %backedge343 344cold_path:345  br label %backedge346 347backedge:348  %iv.next = add i32 %iv, %x349  call void @side_effect() nofree350  %loop.cond = icmp ult i32 %iv.next, 1000351  br i1 %loop.cond, label %loop, label %exit352 353exit:354  ret i32 %x355}356 357; TODO: We can PRE via splitting of the critical edge in the cold path.358define i32 @test_load_on_exiting_cold_path_01(ptr %p) {359; CHECK-LABEL: @test_load_on_exiting_cold_path_01(360; CHECK-NEXT:  entry:361; CHECK-NEXT:    br label [[LOOP:%.*]]362; CHECK:       loop:363; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]364; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4365; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0366; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]367; CHECK:       hot_path:368; CHECK-NEXT:    br label [[BACKEDGE]]369; CHECK:       cold_path:370; CHECK-NEXT:    [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]371; CHECK-NEXT:    br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]372; CHECK:       backedge:373; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]374; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000375; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]376; CHECK:       exit:377; CHECK-NEXT:    ret i32 [[X]]378; CHECK:       cold_exit:379; CHECK-NEXT:    ret i32 -1380;381entry:382  br label %loop383 384loop:385  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]386  %x = load i32, ptr %p387  %cond = icmp ne i32 %x, 0388  br i1 %cond, label %hot_path, label %cold_path389 390hot_path:391  br label %backedge392 393cold_path:394  %side_cond = call i1 @side_effect_cond() nofree395  br i1 %side_cond, label %backedge, label %cold_exit396 397backedge:398  %iv.next = add i32 %iv, %x399  %loop.cond = icmp ult i32 %iv.next, 1000400  br i1 %loop.cond, label %loop, label %exit401 402exit:403  ret i32 %x404 405cold_exit:406  ret i32 -1407}408 409; TODO: We can PRE via splitting of the critical edge in the cold path.410define i32 @test_load_on_exiting_cold_path_02(ptr %p) gc "statepoint-example" personality ptr @personality_function {411; CHECK-LABEL: @test_load_on_exiting_cold_path_02(412; CHECK-NEXT:  entry:413; CHECK-NEXT:    br label [[LOOP:%.*]]414; CHECK:       loop:415; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]416; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4417; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0418; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]419; CHECK:       hot_path:420; CHECK-NEXT:    br label [[BACKEDGE]]421; CHECK:       cold_path:422; CHECK-NEXT:    invoke void @side_effect()423; CHECK-NEXT:    to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]]424; CHECK:       backedge:425; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]426; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000427; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]428; CHECK:       exit:429; CHECK-NEXT:    ret i32 [[X]]430; CHECK:       cold_exit:431; CHECK-NEXT:    [[LANDING_PAD:%.*]] = landingpad token432; CHECK-NEXT:    cleanup433; CHECK-NEXT:    ret i32 -1434;435entry:436  br label %loop437 438loop:439  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]440  %x = load i32, ptr %p441  %cond = icmp ne i32 %x, 0442  br i1 %cond, label %hot_path, label %cold_path443 444hot_path:445  br label %backedge446 447cold_path:448  invoke void @side_effect() to label %backedge unwind label %cold_exit449 450backedge:451  %iv.next = add i32 %iv, %x452  %loop.cond = icmp ult i32 %iv.next, 1000453  br i1 %loop.cond, label %loop, label %exit454 455exit:456  ret i32 %x457 458cold_exit:459  %landing_pad = landingpad token460  cleanup461  ret i32 -1462}463 464; Make sure we do not insert load into both cold path & backedge.465define i32 @test_load_on_cold_path_and_backedge(ptr %p) {466; CHECK-LABEL: @test_load_on_cold_path_and_backedge(467; CHECK-NEXT:  entry:468; CHECK-NEXT:    br label [[LOOP:%.*]]469; CHECK:       loop:470; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]471; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4472; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0473; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]474; CHECK:       hot_path:475; CHECK-NEXT:    br label [[BACKEDGE]]476; CHECK:       cold_path:477; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]478; CHECK-NEXT:    br label [[BACKEDGE]]479; CHECK:       backedge:480; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]481; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000482; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]483; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]484; CHECK:       exit:485; CHECK-NEXT:    ret i32 [[X]]486;487entry:488  br label %loop489 490loop:491  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]492  %x = load i32, ptr %p493  %cond = icmp ne i32 %x, 0494  br i1 %cond, label %hot_path, label %cold_path495 496hot_path:497  br label %backedge498 499cold_path:500  call void @side_effect() nofree501  br label %backedge502 503backedge:504  %iv.next = add i32 %iv, %x505  %loop.cond = icmp ult i32 %iv.next, 1000506  call void @side_effect() nofree507  br i1 %loop.cond, label %loop, label %exit508 509exit:510  ret i32 %x511}512 513; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load.514define i32 @test_load_multi_block_cold_path(ptr %p) {515; CHECK-LABEL: @test_load_multi_block_cold_path(516; CHECK-NEXT:  entry:517; CHECK-NEXT:    br label [[LOOP:%.*]]518; CHECK:       loop:519; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]520; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4521; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0522; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]523; CHECK:       hot_path:524; CHECK-NEXT:    br label [[BACKEDGE]]525; CHECK:       cold_path.1:526; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]527; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]528; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]529; CHECK-NEXT:    br label [[BACKEDGE]]530; CHECK:       backedge:531; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]532; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000533; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]534; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]535; CHECK:       exit:536; CHECK-NEXT:    ret i32 [[X]]537;538entry:539  br label %loop540 541loop:542  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]543  %x = load i32, ptr %p544  %cond = icmp ne i32 %x, 0545  br i1 %cond, label %hot_path, label %cold_path.1546 547hot_path:548  br label %backedge549 550cold_path.1:551  call void @side_effect() nofree552  br label %cold_path.2553 554cold_path.2:555  call void @side_effect() nofree556  br label %cold_path.3557 558cold_path.3:559  call void @side_effect() nofree560  br label %backedge561 562backedge:563  %iv.next = add i32 %iv, %x564  %loop.cond = icmp ult i32 %iv.next, 1000565  call void @side_effect() nofree566  br i1 %loop.cond, label %loop, label %exit567 568exit:569  ret i32 %x570}571 572; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load.573define i32 @test_load_on_multi_exiting_cold_path(ptr %p) {574; CHECK-LABEL: @test_load_on_multi_exiting_cold_path(575; CHECK-NEXT:  entry:576; CHECK-NEXT:    br label [[LOOP:%.*]]577; CHECK:       loop:578; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]579; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4580; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0581; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]582; CHECK:       hot_path:583; CHECK-NEXT:    br label [[BACKEDGE]]584; CHECK:       cold_path.1:585; CHECK-NEXT:    [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]586; CHECK-NEXT:    br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]]587; CHECK:       cold_path.2:588; CHECK-NEXT:    [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]589; CHECK-NEXT:    br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]]590; CHECK:       cold_path.3:591; CHECK-NEXT:    [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]592; CHECK-NEXT:    br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]]593; CHECK:       backedge:594; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]595; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000596; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]597; CHECK:       exit:598; CHECK-NEXT:    ret i32 [[X]]599; CHECK:       cold_exit:600; CHECK-NEXT:    ret i32 -1601;602entry:603  br label %loop604 605loop:606  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]607  %x = load i32, ptr %p608  %cond = icmp ne i32 %x, 0609  br i1 %cond, label %hot_path, label %cold_path.1610 611hot_path:612  br label %backedge613 614cold_path.1:615  %side_cond.1 = call i1 @side_effect_cond() nofree616  br i1 %side_cond.1, label %cold_path.2, label %cold_exit617 618cold_path.2:619  %side_cond.2 = call i1 @side_effect_cond() nofree620  br i1 %side_cond.2, label %cold_path.3, label %cold_exit621 622cold_path.3:623  %side_cond.3 = call i1 @side_effect_cond() nofree624  br i1 %side_cond.3, label %backedge, label %cold_exit625 626backedge:627  %iv.next = add i32 %iv, %x628  %loop.cond = icmp ult i32 %iv.next, 1000629  br i1 %loop.cond, label %loop, label %exit630 631exit:632  ret i32 %x633 634cold_exit:635  ret i32 -1636}637 638; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop.639define i32 @test_inner_loop(ptr %p, i1 %arg) {640; CHECK-LABEL: @test_inner_loop(641; CHECK-NEXT:  entry:642; CHECK-NEXT:    br label [[LOOP:%.*]]643; CHECK:       loop:644; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]645; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4646; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0647; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]648; CHECK:       hot_path:649; CHECK-NEXT:    br label [[BACKEDGE]]650; CHECK:       cold_path:651; CHECK-NEXT:    br label [[INNER_LOOP:%.*]]652; CHECK:       inner_loop:653; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]654; CHECK-NEXT:    br i1 %arg, label [[INNER_LOOP]], label [[BACKEDGE]]655; CHECK:       backedge:656; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]657; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000658; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]659; CHECK:       exit:660; CHECK-NEXT:    ret i32 [[X]]661;662entry:663  br label %loop664 665loop:666  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]667  %x = load i32, ptr %p668  %cond = icmp ne i32 %x, 0669  br i1 %cond, label %hot_path, label %cold_path670 671hot_path:672  br label %backedge673 674cold_path:675  br label %inner_loop676 677inner_loop:678  call void @side_effect() nofree679  br i1 %arg, label %inner_loop, label %backedge680 681backedge:682  %iv.next = add i32 %iv, %x683  %loop.cond = icmp ult i32 %iv.next, 1000684  br i1 %loop.cond, label %loop, label %exit685 686exit:687  ret i32 %x688}689 690; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason.691define i32 @test_multiple_cold_paths(ptr %p) {692; CHECK-LABEL: @test_multiple_cold_paths(693; CHECK-NEXT:  entry:694; CHECK-NEXT:    br label [[LOOP:%.*]]695; CHECK:       loop:696; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]697; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4698; CHECK-NEXT:    [[COND_1:%.*]] = icmp ne i32 [[X]], 0699; CHECK-NEXT:    br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]]700; CHECK:       hot_path.1:701; CHECK-NEXT:    br label [[DOM_1:%.*]]702; CHECK:       cold_path.1:703; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]704; CHECK-NEXT:    br label [[DOM_1]]705; CHECK:       dom.1:706; CHECK-NEXT:    [[COND_2:%.*]] = icmp ne i32 [[X]], 1707; CHECK-NEXT:    br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]]708; CHECK:       hot_path.2:709; CHECK-NEXT:    br label [[DOM_2:%.*]]710; CHECK:       cold_path.2:711; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]712; CHECK-NEXT:    br label [[DOM_2]]713; CHECK:       dom.2:714; CHECK-NEXT:    [[COND_3:%.*]] = icmp ne i32 [[X]], 2715; CHECK-NEXT:    br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]]716; CHECK:       hot_path.3:717; CHECK-NEXT:    br label [[BACKEDGE]]718; CHECK:       cold_path.3:719; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]720; CHECK-NEXT:    br label [[BACKEDGE]]721; CHECK:       backedge:722; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]723; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000724; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]725; CHECK:       exit:726; CHECK-NEXT:    ret i32 [[X]]727;728entry:729  br label %loop730 731loop:732  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]733  %x = load i32, ptr %p734  %cond.1 = icmp ne i32 %x, 0735  br i1 %cond.1, label %hot_path.1, label %cold_path.1736 737hot_path.1:738  br label %dom.1739 740cold_path.1:741  call void @side_effect() nofree742  br label %dom.1743 744dom.1:745  %cond.2 = icmp ne i32 %x, 1746  br i1 %cond.2, label %hot_path.2, label %cold_path.2747 748hot_path.2:749  br label %dom.2750 751cold_path.2:752  call void @side_effect() nofree753  br label %dom.2754 755dom.2:756  %cond.3 = icmp ne i32 %x, 2757  br i1 %cond.3, label %hot_path.3, label %cold_path.3758 759hot_path.3:760  br label %backedge761 762cold_path.3:763  call void @side_effect() nofree764  br label %backedge765 766backedge:767  %iv.next = add i32 %iv, %x768  %loop.cond = icmp ult i32 %iv.next, 1000769  br i1 %loop.cond, label %loop, label %exit770 771exit:772  ret i32 %x773}774 775; TODO: We can PRE via split of critical edge.776define i32 @test_side_exit_after_merge(ptr %p) {777; CHECK-LABEL: @test_side_exit_after_merge(778; CHECK-NEXT:  entry:779; CHECK-NEXT:    br label [[LOOP:%.*]]780; CHECK:       loop:781; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]782; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4783; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[X]], 0784; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]785; CHECK:       hot_path:786; CHECK-NEXT:    br label [[BACKEDGE]]787; CHECK:       cold_path:788; CHECK-NEXT:    [[COND_1:%.*]] = icmp ne i32 [[IV]], 1789; CHECK-NEXT:    br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]]790; CHECK:       do_call:791; CHECK-NEXT:    [[SIDE_COND:%.*]] = call i1 @side_effect_cond() #[[ATTR0]]792; CHECK-NEXT:    br label [[SIDE_EXITING]]793; CHECK:       side_exiting:794; CHECK-NEXT:    [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ]795; CHECK-NEXT:    br i1 [[SIDE_COND_PHI]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]796; CHECK:       backedge:797; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]798; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000799; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]800; CHECK:       exit:801; CHECK-NEXT:    ret i32 [[X]]802; CHECK:       cold_exit:803; CHECK-NEXT:    ret i32 -1804;805entry:806  br label %loop807 808loop:809  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]810  %x = load i32, ptr %p811  %cond = icmp ne i32 %x, 0812  br i1 %cond, label %hot_path, label %cold_path813 814hot_path:815  br label %backedge816 817cold_path:818  %cond.1 = icmp ne i32 %iv, 1819  br i1 %cond.1, label %do_call, label %side_exiting820 821do_call:822  %side_cond = call i1 @side_effect_cond() nofree823  br label %side_exiting824 825side_exiting:826  %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path]827  br i1 %side_cond_phi, label %backedge, label %cold_exit828 829backedge:830  %iv.next = add i32 %iv, %x831  %loop.cond = icmp ult i32 %iv.next, 1000832  br i1 %loop.cond, label %loop, label %exit833 834exit:835  ret i32 %x836 837cold_exit:838  ret i32 -1839}840 841declare void @llvm.experimental.guard(i1, ...)842 843define i32 @test_guard_1(ptr %p, i32 %g) {844; CHECK-LABEL: @test_guard_1(845; CHECK-NEXT:  entry:846; CHECK-NEXT:    br label [[LOOP:%.*]]847; CHECK:       loop:848; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]849; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]850; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]851; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4852; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[X]], 100853; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]854; CHECK:       hot_path:855; CHECK-NEXT:    br label [[BACKEDGE]]856; CHECK:       cold_path:857; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]858; CHECK-NEXT:    br label [[BACKEDGE]]859; CHECK:       backedge:860; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]861; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000862; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]863; CHECK:       exit:864; CHECK-NEXT:    ret i32 [[X]]865;866entry:867  br label %loop868 869loop:870  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]871  %guard_cond = icmp ne i32 %iv, %g872  call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]873  %x = load i32, ptr %p874  %cond = icmp ult i32 %x, 100875  br i1 %cond, label %hot_path, label %cold_path876 877hot_path:878  br label %backedge879 880cold_path:881  call void @side_effect() nofree882  br label %backedge883 884backedge:885  %iv.next = add i32 %iv, %x886  %loop.cond = icmp ult i32 %iv.next, 1000887  br i1 %loop.cond, label %loop, label %exit888 889exit:890  ret i32 %x891}892 893define i32 @test_guard_2(ptr %p, i32 %g) {894; CHECK-LABEL: @test_guard_2(895; CHECK-NEXT:  entry:896; CHECK-NEXT:    br label [[LOOP:%.*]]897; CHECK:       loop:898; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]899; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp ne i32 [[IV]], [[G:%.*]]900; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P:%.*]], align 4901; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]]) [ "deopt"() ]902; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[X]], 100903; CHECK-NEXT:    br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]904; CHECK:       hot_path:905; CHECK-NEXT:    br label [[BACKEDGE]]906; CHECK:       cold_path:907; CHECK-NEXT:    call void @side_effect() #[[ATTR0]]908; CHECK-NEXT:    br label [[BACKEDGE]]909; CHECK:       backedge:910; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], [[X]]911; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000912; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]913; CHECK:       exit:914; CHECK-NEXT:    ret i32 [[X]]915;916entry:917  br label %loop918 919loop:920  %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]921  %guard_cond = icmp ne i32 %iv, %g922  %x = load i32, ptr %p923  call void(i1, ...) @llvm.experimental.guard(i1 %guard_cond) [ "deopt"() ]924  %cond = icmp ult i32 %x, 100925  br i1 %cond, label %hot_path, label %cold_path926 927hot_path:928  br label %backedge929 930cold_path:931  call void @side_effect() nofree932  br label %backedge933 934backedge:935  %iv.next = add i32 %iv, %x936  %loop.cond = icmp ult i32 %iv.next, 1000937  br i1 %loop.cond, label %loop, label %exit938 939exit:940  ret i32 %x941}942