Here's a new version, which adds support for mips16 and tries to avoid
the window with the frame pointer restore.

Testing mips16 is problematic, all the execute tests fail before and
after - I interpret one of your earlier mails to say that this is
expected. There are no new compilation failures with this patch, but
incorrect earlier versions triggered a few, indicating that the testing
is at least somewhat useful.

I get the following output for restore insns:

        move    $sp,$17
        restore 8,$16,$17
$LCFI2 = .
        .cfi_remember_state
        .cfi_restore 16
        .cfi_restore 17
        .cfi_def_cfa 29, 0

which I think is correct.

Question for Richard H.: What is this actually good for, other than
presenting consistent information to dwarf2cfi? Do we actually expect
code to unwind through the middle of an epilogue?


Bernd
        * config/mips/mips.c (cfa_restores, cfa_sp_offset): New static
        variables.
        (mips16e_save_restore_reg): Add to cfa_restores.
        (mips_restore_reg): Add to cfa_restores, and add a REG_CFA_DEF_CFA
        note to insns restoring the frame pointer.
        (mips_expand_epilogue): Initialize the new variables.  Annotate RTL
        to ensure dwarf2cfi sees the effects of the epilogue.  Generate a
        simple_return only if the return address is in r31.

Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      (revision 178135)
+++ gcc/config/mips/mips.c      (working copy)
@@ -501,6 +501,11 @@ int sdb_label_count;
 int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
 int mips_dwarf_regno[FIRST_PSEUDO_REGISTER];
 
+/* Used to collect REG_CFA notes during epilogue generation.  */
+static rtx cfa_restores = NULL_RTX;
+/* Used to produce REG_CFA_DEF_CFA notes during epilogue generation.  */
+static HOST_WIDE_INT cfa_sp_offset;
+
 /* The nesting depth of the PRINT_OPERAND '%(', '%<' and '%[' constructs.  */
 struct mips_asm_switch mips_noreorder = { "reorder", 0 };
 struct mips_asm_switch mips_nomacro = { "macro", 0 };
@@ -8371,8 +8376,8 @@ mips16e_collect_argument_saves (void)
 }
 
 /* Return a move between register REGNO and memory location SP + OFFSET.
-   Make the move a load if RESTORE_P, otherwise make it a frame-related
-   store.  */
+   Make the move a load and update cfa_restores if RESTORE_P, otherwise
+   make it a frame-related store.  */
 
 static rtx
 mips16e_save_restore_reg (bool restore_p, HOST_WIDE_INT offset,
@@ -8382,6 +8387,9 @@ mips16e_save_restore_reg (bool restore_p
 
   mem = gen_frame_mem (SImode, plus_constant (stack_pointer_rtx, offset));
   reg = gen_rtx_REG (SImode, regno);
+  if (restore_p)
+    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+
   return (restore_p
          ? gen_rtx_SET (VOIDmode, reg, mem)
          : mips_frame_set (mem, reg));
@@ -10227,17 +10236,30 @@ mips_expand_prologue (void)
     emit_insn (gen_blockage ());
 }
 
-/* Emit instructions to restore register REG from slot MEM.  */
+/* Emit instructions to restore register REG from slot MEM.  Also update
+   the cfa_restores list.  */
 
 static void
 mips_restore_reg (rtx reg, rtx mem)
 {
+  rtx orig_reg = reg;
+  rtx last;
+
   /* There's no MIPS16 instruction to load $31 directly.  Load into
      $7 instead and adjust the return insn appropriately.  */
   if (TARGET_MIPS16 && REGNO (reg) == RETURN_ADDR_REGNUM)
     reg = gen_rtx_REG (GET_MODE (reg), GP_REG_FIRST + 7);
 
   mips_emit_save_slot_move (reg, mem, MIPS_EPILOGUE_TEMP (GET_MODE (reg)));
+  if (reg == orig_reg)
+    cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+
+  if (!frame_pointer_needed || REGNO (reg) != HARD_FRAME_POINTER_REGNUM)
+    return;
+  last = get_last_insn ();
+  add_reg_note (last, REG_CFA_DEF_CFA, plus_constant (stack_pointer_rtx,
+                                                     cfa_sp_offset));
+  RTX_FRAME_RELATED_P (last) = 1;
 }
 
 /* Emit any instructions needed before a return.  */
@@ -10268,6 +10290,8 @@ mips_expand_epilogue (bool sibcall_p)
   HOST_WIDE_INT step1, step2;
   rtx base, target, insn;
 
+  cfa_restores = NULL_RTX;
+
   if (!sibcall_p && mips_can_use_return_insn ())
     {
       emit_jump_insn (gen_return ());
@@ -10306,6 +10330,8 @@ mips_expand_epilogue (bool sibcall_p)
       step1 -= step2;
     }
 
+  cfa_sp_offset = step2;
+
   /* Set TARGET to BASE + STEP1.  */
   target = base;
   if (step1 > 0)
@@ -10324,12 +10350,26 @@ mips_expand_epilogue (bool sibcall_p)
       if (!TARGET_MIPS16)
        target = stack_pointer_rtx;
 
-      emit_insn (gen_add3_insn (target, base, adjust));
+      insn = emit_insn (gen_add3_insn (target, base, adjust));
+      if (!frame_pointer_needed && target == stack_pointer_rtx)
+       {
+         RTX_FRAME_RELATED_P (insn) = 1;
+         add_reg_note (insn, REG_CFA_DEF_CFA,
+                       plus_constant (stack_pointer_rtx, step2));
+       }
     }
 
   /* Copy TARGET into the stack pointer.  */
   if (target != stack_pointer_rtx)
