https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69887
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |ebotcazou at gcc dot gnu.org, | |jakub at gcc dot gnu.org --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- void *a[6]; void foo () { __builtin_setjmp (a); __builtin_longjmp (a, 1); } The problem is that pass_expand::execute in /* At the moment not all abnormal edges match the RTL representation. It is safe to remove them here as find_many_sub_basic_blocks will rediscover them. In the future we should get this fixed properly. */ if ((e->flags & EDGE_ABNORMAL) && !(e->flags & EDGE_SIBCALL)) remove_edge (e); else ei_next (&ei); removes the abnormal edges, but find_many_sub_basic_blocks doesn't actually recreate any corresponding edge from the REG_NON_LOCAL_GOTO JUMP_INSN (the label is not marked as forced_label, just LABEL_PRESERVED_P), thus the cfg cleanup at the end of expand pass attempts to remove the __builtin_setjmp_receiver basic block as unreachable. As the label is LABEL_PRESERVED_P, it doesn't actually delete the label, just turns it into NOTE_INSN_DELETED_LABEL, and there is some insn earlier (expanded from __builtin_setjmp_setup) that references that deleted label through LABEL_REF. Later on CSE determines that the REG_NON_LOCAL_GOTO JUMP_INSN can only jump to the particular (deleted) label, and bumps its LABEL_NUSES (probably rtl checking would ICE here, non-rtl checking just silently turns that NOTE_INSN_DELETED_LABEL into NOTE_INSN_DELETED_DEBUG_LABEL. Thus, a quick hack could be to tweak cse.c to follow mark_jump_label_1 and don't touch LABEL_NUSES on deleted labels. But, it still looks wrong to me, we'd then attempt to jump into a middle of basic block. So I bet we want to do something during find_many_sub_basic_blocks or elsewhere during expansion, so that we keep the setjmp receiver basic block alive.