brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.6 KiB · 7750141 Raw
978 lines · plain
1; Test that llvm-reduce can move intermediate values by inserting2; early returns3;4; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions-to-return --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t5; RUN: FileCheck --check-prefixes=CHECK,RESULT %s < %t6 7@gv = global i32 0, align 48@gv_struct = global { i32, float } zeroinitializer, align 49@gv_array = global [3 x i32] zeroinitializer, align 410@gv_empty_struct = global { } zeroinitializer, align 411 12; CHECK: @global.func.user = global ptr @store_instruction_to_return_with_uses13@global.func.user = global ptr @store_instruction_to_return_with_uses14 15; INTERESTING-LABEL: @store_instruction_to_return_with_uses(16; INTERESTING-NEXT: = load17 18; RESULT-LABEL: define i32 @store_instruction_to_return_with_uses(ptr %arg) {19; RESULT-NEXT: %load = load i32, ptr %arg, align 420; RESULT-NEXT: ret i32 %load21define void @store_instruction_to_return_with_uses(ptr %arg) {22  %load = load i32, ptr %arg23  store i32 %load, ptr @gv24  ret void25}26 27; INTERESTING-LABEL: define void @user(28; INTERESTING: call29 30; RESULT-LABEL: define void @user(31; RESULT-NEXT: call i32 @store_instruction_to_return_with_uses(ptr %a, ptr %b)32; RESULT-NEXT: ret void33; RESULT-NEXT: }34define void @user(ptr %a, ptr %b) {35  call void @store_instruction_to_return_with_uses(ptr %a, ptr %b)36  ret void37}38 39; INTERESTING-LABEL: @store_instruction_to_return_no_uses(40; INTERESTING: = load i3241 42; RESULT-LABEL: define i32 @store_instruction_to_return_no_uses(43; RESULT-NEXT: %load = load i3244; RESULT-NEXT: ret i32 %load45define void @store_instruction_to_return_no_uses(ptr %arg) {46  %load = load i32, ptr %arg47  store i32 %load, ptr @gv48  ret void49}50 51; INTERESTING-LABEL: @store_instruction_to_return_preserve_attrs(52; INTERESTING: = load53 54; RESULT: ; Function Attrs: nounwind55; RESULT-NEXT: define weak i32 @store_instruction_to_return_preserve_attrs(ptr byref(i32) %arg) #0 {56; RESULT-NEXT: %load = load i32, ptr %arg, align 457; RESULT-NEXT: ret i32 %load58define weak void @store_instruction_to_return_preserve_attrs(ptr byref(i32) %arg) nounwind "some-attr" {59  %load = load i32, ptr %arg60  store i32 %load, ptr @gv61  ret void62}63 64; INTERESTING-LABEL: @store_instruction_to_return_preserve_addrspace(65; INTERESTING: = load66 67; RESULT-LABEL: define i32 @store_instruction_to_return_preserve_addrspace(ptr %arg) addrspace(1) {68; RESULT-NEXT: %load = load i32, ptr %arg, align 469; RESULT-NEXT: ret i32 %load70define void @store_instruction_to_return_preserve_addrspace(ptr %arg) addrspace(1) {71  %load = load i32, ptr %arg72  store i32 %load, ptr @gv73  ret void74}75 76; INTERESTING-LABEL: @store_instruction_to_return_no_uses_unreachable(77; INTERESTING: = load78 79; RESULT-LABEL: define i32 @store_instruction_to_return_no_uses_unreachable(ptr %arg) {80; RESULT-NEXT: %load = load i32, ptr %arg, align 481; RESULT-NEXT: ret i32 %load82define void @store_instruction_to_return_no_uses_unreachable(ptr %arg) {83  %load = load i32, ptr %arg84  store i32 %load, ptr @gv85  unreachable86}87 88; INTERESTING-LABEL: @store_instruction_to_return_with_non_callee_use(89; INTERESTING: = load90 91; RESULT-LABEL: define i32 @store_instruction_to_return_with_non_callee_use(ptr %arg) {92; RESULT-NEXT: %load = load i32, ptr %arg, align 493; RESULT-NEXT: ret i32 %load94define void @store_instruction_to_return_with_non_callee_use(ptr %arg) {95  %load = load i32, ptr %arg96  store i32 %load, ptr @gv97  ret void98}99 100declare void @takes_fptr(ptr)101 102; CHECK: @non_callee_user(103; CHECK: ret void104define void @non_callee_user(ptr %a, ptr %b) {105  call void @takes_fptr(ptr @store_instruction_to_return_with_non_callee_use)106  ret void107}108 109declare i32 @convergent_call() convergent110 111; CHECK-LABEL: @no_return_token_def(112; CHECK: call token113; RESULT: ret void114define void @no_return_token_def(ptr %arg) convergent {115  %t = call token @llvm.experimental.convergence.entry()116  ret void117}118 119; INTERESTING-LABEL: @no_return_token_def_other(120; INTERESTING: call token121 122; RESULT-LABEL: define i32 @no_return_token_def_other(123; RESULT: call token124; RESULT: call i32125; RESULT: ret i32126define void @no_return_token_def_other(ptr %arg) convergent {127  %t = call token @llvm.experimental.convergence.entry()128  %call = call i32 @convergent_call() [ "convergencectrl"(token %t) ]129  store i32 %call, ptr @gv130  ret void131}132 133; INTERESTING-LABEL: @store_instruction_to_return_variadic_func(134; INTERESTING: = load135 136; RESULT-LABEL: define i32 @store_instruction_to_return_variadic_func(ptr %arg, ...)137; RESULT-NEXT: %load = load i32, ptr %arg, align 4138; RESULT-NEXT: ret i32 %load139define void @store_instruction_to_return_variadic_func(ptr %arg, ...) {140  %load = load i32, ptr %arg141  store i32 %load, ptr @gv142  ret void143}144 145; Has a callsite use that is invoking the function with a non-void146; return type, that does not match the new return type.147 148; INTERESTING-LABEL: @inst_to_return_has_nonvoid_wrong_type_caller(149 150; RESULT-LABEL: define void @inst_to_return_has_nonvoid_wrong_type_caller(151; RESULT-NEXT: %load = load i32, ptr %arg152; RESULT-NEXT: store i32 %load, ptr @gv153; RESULT-NEXT: ret void154define void @inst_to_return_has_nonvoid_wrong_type_caller(ptr %arg) {155  %load = load i32, ptr %arg156  store i32 %load, ptr @gv157  ret void158}159 160; INTERESTING-LABEL: @wrong_callsite_return_type(161 162; RESULT-LABEL: define i64 @wrong_callsite_return_type(163; RESULT-NEXT: %ret = call i64 @inst_to_return_has_nonvoid_wrong_type_caller(ptr %arg)164; RESULT-NEXT: ret i64 %ret165define i64 @wrong_callsite_return_type(ptr %arg) {166  %ret = call i64 @inst_to_return_has_nonvoid_wrong_type_caller(ptr %arg)167  ret i64 %ret168}169 170; INTERESTING-LABEL: @inst_to_return_already_has_new_type_caller(171 172; RESULT-LABEL: define i32 @inst_to_return_already_has_new_type_caller(173; RESULT-NEXT: %load = load i32, ptr %arg, align 4174; RESULT-NEXT: ret i32 %load175define void @inst_to_return_already_has_new_type_caller(ptr %arg) {176  %load = load i32, ptr %arg177  store i32 %load, ptr @gv178  ret void179}180 181; Callsite has UB signature mismatch, but the return type happens to182; match the new return type.183;184; INTERESTING-LABEL: @callsite_already_new_return_type(185 186; RESULT-LABEL: define i32 @callsite_already_new_return_type(187; RESULT-NEXT: %ret = call i32 @inst_to_return_already_has_new_type_caller(ptr %arg)188; RESULT-NEXT: ret i32 %ret189define i32 @callsite_already_new_return_type(ptr %arg) {190  %ret = call i32 @inst_to_return_already_has_new_type_caller(ptr %arg)191  ret i32 %ret192}193 194; INTERESTING-LABEL: @non_void_no_op(195; INTERESTING: = load196; INTERESTING: ret197 198; RESULT-LABEL: define ptr @non_void_no_op(199; RESULT-NEXT: %load = load i32, ptr %arg200; RESULT-NEXT: store i32 %load, ptr @gv201; RESULT-NEXT: ret ptr null202define ptr @non_void_no_op(ptr %arg) {203  %load = load i32, ptr %arg204  store i32 %load, ptr @gv205  ret ptr null206}207 208; INTERESTING-LABEL: @non_void_no_op_caller(209 210; RESULT-LABEL: define ptr @non_void_no_op_caller(ptr %arg) {211; RESULT-NEXT: %call = call ptr @non_void_no_op(ptr %arg)212; RESULT-NEXT: ret ptr %call213define ptr @non_void_no_op_caller(ptr %arg) {214  %call = call ptr @non_void_no_op(ptr %arg)215  ret ptr %call216}217 218; INTERESTING-LABEL: @non_void_same_type_use(219; INTERESTING: = load220; INTERESTING: ret221 222; RESULT-LABEL: define i32 @non_void_same_type_use(223; RESULT-NEXT: %load = load i32, ptr %arg224; RESULT-NEXT: ret i32 %load225define i32 @non_void_same_type_use(ptr %arg) {226  %load = load i32, ptr %arg227  store i32 %load, ptr @gv228  ret i32 0229}230 231; INTERESTING-LABEL: @non_void_bitcastable_type_use(232; INTERESTING: = load233; INTERESTING: ret234 235; RESULT-LABEL: define i32 @non_void_bitcastable_type_use(236; RESULT-NEXT: %load = load float, ptr %arg237; RESULT-NEXT: store float %load,238; RESULT-NEXT: ret i32 0239define i32 @non_void_bitcastable_type_use(ptr %arg) {240  %load = load float, ptr %arg241  store float %load, ptr @gv242  ret i32 0243}244 245; INTERESTING-LABEL: @non_void_bitcastable_type_use_caller(246define i32 @non_void_bitcastable_type_use_caller(ptr %arg) {247  %ret = call i32 @non_void_bitcastable_type_use(ptr %arg)248  ret i32 %ret249}250 251; INTERESTING-LABEL: @form_return_struct(252; INTERESTING: = load { i32, float }253 254; RESULT-LABEL: define { i32, float } @form_return_struct(ptr %arg) {255; RESULT-NEXT: %load = load { i32, float }, ptr %arg, align 4256; RESULT-NEXT: ret { i32, float } %load257define void @form_return_struct(ptr %arg) {258  %load = load { i32, float }, ptr %arg259  store { i32, float } %load, ptr @gv_struct260  ret void261}262 263; INTERESTING-LABEL: define void @return_struct_user(264; INTERESTING-NEXT: call265; RESULT: call { i32, float } @form_return_struct(ptr %arg)266define void @return_struct_user(ptr %arg) {267  call void @form_return_struct(ptr %arg)268  ret void269}270 271; INTERESTING-LABEL: @form_return_array(272; INTERESTING: = load273 274; RESULT-LABEL: define [3 x i32] @form_return_array(275; RESULT-NEXT: %load = load [3 x i32]276; RESULT-NEXT: ret [3 x i32] %load277define void @form_return_array(ptr %arg) {278  %load = load [3 x i32], ptr %arg279  store [3 x i32] %load, ptr @gv_array280  ret void281}282 283; CHECK-LABEL: @return_array_user(284; RESULT: call [3 x i32] @form_return_array(ptr %arg)285define void @return_array_user(ptr %arg) {286  call void @form_return_array(ptr %arg)287  ret void288}289 290; INTERESTING-LABEL: @form_return_empty_struct(291; INTERESTING: = load292 293; RESULT: define {} @form_return_empty_struct(294; RESULT-NEXT: %load = load {}295; RESULT-NEXT: ret {} %load296define void @form_return_empty_struct(ptr %arg) {297  %load = load { }, ptr %arg298  store { } %load, ptr @gv_empty_struct299  ret void300}301 302; CHECK-LABEL: define void @return_empty_struct_user(303; RESULT: call {} @form_return_empty_struct(ptr %arg)304define void @return_empty_struct_user(ptr %arg) {305  call void @form_return_empty_struct(ptr %arg)306  ret void307}308 309define target("sometarget.sometype") @target_type_func() {310  ret target("sometarget.sometype") poison311}312 313define void @target_type_user(target("sometarget.sometype") %a) {314  ret void315}316 317; INTERESTING-LABEL: @form_return_target_ty(318; INTERESTING: call target("sometarget.sometype") @target_type_func()319 320; RESULT: define target("sometarget.sometype") @form_return_target_ty(321; RESULT-NEXT: %call = call target("sometarget.sometype") @target_type_func()322; RESULT-NEXT:  ret target("sometarget.sometype") %call323define void @form_return_target_ty(ptr %arg) {324  %call = call target("sometarget.sometype") @target_type_func()325  call void @target_type_user(target("sometarget.sometype") %call)326  ret void327}328 329; CHECK-LABEL: define void @return_target_ty_user(330; RESULT-NEXT: %1 = call target("sometarget.sometype") @form_return_target_ty(ptr %arg)331; RESULT-NEXT: ret void332define void @return_target_ty_user(ptr %arg) {333  call void @form_return_target_ty(ptr %arg)334  ret void335}336 337; Make sure an invalid reduction isn't attempted for a function with338; an sret argument339 340; CHECK-LABEL: @no_sret_nonvoid_return341define void @no_sret_nonvoid_return(ptr sret(i32) %out.sret, ptr %arg) {342  %load = load i32, ptr %arg343  store i32 %load, ptr %out.sret344  ret void345}346 347; Test a calling convention where it's illegal to use a non-void348; return. No invalid reduction should be introduced.349 350; INTERESTING-LABEL: @no_void_return_callingconv(351; INTERESTING: = load i32352 353; RESULT-LABEL: define amdgpu_kernel void @no_void_return_callingconv(354; RESULT-NEXT: %load = load i32355; RESULT-NEXT: store i32 %load356; RESULT-NEXT: ret void357define amdgpu_kernel void @no_void_return_callingconv(ptr %arg) {358  %load = load i32, ptr %arg359  store i32 %load, ptr @gv360  ret void361}362 363; INTERESTING-LABEL: @keep_first_of_3(364; INTERESTING: %load0 = load i32, ptr %arg0365; INTERESTING: ret366 367; RESULT-LABEL: define i32 @keep_first_of_3(368; RESULT-NEXT: %load0 = load i32, ptr %arg0, align 4369; RESULT-NEXT: ret i32 %load0370define void @keep_first_of_3(ptr %arg0, ptr %arg1, ptr %arg2) {371  %load0 = load i32, ptr %arg0372  %load1 = load i32, ptr %arg1373  %load2 = load i32, ptr %arg2374  store i32 %load0, ptr @gv375  store i32 %load1, ptr @gv376  store i32 %load2, ptr @gv377  ret void378}379 380; INTERESTING-LABEL: @keep_second_of_3(381; INTERESTING: %load1 = load i32, ptr %arg1382 383; RESULT-LABEL: define i32 @keep_second_of_3(384; RESULT-NEXT: %load0 = load i32, ptr %arg0385; RESULT-NEXT: %load1 = load i32, ptr %arg1386; RESULT-NEXT: ret i32 %load1387define void @keep_second_of_3(ptr %arg0, ptr %arg1, ptr %arg2) {388  %load0 = load i32, ptr %arg0389  %load1 = load i32, ptr %arg1390  %load2 = load i32, ptr %arg2391  store i32 %load0, ptr @gv392  store i32 %load1, ptr @gv393  store i32 %load2, ptr @gv394  ret void395}396 397; INTERESTING-LABEL: @keep_third_of_3(398; INTERESTING: %load2 = load i32, ptr %arg2399 400; RESULT-LABEL: define i32 @keep_third_of_3(401; RESULT-NEXT: %load0 = load i32, ptr %arg0, align 4402; RESULT-NEXT: %load1 = load i32, ptr %arg1, align 4403; RESULT-NEXT: %load2 = load i32, ptr %arg2, align 4404; RESULT-NEXT: ret i32 %load2405define void @keep_third_of_3(ptr %arg0, ptr %arg1, ptr %arg2) {406  %load0 = load i32, ptr %arg0407  %load1 = load i32, ptr %arg1408  %load2 = load i32, ptr %arg2409  store i32 %load0, ptr @gv410  store i32 %load1, ptr @gv411  store i32 %load2, ptr @gv412  ret void413}414 415; INTERESTING-LABEL: @keep_first_2_of_3(416; INTERESTING: %load0 = load i32, ptr %arg0417; INTERESTING: %load1 = load i32, ptr %arg1418 419; RESULT-LABEL: define i32 @keep_first_2_of_3(420; RESULT-NEXT: %load0 = load i32, ptr %arg0421; RESULT-NEXT: %load1 = load i32, ptr %arg1422; RESULT-NEXT: ret i32 %load1423define void @keep_first_2_of_3(ptr %arg0, ptr %arg1, ptr %arg2) {424  %load0 = load i32, ptr %arg0425  %load1 = load i32, ptr %arg1426  %load2 = load i32, ptr %arg2427  store i32 %load0, ptr @gv428  store i32 %load1, ptr @gv429  store i32 %load2, ptr @gv430  ret void431}432 433; INTERESTING-LABEL: @keep_second_of_3_already_ret_constexpr(434; INTERESTING: %load1 = load i32, ptr %arg1435; INTERESTING: ret436 437; RESULT-LABEL: define i32 @keep_second_of_3_already_ret_constexpr(438; RESULT-NEXT: %load0 = load i32, ptr %arg0, align 4439; RESULT-NEXT: %load1 = load i32, ptr %arg1, align 4440; RESULT-NEXT: ret i32 %load1441define i32 @keep_second_of_3_already_ret_constexpr(ptr %arg0, ptr %arg1, ptr %arg2) {442  %load0 = load i32, ptr %arg0443  %load1 = load i32, ptr %arg1444  %load2 = load i32, ptr %arg2445  store i32 %load0, ptr @gv446  store i32 %load1, ptr @gv447  store i32 %load2, ptr @gv448  ret i32 ptrtoint (ptr @gv to i32)449}450 451; INTERESTING-LABEL: @self_recursive(452; INTERESTING:  %load = load i32, ptr %arg453 454; RESULT-LABEL: define i32 @self_recursive(455; RESULT-NEXT: %load = load i32, ptr %arg, align 4456; RESULT-NEXT: ret i32 %load457define void @self_recursive(ptr %arg) {458  %load = load i32, ptr %arg459  store i32 %load, ptr @gv460  call void @self_recursive(ptr %arg)461  ret void462}463 464; INTERESTING-LABEL: @has_invoke_user(465 466; RESULT-LABEL: define i32 @has_invoke_user(467; RESULT-NEXT: %load = load i32, ptr %arg, align 4468; RESULT-NEXT: ret i32 %load469define void @has_invoke_user(ptr %arg) {470  %load = load i32, ptr %arg471  store i32 %load, ptr @gv472  ret void473}474 475declare i32 @__gxx_personality_v0(...)476 477; INTERESTING-LABEL: @invoker(478; RESULT:   %0 = invoke i32 @has_invoke_user(ptr %arg)479define void @invoker(ptr %arg) personality ptr @__gxx_personality_v0 {480bb:481  invoke void @has_invoke_user(ptr %arg)482    to label %bb3 unwind label %bb1483 484bb1:485  landingpad { ptr, i32 }486  catch ptr null487  br label %bb3488 489bb3:490  ret void491}492 493; INTERESTING-LABEL: @return_from_nonentry_block(494 495; RESULT-LABEL: define i32 @return_from_nonentry_block(496; RESULT: br i1 %arg0, label %bb0, label %bb1497 498; RESULT: bb0:499; RESULT-NEXT: %load = load i32, ptr %arg1, align 4500; RESULT-NEXT: ret i32 %load501 502; RESULT: bb1:503; RESULT-NEXT: unreachable504define void @return_from_nonentry_block(i1 %arg0, ptr %arg1) {505entry:506  br i1 %arg0, label %bb0, label %bb1507 508bb0:509  %load = load i32, ptr %arg1510  store i32 %load, ptr @gv511  ret void512 513bb1:514  unreachable515}516 517; INTERESTING-LABEL: @multi_void_return(518; INTERESTING: %load = load i32, ptr %arg1519 520; RESULT-LABEL: define i32 @multi_void_return(i1 %arg0, ptr %arg1) {521; RESULT-NEXT: entry:522; RESULT-NEXT: br i1 %arg0, label %bb0, label %bb1523 524; RESULT: bb0:525; RESULT-NEXT: %load = load i32, ptr %arg1526; RESULT-NEXT: ret i32 %load527 528; RESULT: bb1:529; RESULT-NEXT: ret i32 0530define void @multi_void_return(i1 %arg0, ptr %arg1) {531entry:532  br i1 %arg0, label %bb0, label %bb1533 534bb0:535  %load = load i32, ptr %arg1536  store i32 %load, ptr @gv537  ret void538 539bb1:540  ret void541}542 543; INTERESTING-LABEL: @multi_void_return_dominates_all(544; INTERESTING: %load = load i32, ptr %arg1545 546; RESULT-LABEL: define i32 @multi_void_return_dominates_all(547; RESULT-NEXT: entry:548; RESULT-NEXT: %load = load i32, ptr %arg1, align 4549; RESULT-NEXT: ret i32 %load550; RESULT-NEXT: }551define void @multi_void_return_dominates_all(i1 %arg0, ptr %arg1) {552entry:553  %load = load i32, ptr %arg1554  br i1 %arg0, label %bb0, label %bb1555 556bb0:557  store i32 %load, ptr @gv558  ret void559 560bb1:561  ret void562}563 564; INTERESTING-LABEL: @multi_unreachable_dominates_all(565; INTERESTING: %load = load i32, ptr %arg1566 567; RESULT-LABEL: define i32 @multi_unreachable_dominates_all(568; RESULT-NEXT: entry:569; RESULT-NEXT: %load = load i32, ptr %arg1, align 4570; RESULT-NEXT: ret i32 %load571; RESULT-NEXT: }572define void @multi_unreachable_dominates_all(i1 %arg0, ptr %arg1) {573entry:574  %load = load i32, ptr %arg1575  br i1 %arg0, label %bb0, label %bb1576 577bb0:578  store i32 %load, ptr @gv579  unreachable580 581bb1:582  unreachable583}584 585; We want to mutate %bb0 to return %load0, and not break the ret in586; %bb1587 588; INTERESTING-LABEL: @multi_nonvoid_return(589; INTERESTING: %other = load i32, ptr %arg2590; INTERESTING: br i1 %arg0591; INTERESTING: %load = load i32, ptr %arg1592 593 594; RESULT-LABEL: define i32 @multi_nonvoid_return(595 596; RESULT: entry:597; RESULT-NEXT: %other = load i32, ptr %arg2598; RESULT-NEXT: br i1 %arg0, label %bb0, label %bb1599 600; RESULT: bb0:601; RESULT-NEXT: %load = load i32, ptr %arg1, align 4602; RESULT-NEXT: ret i32 %load603 604; RESULT: bb1:605; RESULT-NEXT: ret i32 99606define i32 @multi_nonvoid_return(i1 %arg0, ptr %arg1, ptr %arg2) {607entry:608  %other = load i32, ptr %arg2609  br i1 %arg0, label %bb0, label %bb1610 611bb0:612  %load = load i32, ptr %arg1613  store i32 %load, ptr @gv614  ret i32 %other615 616bb1:617  ret i32 99618}619 620; TODO: Could handle this better if we avoided eliminating code that621; was already dead622 623; INTERESTING-LABEL: @interesting_in_unreachable_code(624; INTERESTING: %load = load i32, ptr %arg625 626; RESULT-LABEL: define void @interesting_in_unreachable_code(627; RESULT-NEXT: entry:628; RESULT-NEXT:  ret void629 630; RESULT: bb: ; No predecessors!631; RESULT-NEXT: %load = load i32, ptr %arg, align 4632; RESULT-NEXT: store i32 %load,633; RESULT-NEXT: ret void634define void @interesting_in_unreachable_code(ptr %arg) {635entry:636  ret void637 638bb:639  %load = load i32, ptr %arg640  store i32 %load, ptr @gv641  ret void642}643 644; INTERESTING-LABEL: @use_in_successor_phi(645; INTERESTING: %load0 = load i32, ptr %arg1646 647; RESULT-LABEL: define i32 @use_in_successor_phi(648; RESULT-NEXT: entry:649; RESULT-NEXT: %load0 = load i32, ptr %arg1, align 4650; RESULT-NEXT: ret i32 %load0651; RESULT-NEXT: }652define void @use_in_successor_phi(i1 %arg0, ptr %arg1, ptr %arg2) {653entry:654  %load0 = load i32, ptr %arg1655  br i1 %arg0, label %bb0, label %bb1656 657bb0:658  %phi = phi i32 [ %load0, %entry ], [ %load1, %bb1 ]659  store i32 %phi, ptr @gv660  br label %bb2661 662bb1:663  %load1 = load i32, ptr %arg2664  br label %bb0665 666bb2:667  ret void668}669 670; INTERESTING-LABEL: @use_in_successor_phi_repeated(671; INTERESTING: %load0 = load i32, ptr %arg1672 673; RESULT-LABEL: define i32 @use_in_successor_phi_repeated(674; RESULT-NEXT: entry:675; RESULT-NEXT: %load0 = load i32, ptr %arg1, align 4676; RESULT-NEXT: ret i32 %load0677; RESULT-NEXT: }678define void @use_in_successor_phi_repeated(i1 %arg0, ptr %arg1, ptr %arg2, i32 %switch.val) {679entry:680  %load0 = load i32, ptr %arg1681  br i1 %arg0, label %bb0, label %bb1682 683bb0:684  %phi = phi i32 [ %load0, %entry ], [ %load1, %bb1 ], [ %load1, %bb1 ]685  store i32 %phi, ptr @gv686  br label %bb2687 688bb1:689  %load1 = load i32, ptr %arg2690  switch i32 %switch.val, label %bb2 [691    i32 1, label %bb0692    i32 2, label %bb0693  ]694 695bb2:696  ret void697}698 699; INTERESTING-LABEL: @replace_cond_br_with_ret(700; INTERESTING: %load0 = load i32, ptr %arg1701 702; RESULT-LABEL: define i32 @replace_cond_br_with_ret(703; RESULT-NEXT: entry:704; RESULT-NEXT: %load0 = load i32, ptr %arg1, align 4705; RESULT-NEXT: ret i32 %load0706define void @replace_cond_br_with_ret(i1 %arg0, ptr %arg1, ptr %arg2) {707entry:708  %load0 = load i32, ptr %arg1709  br i1 %arg0, label %bb0, label %bb1710 711bb0:712  store i32 %load0, ptr %arg2713  ret void714 715bb1:716  store i32 %load0, ptr %arg2717  ret void718}719 720; INTERESTING-LABEL: @replace_switch_with_ret(721; INTERESTING: %load0 = load i32, ptr %arg1722 723; RESULT-LABEL: define i32 @replace_switch_with_ret(724; RESULT-NEXT: entry:725; RESULT-NEXT: %load0 = load i32, ptr %arg1, align 4726; RESULT-NEXT: ret i32 %load0727; RESULT-NEXT: }728define void @replace_switch_with_ret(i32 %arg0, ptr %arg1, ptr %arg2) {729entry:730  %load0 = load i32, ptr %arg1731  switch i32 %arg0, label %bb2 [732    i32 1, label %bb0733    i32 2, label %bb1734  ]735 736bb0:737  store i32 9, ptr %arg2738  ret void739 740bb1:741  store i32 10, ptr %arg2742  unreachable743 744bb2:745  ret void746}747 748; INTERESTING-LABEL: @replace_uncond_br_with_ret(749; INTERESTING: %load0 = load i32, ptr %arg1750 751; RESULT-LABEL: define i32 @replace_uncond_br_with_ret(752; RESULT-NEXT: entry:753; RESULT: %load0 = load i32, ptr %arg1, align 4754; RESULT-NEXT: ret i32 %load0755; RESULT-NEXT: }756define void @replace_uncond_br_with_ret(i1 %arg0, ptr %arg1, ptr %arg2) {757entry:758  %load0 = load i32, ptr %arg1759  br label %bb0760 761bb0:762  store i32 %load0, ptr %arg2763  ret void764}765 766; INTERESTING-LABEL: @replace_uncond_br_with_ret_with_phi(767; INTERESTING: %load0 = load i32, ptr %arg1768 769; RESULT-LABEL: define i32 @replace_uncond_br_with_ret_with_phi(770; RESULT-NEXT: entry:771; RESULT-NEXT: %load0 = load i32, ptr %arg1772; RESULT-NEXT: ret i32 %load0773; RESULT-NEXT: }774define void @replace_uncond_br_with_ret_with_phi(i1 %arg0, ptr %arg1, ptr %arg2, ptr %arg3) {775entry:776  %load0 = load i32, ptr %arg1777  br label %bb0778 779bb0:780  %phi = phi i32 [ %load0, %entry ]781  store i32 %phi, ptr %arg2782  store i32 %load0, ptr %arg3783  ret void784}785 786; INTERESTING-LABEL: @use_tail_instr_in_successor_phi(787; INTERESTING: %load0 = load i32, ptr %arg1788 789; RESULT-LABEL: define i32 @use_tail_instr_in_successor_phi(790; RESULT-NEXT: entry:791; RESULT-NEXT: %load0 = load i32, ptr %arg1792; RESULT-NEXT: ret i32 %load0793; RESULT-NEXT: }794define void @use_tail_instr_in_successor_phi(i1 %arg0, ptr %arg1, ptr %arg2) {795entry:796  %load0 = load i32, ptr %arg1797  %load1 = load i32, ptr %arg2798  br i1 %arg0, label %bb0, label %bb1799 800bb0:801  %phi = phi i32 [ %load0, %entry ], [ %load1, %bb1 ]802  store i32 %phi, ptr @gv803  br label %bb2804 805bb1:806  br label %bb0807 808bb2:809  ret void810}811 812; INTERESTING-LABEL: @use_before_instr_in_successor_phi(813; INTERESTING: %load1 = load i32, ptr %arg2814 815; RESULT-LABEL: define i32 @use_before_instr_in_successor_phi(816; RESULT-NEXT: entry:817; RESULT-NEXT: %load0 = load i32, ptr %arg1818; RESULT-NEXT: %load1 = load i32, ptr %arg2819; RESULT-NEXT: ret i32 %load1820; RESULT-NEXT: }821define void @use_before_instr_in_successor_phi(i1 %arg0, ptr %arg1, ptr %arg2) {822entry:823  %load0 = load i32, ptr %arg1824  %load1 = load i32, ptr %arg2825  br i1 %arg0, label %bb0, label %bb1826 827bb0:828  %phi = phi i32 [ %load0, %entry ], [ %load1, %bb1 ]829  store i32 %phi, ptr @gv830  br label %bb2831 832bb1:833  br label %bb0834 835bb2:836  ret void837}838 839declare i32 @maybe_throwing_callee(i32)840declare void @thrown()841declare void @did_not_throw(i32)842 843; TODO: Handle invokes properly844; INTERESTING-LABEL @reduce_invoke_use(845; INTERESTING: call void @did_not_throw(i32 %invoke)846 847; RESULT-LABEL: define { ptr, i32 } @reduce_invoke_use(848 849; RESULT: %invoke = invoke i32 @maybe_throwing_callee850 851; RESULT: bb1: ; preds = %bb852; RESULT-NEXT: %landing = landingpad { ptr, i32 }853; RESULT-NEXT: catch ptr null854; RESULT-NEXT: ret { ptr, i32 } %landing855 856; RESULT: bb4: ; preds = %bb3857; RESULT-NEXT: ret { ptr, i32 } zeroinitializer858define void @reduce_invoke_use(i32 %arg) personality ptr @__gxx_personality_v0 {859bb:860  %invoke = invoke i32 @maybe_throwing_callee(i32 %arg)861          to label %bb3 unwind label %bb1862 863bb1:                                              ; preds = %bb864  %landing = landingpad { ptr, i32 }865          catch ptr null866  call void @thrown()867  br label %bb4868 869bb3:                                              ; preds = %bb870  call void @did_not_throw(i32 %invoke)871  br label %bb4872 873bb4:                                              ; preds = %bb3, %bb1874  ret void875}876 877; We can replace the branch in %bb0 with a return, but bb2 will still878; be reachable after879 880; INTERESTING-LABEL: @successor_block_not_dead_after_ret(881; INTERESTING: %load0 = load i32, ptr %arg2882 883; RESULT-LABEL: define i32 @successor_block_not_dead_after_ret(884; RESULT: entry:885; RESULT-NEXT: br i1 %arg0, label %bb0, label %bb2886 887; RESULT: bb0:                                              ; preds = %entry888; RESULT-NEXT: %load0 = load i32, ptr %arg2, align 4889; RESULT-NEXT: ret i32 %load0890 891; RESULT: bb2:                                              ; preds = %entry892; RESULT-NEXT: %phi = phi i32 [ %arg4, %entry ]893; RESULT-NEXT: ret i32 %phi894; RESULT-NEXT: }895define void @successor_block_not_dead_after_ret(i1 %arg0, i1 %arg1, ptr %arg2, ptr %arg3, i32 %arg4, i32 %arg5) {896entry:897  br i1 %arg0, label %bb0, label %bb2898 899bb0:900  %load0 = load i32, ptr %arg2901  store i32 %load0, ptr @gv902  br i1 %arg1, label %bb1, label %bb2903 904bb1:905  %load1 = load i32, ptr %arg3906  store i32 %load1, ptr @gv907  br label %bb0908 909bb2:910  %phi = phi i32 [ %arg4, %entry ], [ %arg5, %bb0 ]911  store i32 %phi, ptr @gv912  ret void913}914 915; INTERESTING-LABEL: @successor_block_self_loop_phi(916; INTERESTING: %load0 = load i32, ptr %arg2917 918; RESULT-LABEL: define i32 @successor_block_self_loop_phi(919; RESULT: entry:920; RESULT-NEXT: br i1 %arg0, label %bb0, label %bb1921 922; RESULT: bb0:                                              ; preds = %entry923; RESULT-NEXT: %phi = phi i32 [ 12, %entry ]924; RESULT-NEXT: %load0 = load i32, ptr %arg2, align 4925; RESULT-NEXT: ret i32 %load0926 927; RESULT: bb1:                                              ; preds = %entry928; RESULT-NEXT: ret i32 0929; RESULT-NEXT: }930define void @successor_block_self_loop_phi(i1 %arg0, i1 %arg1, ptr %arg2) {931entry:932  br i1 %arg0, label %bb0, label %bb1933 934bb0:935  %phi = phi i32 [ 12, %entry ], [ %load0, %bb0 ]936  %load0 = load i32, ptr %arg2937  store i32 %phi, ptr @gv938  br i1 %arg1, label %bb0, label %bb1939 940bb1:941  ret void942}943 944; INTERESTING-LABEL: @successor_block_self_loop_phi_2(945; INTERESTING: %phi1 = phi i32946 947; RESULT-LABEL: define i32 @successor_block_self_loop_phi_2(948; RESULT: entry:949; RESULT-NEXT: %load0 = load i32, ptr %arg2950; RESULT-NEXT: br i1 %arg0, label %bb0, label %bb1951 952; RESULT: bb0:                                              ; preds = %entry953; RESULT-NEXT: %phi0 = phi i32 [ 12, %entry ]954; RESULT-NEXT: %phi1 = phi i32 [ %arg4, %entry ]955; RESULT-NEXT: ret i32 %phi1956 957; RESULT-NOT: bb958 959; RESULT: bb1:                                              ; preds = %entry960; RESULT-NEXT: ret i32 0961; RESULT-NEXT: }962define void @successor_block_self_loop_phi_2(i1 %arg0, i1 %arg1, ptr %arg2, ptr %arg3, i32 %arg4) {963entry:964  %load0 = load i32, ptr %arg2965  br i1 %arg0, label %bb0, label %bb1966 967bb0:968  %phi0 = phi i32 [ 12, %entry ], [ %load0, %bb0 ]969  %phi1 = phi i32 [ %arg4, %entry ], [ %load1, %bb0 ]970  %load1 = load i32, ptr %arg3971  store i32 %phi0, ptr @gv972  store i32 %phi1, ptr @gv973  br i1 %arg1, label %bb0, label %bb1974 975bb1:976  ret void977}978