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.

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

Reply via email to