On Tue, 26 Feb 2019, Jakub Jelinek wrote:

> On Tue, Feb 26, 2019 at 04:08:21PM +0100, Richard Biener wrote:
> > I think we can have multiple .ABNORMAL_DISPATCHERs - at least in theory
> > via inlining, though I see code in the inliner avoiding multiple ones
> > at least for nonlocal goto, not sure if that covers all cases.
> 
> Ok.
> 
> > > Shall I modify the patch for that?
> > 
> > Might it even simplify the patch?  If not the only comment on the
> > original patch is that it would be nice to test it on a SJLJ EH
> > target ...
> 
>  1 file changed, 29 insertions(+), 16 deletions(-)
> so not really simplify it, but not terrible either.
> 
> Here is the incremental (untested) diff of what handles that.
> 
> I don't have access to any standard SJLJ EH targets, but will try
> --enable-sjlj-exceptions on x86_64-linux to see how far I get with that.

Indeed not terrible.  Maybe Eric can help with testing on a SJLJ
target (though IIRC Ada uses its own EH scheme on such targets?)

Richard.

> --- gcc/tree-cfgcleanup.c.jj  2019-02-26 16:52:33.828719803 +0100
> +++ gcc/tree-cfgcleanup.c     2019-02-26 17:11:07.735576027 +0100
> @@ -731,12 +731,7 @@ cleanup_tree_cfg_bb (basic_block bb)
>     normally are effectively unreachable as well.  Additionally ignore
>     __builtin_setjmp_receiver starting blocks, which have one FORCED_LABEL
>     and which are always only reachable through EDGE_ABNORMAL edge.  They are
> -   handled in cleanup_control_flow_pre.
> -   Similarly, return true for EDGE_ABNORMAL edge from any basic block to
> -   .ABNORMAL_DISPATCHER basic block if the latter block has no successors.
> -   .ABNORMAL_DISPATCHER basic blocks that don't dispatch to anything are 
> dead,
> -   don't really need any EDGE_ABNORMAL edges to them and can be safely
> -   removed.  */
> +   handled in cleanup_control_flow_pre.  */
>  
>  static bool
>  maybe_dead_abnormal_edge_p (edge e)
> @@ -747,16 +742,7 @@ maybe_dead_abnormal_edge_p (edge e)
>    gimple_stmt_iterator gsi = gsi_start_nondebug_after_labels_bb (e->src);
>    gimple *g = gsi_stmt (gsi);
>    if (!g || !gimple_call_internal_p (g, IFN_ABNORMAL_DISPATCHER))
> -    {
> -      if (EDGE_COUNT (e->dest->succs) == 0)
> -     {
> -       gsi = gsi_start_nondebug_after_labels_bb (e->dest);
> -       g = gsi_stmt (gsi);
> -       if (g && gimple_call_internal_p (g, IFN_ABNORMAL_DISPATCHER))
> -         return true;
> -     }
> -      return false;
> -    }
> +    return false;
>  
>    tree target = NULL_TREE;
>    for (gsi = gsi_start_bb (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
> @@ -846,6 +832,7 @@ cleanup_control_flow_pre ()
>    bitmap_clear (visited);
>  
>    vec<edge, va_gc> *setjmp_vec = NULL;
> +  auto_vec<basic_block, 4> abnormal_dispatchers;
>  
>    stack.quick_push (ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs));
>  
> @@ -877,6 +864,16 @@ cleanup_control_flow_pre ()
>               stack.quick_push (ei_start (setjmp_vec));
>           }
>  
> +       if ((ei_edge (ei)->flags
> +            & (EDGE_ABNORMAL | EDGE_EH)) == EDGE_ABNORMAL)
> +         {
> +           gimple_stmt_iterator gsi
> +             = gsi_start_nondebug_after_labels_bb (dest);
> +           gimple *g = gsi_stmt (gsi);
> +           if (g && gimple_call_internal_p (g, IFN_ABNORMAL_DISPATCHER))
> +             abnormal_dispatchers.safe_push (dest);
> +         }
> +
>         if (EDGE_COUNT (dest->succs) > 0)
>           stack.quick_push (ei_start (dest->succs));
>       }
> @@ -895,6 +892,22 @@ cleanup_control_flow_pre ()
>  
>    vec_free (setjmp_vec);
>  
> +  /* If we've marked .ABNORMAL_DISPATCHER basic block(s) as visited
> +     above, but haven't marked any of their successors as visited,
> +     unmark them now, so that they can be removed as useless.  */
> +  basic_block dispatcher_bb;
> +  unsigned int k;
> +  FOR_EACH_VEC_ELT (abnormal_dispatchers, k, dispatcher_bb)
> +    {
> +      edge e;
> +      edge_iterator ei;
> +      FOR_EACH_EDGE (e, ei, dispatcher_bb->succs)
> +     if (bitmap_bit_p (visited, e->dest->index))
> +       break;
> +      if (e == NULL)
> +     bitmap_clear_bit (visited, dispatcher_bb->index);
> +    }
> +
>    set_dom_info_availability (CDI_DOMINATORS, saved_state);
>  
>    /* We are deleting BBs in non-reverse dominator order, make sure
> 
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to