https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108691
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- The reason is that gimple_call_flags returns a different answer from the indirect function call vs. the direct function call after propagating of the &setjmp constant. First of all 'returns_twice' is an attribute that cannot be set on a function type: int __attribute__((returns_twice)) (*foo) (void); > gcc-12 -S t.c -Wall t.c:1:1: warning: 'returns_twice' attribute ignored [-Wattributes] 1 | int __attribute__((returns_twice)) (*foo) (void); | ^~~ so one cannot have an indirect call annotated. But even then we for example treat indirect missing 'noreturn' conservatively, not requiring it to end a BB and only enforce that in the fixup-CFG pass. Now, for return_twice we could similarly check gimple_call_ctrl_altering. That still leaves us with missing abnormal edges - David, was this reduced from an actual program? When fixing up DCE to not set cfun->calls_setjmp it will eventually be set late in emit_call_1 via if (ecf_flags & ECF_RETURNS_TWICE) { add_reg_note (call_insn, REG_SETJMP, const0_rtx); cfun->calls_setjmp = 1; } a "fix" here would be to _check_ for cfun->calls_setjmp instead of setting it (or assert it is set). The control-altering flag has no representation on GENERIC, and we're still expanding calls via intermediate GENERIC ...