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);
     }
 }

Reply via email to