https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86108

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The problem is in cross-jumping, we have a landing pad with one EDGE_CROSSING
and some EH predecessor edges.  The DF code treats the bb_has_eh_pred specially
and creates artificial generation of the EH_RETURN_DATA_REGNO blocks at the
start of those blocks, rather than making those regs visible on the in edge.

I've tried:
--- gcc/bb-reorder.c.jj 2018-05-31 21:51:18.508292965 +0200
+++ gcc/bb-reorder.c    2018-06-15 12:57:34.501095317 +0200
@@ -1507,8 +1507,11 @@ dw2_fix_up_crossing_landing_pad (eh_land
   new_lp->landing_pad = gen_label_rtx ();
   LABEL_PRESERVE_P (new_lp->landing_pad) = 1;

+  e = split_block_after_labels (old_bb);
+  old_bb = e->src;
+
   /* Create the forwarder block.  */
-  basic_block new_bb = create_forwarder_block (new_lp->landing_pad, old_bb);
+  basic_block new_bb = create_forwarder_block (new_lp->landing_pad, e->dest);

   /* Fix up the edges.  */
   for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)) != NULL; )
to make sure we don't have bbs with both EDGE_CROSSING and EH incoming edges.
Another possibility is to disallow cross-jumping of the bb_has_eh_pred basic
blocks, like:
--- gcc/cfgcleanup.c.jj 2018-04-25 09:41:37.753686037 +0200
+++ gcc/cfgcleanup.c    2018-06-15 13:18:43.173257421 +0200
@@ -1976,6 +1976,12 @@ try_crossjump_to_edge (int mode, edge e1
   if (!outgoing_edges_match (mode, src1, src2))
     return false;

+  /* The DF uses magic for EH landing pads where the EH_RETURN_DATA_REGNO
+     regs are artificially defined at the start.  Avoid cross-jumping in
+     between the EH landing pads and other bbs.  */
+  if (bb_has_eh_pred (src1) != bb_has_eh_pred (src2))
+    return false;
+
   /* ... and part the second.  */
   nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir);

Either of the patches fix the testcase, there is some code growth though, but
maybe it is mainly about adding the missing register moves that are incorrectly
missing without them.  Without the patches main has 3259 bytes and main.cold
1276 bytes, with the first path it is 3337/1371 bytes and with the second patch
instead 3337/1374 bytes.
Conceptually, I think the first patch is better, the DF info isn't incorrect
then (if we have bbs with both crossing and EH predecessors, we don't mention
the EH regs in lr/live in on the EH pad nor in lr/live out on the EH pad in the
other partition that just branches to it.

Reply via email to