http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49686
Summary: [4.7 Regression] CFI notes are missed for delayed slot Product: gcc Version: unknown Status: UNCONFIRMED Keywords: EH Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: kkoj...@gcc.gnu.org CC: r...@gcc.gnu.org Target: sh4-unknown-linux-gnu Many EH tests fail on SH after the recent dwarf2 clean up. These failures went away with -fno-delayed-branch. A tiny testcase is int foo (int a) { if (a) bar (); return 1; } and with -O1 -fexceptions -fnon-call-exceptions, its assember output of the new compiler starts like foo: .LFB0: tst r4,r4 bt/s .L2 sts.l pr,@-r15 while the old compiler outputs CFI for the last frame related insn sts.l pr,@-r15 in the delayed slot: foo: .LFB0: tst r4,r4 .LCFI0: bt/s .L2 sts.l pr,@-r15 It seems that dwarf2out_frame_debug emits CFI notes at the middle of the elements of SEQUENCE and they were lost. The patch below works for me. --- ORIG/trunk/gcc/dwarf2cfi.c 2011-07-09 14:42:50.000000000 +0900 +++ trunk/gcc/dwarf2cfi.c 2011-07-09 14:46:18.000000000 +0900 @@ -2170,11 +2170,10 @@ dwarf2out_frame_debug_expr (rtx expr) sets SP or FP (adjusting how we calculate the frame address) or saves a register to the stack. If INSN is NULL_RTX, initialize our state. - If AFTER_P is false, we're being called before the insn is emitted, - otherwise after. Call instructions get invoked twice. */ + Notes are inserted at WHERE. Call instructions get invoked twice. */ static void -dwarf2out_frame_debug (rtx insn, bool after_p) +dwarf2out_frame_debug (rtx insn, rtx where) { rtx note, n; bool handled_one = false; @@ -2183,13 +2182,13 @@ dwarf2out_frame_debug (rtx insn, bool af /* Remember where we are to insert notes. Do not separate tablejump insns from their ADDR_DIFF_VEC. Putting the note after the VEC should be ok. */ - if (after_p) + if (insn == where) { if (!tablejump_p (insn, NULL, &cfi_insn)) - cfi_insn = insn; + cfi_insn = where; } else - cfi_insn = PREV_INSN (insn); + cfi_insn = where; if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn)) dwarf2out_flush_queued_reg_saves (); @@ -2200,7 +2199,7 @@ dwarf2out_frame_debug (rtx insn, bool af matter if the stack pointer is not the CFA register anymore but is still used to save registers. */ if (!ACCUMULATE_OUTGOING_ARGS) - dwarf2out_notice_stack_adjust (insn, after_p); + dwarf2out_notice_stack_adjust (insn, (insn == where)); cfi_insn = NULL; return; } @@ -2434,7 +2433,7 @@ create_cfi_notes (void) if (BARRIER_P (insn)) { - dwarf2out_frame_debug (insn, false); + dwarf2out_frame_debug (insn, PREV_INSN (insn)); continue; } @@ -2469,7 +2468,7 @@ create_cfi_notes (void) pat = PATTERN (insn); if (asm_noperands (pat) >= 0) { - dwarf2out_frame_debug (insn, false); + dwarf2out_frame_debug (insn, PREV_INSN (insn)); continue; } @@ -2477,14 +2476,14 @@ create_cfi_notes (void) { int i, n = XVECLEN (pat, 0); for (i = 1; i < n; ++i) - dwarf2out_frame_debug (XVECEXP (pat, 0, i), false); + dwarf2out_frame_debug (XVECEXP (pat, 0, i), PREV_INSN (insn)); } if (CALL_P (insn) || find_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL)) - dwarf2out_frame_debug (insn, false); + dwarf2out_frame_debug (insn, PREV_INSN (insn)); - dwarf2out_frame_debug (insn, true); + dwarf2out_frame_debug (insn, insn); } }