640 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -aa-pipeline=basic-aa -enable-load-pre -enable-pre -passes=gvn -S < %s | FileCheck %s --check-prefixes=CHECK,MDEP3; RUN: opt -aa-pipeline=basic-aa -enable-load-pre -enable-pre -passes='gvn<memoryssa>' -S < %s | FileCheck %s --check-prefixes=CHECK,MSSA4 5declare void @side_effect()6declare i1 @side_effect_cond()7 8declare i32 @personality_function()9 10; TODO: We can PRE the load away from the hot path.11define i32 @test_load_on_cold_path(ptr %p) {12; CHECK-LABEL: @test_load_on_cold_path(13; CHECK-NEXT: entry:14; CHECK-NEXT: br label [[LOOP:%.*]]15; CHECK: loop:16; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]17; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 418; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 019; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]20; CHECK: hot_path:21; CHECK-NEXT: br label [[BACKEDGE]]22; CHECK: cold_path:23; CHECK-NEXT: call void @side_effect()24; CHECK-NEXT: br label [[BACKEDGE]]25; CHECK: backedge:26; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]27; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100028; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]29; CHECK: exit:30; CHECK-NEXT: ret i32 [[X]]31;32entry:33 br label %loop34 35loop:36 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]37 %x = load i32, ptr %p38 %cond = icmp ne i32 %x, 039 br i1 %cond, label %hot_path, label %cold_path40 41hot_path:42 br label %backedge43 44cold_path:45 call void @side_effect()46 br label %backedge47 48backedge:49 %iv.next = add i32 %iv, %x50 %loop.cond = icmp ult i32 %iv.next, 100051 br i1 %loop.cond, label %loop, label %exit52 53exit:54 ret i32 %x55}56 57; PRE here is meaningless, so we should not do it.58define i32 @test_load_on_both_paths(ptr %p) {59; CHECK-LABEL: @test_load_on_both_paths(60; CHECK-NEXT: entry:61; CHECK-NEXT: br label [[LOOP:%.*]]62; CHECK: loop:63; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]64; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 465; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 066; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]67; CHECK: hot_path:68; CHECK-NEXT: call void @side_effect()69; CHECK-NEXT: br label [[BACKEDGE]]70; CHECK: cold_path:71; CHECK-NEXT: call void @side_effect()72; CHECK-NEXT: br label [[BACKEDGE]]73; CHECK: backedge:74; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]75; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 100076; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]77; CHECK: exit:78; CHECK-NEXT: ret i32 [[X]]79;80entry:81 br label %loop82 83loop:84 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]85 %x = load i32, ptr %p86 %cond = icmp ne i32 %x, 087 br i1 %cond, label %hot_path, label %cold_path88 89hot_path:90 call void @side_effect()91 br label %backedge92 93cold_path:94 call void @side_effect()95 br label %backedge96 97backedge:98 %iv.next = add i32 %iv, %x99 %loop.cond = icmp ult i32 %iv.next, 1000100 br i1 %loop.cond, label %loop, label %exit101 102exit:103 ret i32 %x104}105 106 107; We could PRE here, but it doesn't seem very profitable.108define i32 @test_load_on_backedge(ptr %p) {109; CHECK-LABEL: @test_load_on_backedge(110; CHECK-NEXT: entry:111; CHECK-NEXT: br label [[LOOP:%.*]]112; CHECK: loop:113; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]114; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4115; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0116; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]117; CHECK: hot_path:118; CHECK-NEXT: br label [[BACKEDGE]]119; CHECK: cold_path:120; CHECK-NEXT: br label [[BACKEDGE]]121; CHECK: backedge:122; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]123; CHECK-NEXT: call void @side_effect()124; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000125; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]126; CHECK: exit:127; CHECK-NEXT: ret i32 [[X]]128;129entry:130 br label %loop131 132loop:133 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]134 %x = load i32, ptr %p135 %cond = icmp ne i32 %x, 0136 br i1 %cond, label %hot_path, label %cold_path137 138hot_path:139 br label %backedge140 141cold_path:142 br label %backedge143 144backedge:145 %iv.next = add i32 %iv, %x146 call void @side_effect()147 %loop.cond = icmp ult i32 %iv.next, 1000148 br i1 %loop.cond, label %loop, label %exit149 150exit:151 ret i32 %x152}153 154; TODO: We can PRE via splitting of the critical edge in the cold path.155define i32 @test_load_on_exiting_cold_path_01(ptr %p) {156; CHECK-LABEL: @test_load_on_exiting_cold_path_01(157; CHECK-NEXT: entry:158; CHECK-NEXT: br label [[LOOP:%.*]]159; CHECK: loop:160; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]161; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4162; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0163; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]164; CHECK: hot_path:165; CHECK-NEXT: br label [[BACKEDGE]]166; CHECK: cold_path:167; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond()168; CHECK-NEXT: br i1 [[SIDE_COND]], label [[BACKEDGE]], label [[COLD_EXIT:%.*]]169; CHECK: backedge:170; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]171; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000172; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]173; CHECK: exit:174; CHECK-NEXT: ret i32 [[X]]175; CHECK: cold_exit:176; CHECK-NEXT: ret i32 -1177;178entry:179 br label %loop180 181loop:182 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]183 %x = load i32, ptr %p184 %cond = icmp ne i32 %x, 0185 br i1 %cond, label %hot_path, label %cold_path186 187hot_path:188 br label %backedge189 190cold_path:191 %side_cond = call i1 @side_effect_cond()192 br i1 %side_cond, label %backedge, label %cold_exit193 194backedge:195 %iv.next = add i32 %iv, %x196 %loop.cond = icmp ult i32 %iv.next, 1000197 br i1 %loop.cond, label %loop, label %exit198 199exit:200 ret i32 %x201 202cold_exit:203 ret i32 -1204}205 206; TODO: We can PRE via splitting of the critical edge in the cold path.207define i32 @test_load_on_exiting_cold_path_02(ptr %p) gc "statepoint-example" personality ptr @personality_function {208; CHECK-LABEL: @test_load_on_exiting_cold_path_02(209; CHECK-NEXT: entry:210; CHECK-NEXT: br label [[LOOP:%.*]]211; CHECK: loop:212; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]213; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4214; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0215; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]216; CHECK: hot_path:217; CHECK-NEXT: br label [[BACKEDGE]]218; CHECK: cold_path:219; CHECK-NEXT: invoke void @side_effect()220; CHECK-NEXT: to label [[BACKEDGE]] unwind label [[COLD_EXIT:%.*]]221; CHECK: backedge:222; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]223; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000224; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]225; CHECK: exit:226; CHECK-NEXT: ret i32 [[X]]227; CHECK: cold_exit:228; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad token229; CHECK-NEXT: cleanup230; CHECK-NEXT: ret i32 -1231;232entry:233 br label %loop234 235loop:236 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]237 %x = load i32, ptr %p238 %cond = icmp ne i32 %x, 0239 br i1 %cond, label %hot_path, label %cold_path240 241hot_path:242 br label %backedge243 244cold_path:245 invoke void @side_effect() to label %backedge unwind label %cold_exit246 247backedge:248 %iv.next = add i32 %iv, %x249 %loop.cond = icmp ult i32 %iv.next, 1000250 br i1 %loop.cond, label %loop, label %exit251 252exit:253 ret i32 %x254 255cold_exit:256 %landing_pad = landingpad token257 cleanup258 ret i32 -1259}260 261; Make sure we do not insert load into both cold path & backedge.262define i32 @test_load_on_cold_path_and_backedge(ptr %p) {263; CHECK-LABEL: @test_load_on_cold_path_and_backedge(264; CHECK-NEXT: entry:265; CHECK-NEXT: br label [[LOOP:%.*]]266; CHECK: loop:267; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]268; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4269; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0270; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]271; CHECK: hot_path:272; CHECK-NEXT: br label [[BACKEDGE]]273; CHECK: cold_path:274; CHECK-NEXT: call void @side_effect()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: call void @side_effect()280; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]281; CHECK: exit:282; CHECK-NEXT: ret i32 [[X]]283;284entry:285 br label %loop286 287loop:288 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]289 %x = load i32, ptr %p290 %cond = icmp ne i32 %x, 0291 br i1 %cond, label %hot_path, label %cold_path292 293hot_path:294 br label %backedge295 296cold_path:297 call void @side_effect()298 br label %backedge299 300backedge:301 %iv.next = add i32 %iv, %x302 %loop.cond = icmp ult i32 %iv.next, 1000303 call void @side_effect()304 br i1 %loop.cond, label %loop, label %exit305 306exit:307 ret i32 %x308}309 310; TODO: We can PRE the load away from the hot path. Make sure we only insert 1 load.311define i32 @test_load_multi_block_cold_path(ptr %p) {312; CHECK-LABEL: @test_load_multi_block_cold_path(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_1:%.*]]320; CHECK: hot_path:321; CHECK-NEXT: br label [[BACKEDGE]]322; CHECK: cold_path.1:323; CHECK-NEXT: call void @side_effect()324; CHECK-NEXT: call void @side_effect()325; CHECK-NEXT: call void @side_effect()326; CHECK-NEXT: br label [[BACKEDGE]]327; CHECK: backedge:328; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]329; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000330; CHECK-NEXT: call void @side_effect()331; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]332; CHECK: exit:333; CHECK-NEXT: ret i32 [[X]]334;335entry:336 br label %loop337 338loop:339 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]340 %x = load i32, ptr %p341 %cond = icmp ne i32 %x, 0342 br i1 %cond, label %hot_path, label %cold_path.1343 344hot_path:345 br label %backedge346 347cold_path.1:348 call void @side_effect()349 br label %cold_path.2350 351cold_path.2:352 call void @side_effect()353 br label %cold_path.3354 355cold_path.3:356 call void @side_effect()357 br label %backedge358 359backedge:360 %iv.next = add i32 %iv, %x361 %loop.cond = icmp ult i32 %iv.next, 1000362 call void @side_effect()363 br i1 %loop.cond, label %loop, label %exit364 365exit:366 ret i32 %x367}368 369; TODO: We can PRE via splitting of the critical edge in the cold path. Make sure we only insert 1 load.370define i32 @test_load_on_multi_exiting_cold_path(ptr %p) {371; CHECK-LABEL: @test_load_on_multi_exiting_cold_path(372; CHECK-NEXT: entry:373; CHECK-NEXT: br label [[LOOP:%.*]]374; CHECK: loop:375; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]376; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4377; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0378; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH_1:%.*]]379; CHECK: hot_path:380; CHECK-NEXT: br label [[BACKEDGE]]381; CHECK: cold_path.1:382; CHECK-NEXT: [[SIDE_COND_1:%.*]] = call i1 @side_effect_cond()383; CHECK-NEXT: br i1 [[SIDE_COND_1]], label [[COLD_PATH_2:%.*]], label [[COLD_EXIT:%.*]]384; CHECK: cold_path.2:385; CHECK-NEXT: [[SIDE_COND_2:%.*]] = call i1 @side_effect_cond()386; CHECK-NEXT: br i1 [[SIDE_COND_2]], label [[COLD_PATH_3:%.*]], label [[COLD_EXIT]]387; CHECK: cold_path.3:388; CHECK-NEXT: [[SIDE_COND_3:%.*]] = call i1 @side_effect_cond()389; CHECK-NEXT: br i1 [[SIDE_COND_3]], label [[BACKEDGE]], label [[COLD_EXIT]]390; CHECK: backedge:391; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]392; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000393; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]394; CHECK: exit:395; CHECK-NEXT: ret i32 [[X]]396; CHECK: cold_exit:397; CHECK-NEXT: ret i32 -1398;399entry:400 br label %loop401 402loop:403 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]404 %x = load i32, ptr %p405 %cond = icmp ne i32 %x, 0406 br i1 %cond, label %hot_path, label %cold_path.1407 408hot_path:409 br label %backedge410 411cold_path.1:412 %side_cond.1 = call i1 @side_effect_cond()413 br i1 %side_cond.1, label %cold_path.2, label %cold_exit414 415cold_path.2:416 %side_cond.2 = call i1 @side_effect_cond()417 br i1 %side_cond.2, label %cold_path.3, label %cold_exit418 419cold_path.3:420 %side_cond.3 = call i1 @side_effect_cond()421 br i1 %side_cond.3, label %backedge, label %cold_exit422 423backedge:424 %iv.next = add i32 %iv, %x425 %loop.cond = icmp ult i32 %iv.next, 1000426 br i1 %loop.cond, label %loop, label %exit427 428exit:429 ret i32 %x430 431cold_exit:432 ret i32 -1433}434 435; TODO: PRE via splittinga backedge in the cold loop. Make sure we don't insert a load into an inner loop.436define i32 @test_inner_loop(ptr %p, i1 %arg) {437; CHECK-LABEL: @test_inner_loop(438; CHECK-NEXT: entry:439; CHECK-NEXT: br label [[LOOP:%.*]]440; CHECK: loop:441; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]442; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4443; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0444; CHECK-NEXT: br i1 [[COND]], label [[HOT_PATH:%.*]], label [[COLD_PATH:%.*]]445; CHECK: hot_path:446; CHECK-NEXT: br label [[BACKEDGE]]447; CHECK: cold_path:448; CHECK-NEXT: br label [[INNER_LOOP:%.*]]449; CHECK: inner_loop:450; CHECK-NEXT: call void @side_effect()451; CHECK-NEXT: br i1 [[ARG:%.*]], label [[INNER_LOOP]], label [[BACKEDGE]]452; CHECK: backedge:453; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]454; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000455; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]456; CHECK: exit:457; CHECK-NEXT: ret i32 [[X]]458;459entry:460 br label %loop461 462loop:463 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]464 %x = load i32, ptr %p465 %cond = icmp ne i32 %x, 0466 br i1 %cond, label %hot_path, label %cold_path467 468hot_path:469 br label %backedge470 471cold_path:472 br label %inner_loop473 474inner_loop:475 call void @side_effect()476 br i1 %arg, label %inner_loop, label %backedge477 478backedge:479 %iv.next = add i32 %iv, %x480 %loop.cond = icmp ult i32 %iv.next, 1000481 br i1 %loop.cond, label %loop, label %exit482 483exit:484 ret i32 %x485}486 487; TODO: We can PRE here, but profitablility depends on frequency of cold blocks. Conservatively, we should not do it unless there is a reason.488define i32 @test_multiple_cold_paths(ptr %p) {489; CHECK-LABEL: @test_multiple_cold_paths(490; CHECK-NEXT: entry:491; CHECK-NEXT: br label [[LOOP:%.*]]492; CHECK: loop:493; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]494; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4495; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[X]], 0496; CHECK-NEXT: br i1 [[COND_1]], label [[HOT_PATH_1:%.*]], label [[COLD_PATH_1:%.*]]497; CHECK: hot_path.1:498; CHECK-NEXT: br label [[DOM_1:%.*]]499; CHECK: cold_path.1:500; CHECK-NEXT: call void @side_effect()501; CHECK-NEXT: br label [[DOM_1]]502; CHECK: dom.1:503; CHECK-NEXT: [[COND_2:%.*]] = icmp ne i32 [[X]], 1504; CHECK-NEXT: br i1 [[COND_2]], label [[HOT_PATH_2:%.*]], label [[COLD_PATH_2:%.*]]505; CHECK: hot_path.2:506; CHECK-NEXT: br label [[DOM_2:%.*]]507; CHECK: cold_path.2:508; CHECK-NEXT: call void @side_effect()509; CHECK-NEXT: br label [[DOM_2]]510; CHECK: dom.2:511; CHECK-NEXT: [[COND_3:%.*]] = icmp ne i32 [[X]], 2512; CHECK-NEXT: br i1 [[COND_3]], label [[HOT_PATH_3:%.*]], label [[COLD_PATH_3:%.*]]513; CHECK: hot_path.3:514; CHECK-NEXT: br label [[BACKEDGE]]515; CHECK: cold_path.3:516; CHECK-NEXT: call void @side_effect()517; CHECK-NEXT: br label [[BACKEDGE]]518; CHECK: backedge:519; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[X]]520; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], 1000521; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]522; CHECK: exit:523; CHECK-NEXT: ret i32 [[X]]524;525entry:526 br label %loop527 528loop:529 %iv = phi i32 [ 0, %entry], [%iv.next, %backedge]530 %x = load i32, ptr %p531 %cond.1 = icmp ne i32 %x, 0532 br i1 %cond.1, label %hot_path.1, label %cold_path.1533 534hot_path.1:535 br label %dom.1536 537cold_path.1:538 call void @side_effect()539 br label %dom.1540 541dom.1:542 %cond.2 = icmp ne i32 %x, 1543 br i1 %cond.2, label %hot_path.2, label %cold_path.2544 545hot_path.2:546 br label %dom.2547 548cold_path.2:549 call void @side_effect()550 br label %dom.2551 552dom.2:553 %cond.3 = icmp ne i32 %x, 2554 br i1 %cond.3, label %hot_path.3, label %cold_path.3555 556hot_path.3:557 br label %backedge558 559cold_path.3:560 call void @side_effect()561 br label %backedge562 563backedge:564 %iv.next = add i32 %iv, %x565 %loop.cond = icmp ult i32 %iv.next, 1000566 br i1 %loop.cond, label %loop, label %exit567 568exit:569 ret i32 %x570}571 572; TODO: We can PRE via split of critical edge.573define i32 @test_side_exit_after_merge(ptr %p) {574; CHECK-LABEL: @test_side_exit_after_merge(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:%.*]]582; CHECK: hot_path:583; CHECK-NEXT: br label [[BACKEDGE]]584; CHECK: cold_path:585; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[IV]], 1586; CHECK-NEXT: br i1 [[COND_1]], label [[DO_CALL:%.*]], label [[SIDE_EXITING:%.*]]587; CHECK: do_call:588; CHECK-NEXT: [[SIDE_COND:%.*]] = call i1 @side_effect_cond()589; CHECK-NEXT: br label [[SIDE_EXITING]]590; CHECK: side_exiting:591; CHECK-NEXT: [[SIDE_COND_PHI:%.*]] = phi i1 [ [[SIDE_COND]], [[DO_CALL]] ], [ true, [[COLD_PATH]] ]592; CHECK-NEXT: br i1 [[SIDE_COND_PHI]], 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_path610 611hot_path:612 br label %backedge613 614cold_path:615 %cond.1 = icmp ne i32 %iv, 1616 br i1 %cond.1, label %do_call, label %side_exiting617 618do_call:619 %side_cond = call i1 @side_effect_cond()620 br label %side_exiting621 622side_exiting:623 %side_cond_phi = phi i1 [%side_cond, %do_call], [true, %cold_path]624 br i1 %side_cond_phi, 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;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:638; MDEP: {{.*}}639; MSSA: {{.*}}640