It's fairly easy to update the virtual ops when the call has no EH edges, which should be cheaper than mark_virtual_operands_for_renaming.
Tested on x86_64-linux-gnu, arm-linux-gnueabi and aarch64-linux-gnu. OK to install? Thanks, Richard gcc/ * tree-call-cdce.c (join_vdefs): New function. (shrink_wrap_one_built_in_call): Use it when the call does not need to end a block. Call mark_virtual_operands_for_renaming otherwise. (pass_call_cdce::execute): Don't call mark_virtual_operands_for_renaming here. diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c index 72828dd..dcaa974 100644 --- a/gcc/tree-call-cdce.c +++ b/gcc/tree-call-cdce.c @@ -708,6 +708,23 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds, /* Probability of the branch (to the call) is taken. */ #define ERR_PROB 0.01 +/* Replace BI_CALL's vdef with a phi that uses BI_CALL's definition + when WITH_CALL is taken and the previous definition when WITHOUT_CALL + is taken. JOIN_BB is the target of both edges. */ + +static void +join_vdefs (gcall *bi_call, edge with_call, edge without_call, + basic_block join_bb) +{ + tree old_vuse = gimple_vuse (bi_call); + tree old_vdef = gimple_vdef (bi_call); + tree new_vdef = copy_ssa_name (old_vuse); + gphi *phi = create_phi_node (new_vdef, join_bb); + replace_uses_by (old_vdef, new_vdef); + add_phi_arg (phi, old_vuse, without_call, UNKNOWN_LOCATION); + add_phi_arg (phi, old_vdef, with_call, UNKNOWN_LOCATION); +} + /* The function to shrink wrap a partially dead builtin call whose return value is not used anywhere, but has to be kept live due to potential error condition. Returns true if the @@ -764,7 +781,8 @@ shrink_wrap_one_built_in_call (gcall *bi_call) bi_call_bb = gimple_bb (bi_call); /* Now find the join target bb -- split bi_call_bb if needed. */ - if (stmt_ends_bb_p (bi_call)) + bool call_must_end_bb_p = stmt_ends_bb_p (bi_call); + if (call_must_end_bb_p) { /* If the call must be the last in the bb, don't split the block, it could e.g. have EH edges. */ @@ -822,6 +840,12 @@ shrink_wrap_one_built_in_call (gcall *bi_call) join_tgt_in_edge_fall_thru->count = guard_bb->count - bi_call_in_edge0->count; + if (call_must_end_bb_p) + mark_virtual_operands_for_renaming (cfun); + else + join_vdefs (bi_call, join_tgt_in_edge_from_call, + join_tgt_in_edge_fall_thru, join_tgt_bb); + /* Code generation for the rest of the conditions */ basic_block prev_guard_bb = NULL; while (nconds > 0) @@ -978,9 +1002,6 @@ pass_call_cdce::execute (function *fun) if (something_changed) { free_dominance_info (CDI_POST_DOMINATORS); - /* As we introduced new control-flow we need to insert PHI-nodes - for the call-clobbers of the remaining call. */ - mark_virtual_operands_for_renaming (fun); return TODO_update_ssa; }