diff mbox

Try to avoid mark_virtual_operands_for_renmaing in call-cdce

Message ID 87611owqn6.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 30, 2015, 11:18 a.m. UTC
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.

Comments

Richard Biener Oct. 30, 2015, 11:46 a.m. UTC | #1
On Fri, Oct 30, 2015 at 12:18 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> 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?

Well.  I think this can be easily improved to handle the EH edge case
by not replacing the virtual uses in the EH region.

Btw, did you verify the pass does things correctly when facing an EH
throwing situation?  It seems all math builtins are marked as NOTHROW
regardless of -fnon-call-exceptions ...

Richard.

> 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;
>      }
>
>
Richard Sandiford Oct. 30, 2015, 12:21 p.m. UTC | #2
Richard Biener <richard.guenther@gmail.com> writes:
> On Fri, Oct 30, 2015 at 12:18 PM, Richard Sandiford
> <richard.sandiford@arm.com> wrote:
>> 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?
>
> Well.  I think this can be easily improved to handle the EH edge case
> by not replacing the virtual uses in the EH region.

OK.  I suppose I was just going for the low-hanging fruit. :-)  I'll drop
this in favour of getting the internal function stuff finished for stage 1.

> Btw, did you verify the pass does things correctly when facing an EH
> throwing situation?  It seems all math builtins are marked as NOTHROW
> regardless of -fnon-call-exceptions ...

The main test case for that seems to be g++.dg/opt/pr58165.C.  I'd tried
other variations of that locally.

Thanks,
Richard
Richard Biener Oct. 30, 2015, 12:46 p.m. UTC | #3
On Fri, Oct 30, 2015 at 1:21 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Fri, Oct 30, 2015 at 12:18 PM, Richard Sandiford
>> <richard.sandiford@arm.com> wrote:
>>> 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?
>>
>> Well.  I think this can be easily improved to handle the EH edge case
>> by not replacing the virtual uses in the EH region.
>
> OK.  I suppose I was just going for the low-hanging fruit. :-)

Heh, true.  It's never that simple.

> I'll drop this in favour of getting the internal function stuff finished for stage 1.

Fair enough (and yes, I definitely like to see at least internal
function support
for genmatch/match.pd for GCC 6).

>> Btw, did you verify the pass does things correctly when facing an EH
>> throwing situation?  It seems all math builtins are marked as NOTHROW
>> regardless of -fnon-call-exceptions ...
>
> The main test case for that seems to be g++.dg/opt/pr58165.C.  I'd tried
> other variations of that locally.

Looking at this example I realize it would be nice to be in "(virtual) EH-closed
SSA form" so that all uses on an EH edge are reachable by walking the
EH edge destination PHI nodes ...

Otherwise of couse the fix is to propagate only into uses which are
not dominated
by the EH dest.  A replace_uses_by variant which takes an edge to check ignored
uses would come handy here.

Richard.

> Thanks,
> Richard
>
diff mbox

Patch

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;
     }