https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80422
--- Comment #2 from Jeffrey A. Law <law at redhat dot com> --- This is a latent bug in cross jumping AFAICT. Essentially a forwarder block becomes unreachable during cfg_cleanup. Later we're cross jumping an indirect (via more forwarders) successor of the now unreachable forwarder and walk up the CFG looking for hunks of equivalent insns. flow_find_cross_jump walks the insn chain backwards from two given points to find identical insns for crossjumping. That walk can cross basic block boundaries (by design, see walk_to_nondebug_insn). As a result flow_find_cross_jump can return in F1 and F2 insns that are not in blocks BB1 and BB2. So given this code in try_crossjump_to_edge: /* Likewise with dead code (possibly newly created by the other optimizations of cfg_cleanup). */ if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0) return false; [ ... ] /* ... and part the second. */ nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir); osrc1 = src1; osrc2 = src2; if (newpos1 != NULL_RTX) src1 = BLOCK_FOR_INSN (newpos1); if (newpos2 != NULL_RTX) src2 = BLOCK_FOR_INSN (newpos2); The EDGE_COUNT checks verify that the original starting points for cross jumping are reachable. But as we walk up the CFG we may run into cases where flow_find_cross_jump walks us into one or more new blocks and we never check to see if those new blocks are reachable or not. A short time later we do this: /* Avoid splitting if possible. We must always split when SRC2 has EH predecessor edges, or we may end up with basic blocks with both normal and EH predecessor edges. */ if (newpos2 == BB_HEAD (src2) && !(EDGE_PRED (src2, 0)->flags & EDGE_EH)) redirect_to = src2; If SRC2 is unreachable, then EDGE_PRED will read outside the vec's boundary triggering the fault. I'm pretty sure the fix is to verify the both blocks are reachable after flow_find_cross_jump as well.