-    mips_emit_move (stack_pointer_rtx, target);
+    {
+      insn = mips_emit_move (stack_pointer_rtx, target);
+      if (!frame_pointer_needed)
+       {
+         add_reg_note (insn, REG_CFA_DEF_CFA,
+                       plus_constant (stack_pointer_rtx, step2));
+         RTX_FRAME_RELATED_P (insn) = 1;
+       }
+    }
 
   /* If we're using addressing macros, $gp is implicitly used by all
      SYMBOL_REFs.  We must emit a blockage insn before restoring $gp
@@ -10357,7 +10397,10 @@ mips_expand_epilogue (bool sibcall_p)
 
       /* Restore the remaining registers and deallocate the final bit
         of the frame.  */
-      emit_insn (restore);
+      restore = emit_insn (restore);
+      REG_NOTES (restore) = cfa_restores;
+      RTX_FRAME_RELATED_P (restore) = 1;
+      add_reg_note (restore, REG_CFA_DEF_CFA, stack_pointer_rtx);
     }
   else
     {
@@ -10393,9 +10436,14 @@ mips_expand_epilogue (bool sibcall_p)
 
          /* If we don't use shoadow register set, we need to update SP.  */
          if (!cfun->machine->use_shadow_register_set_p && step2 > 0)
-           emit_insn (gen_add3_insn (stack_pointer_rtx,
-                                     stack_pointer_rtx,
-                                     GEN_INT (step2)));
+           {
+             insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
+                                              stack_pointer_rtx,
+                                              GEN_INT (step2)));
+             REG_NOTES (insn) = cfa_restores;
+             RTX_FRAME_RELATED_P (insn) = 1;
+             add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
+           }
 
          /* Move to COP0 Status.  */
          emit_insn (gen_cop0_move (gen_rtx_REG (SImode, COP0_STATUS_REG_NUM),
@@ -10405,9 +10453,14 @@ mips_expand_epilogue (bool sibcall_p)
        {
          /* Deallocate the final bit of the frame.  */
          if (step2 > 0)
-           emit_insn (gen_add3_insn (stack_pointer_rtx,
-                                     stack_pointer_rtx,
-                                     GEN_INT (step2)));
+           {
+             insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
+                                              stack_pointer_rtx,
+                                              GEN_INT (step2)));
+             REG_NOTES (insn) = cfa_restores;
+             RTX_FRAME_RELATED_P (insn) = 1;   
+             add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx);
+           }
        }
     }
 
@@ -10442,7 +10495,7 @@ mips_expand_epilogue (bool sibcall_p)
        }
       else
        {
-         unsigned int regno;
+         rtx pat;
 
          /* When generating MIPS16 code, the normal
             mips_for_each_saved_gpr_and_fpr path will restore the return
@@ -10450,11 +10503,16 @@ mips_expand_epilogue (bool sibcall_p)
          if (TARGET_MIPS16
              && !GENERATE_MIPS16E_SAVE_RESTORE
              && BITSET_P (frame->mask, RETURN_ADDR_REGNUM))
-           regno = GP_REG_FIRST + 7;
+           {
+             rtx reg = gen_rtx_REG (Pmode, GP_REG_FIRST + 7);
+             pat = gen_return_internal (reg);
+           }
          else
-           regno = RETURN_ADDR_REGNUM;
-         emit_jump_insn (gen_simple_return_internal (gen_rtx_REG (Pmode,
-                                                                  regno)));
+           {
+             rtx reg = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+             pat = gen_simple_return_internal (reg);
+           }
+         emit_jump_insn (pat);
        }
     }
 

Reply via email to