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.