When a peephole2 replaces a call, the REG_EH_REGION note is copied by
copy_reg_eh_region_note_backward, which skips insns that can't throw.
Without -fexceptions that includes the new call, so a nothrow note
(lp_nr INT_MIN) is lost. In a function with nonlocal labels the call
is then treated as a possible nonlocal goto and ends a basic block,
which rtl_verify_bb_insns rejects:

  error: flow control insn inside a basic block
  internal compiler error: in rtl_verify_bb_insns, at cfgrtl.cc:3011

Seen on alpha-linux with gcc.dg/asan/pr81186.c and pr82545.c at -O2.

gcc/ChangeLog:

        * recog.cc (peep2_attempt): Copy REG_EH_REGION notes to a new
        call that can't throw.
---
 gcc/recog.cc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/gcc/recog.cc b/gcc/recog.cc
index 188ebc37834..848f473c3be 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -4140,6 +4140,12 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int 
match_len, rtx_insn *attempt)
            add_reg_note (new_insn, REG_NOTE_KIND (note),
                          XEXP (note, 0));
            break;
+         case REG_EH_REGION:
+           /* copy_reg_eh_region_note_backward below only handles insns
+              that could throw.  */
+           if (!insn_could_throw_p (new_insn))
+             add_reg_note (new_insn, REG_EH_REGION, XEXP (note, 0));
+           break;
          default:
            /* Discard all other reg notes.  */
            break;

-- 
2.56.1

Reply via email to