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)