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