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: [email protected]
ReportedBy: [email protected]
CC: [email protected]
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);
}
}