https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86108
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #5) > 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. You mean without splitting the block the DF info is incorrect? If so should we add sth to verify-flow-info that makes sure we do not have EDGE_CROSSING and EH incoming edges? Can't an EH edge be EDGE_CROSSING itself?