resource.c (as used by dbr_schedule) considers the stack pointer to be
unused on entry to the epilogue if:

    EXIT_IGNORE_STACK
    && frame_pointer_needed
    && !current_function_sp_is_unchanging

Then the stack deallocation in the epilogue usually causes the
stack pointer to become live on function exit (which it must
always be):

  while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
    {
      mark_set_resources (epilogue_insn, &end_of_function_needs, 0,
                          MARK_SRC_DEST_CALL);
      if (return_insn_p (epilogue_insn))
        break;
    }

But in gcc.c-torture/execute/920428-2.c -Os on mips64-linux-gnu,
we have a case where the shrink-wrapped part of the function
requires a frame but has no normal exits.  There is therefore
no epilogue.  This means that the stack pointer is never added
to end_of_function_needs, and dbr_schedule thinks that normal
exits (which are all outside the shrink-wrapped part) do not
care about the stack pointer.  We then end up speculatively
executing the prologue stack allocation.

One fix would be to add:

  SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);

after the loop above, but it felt odd for start_of_epilogue_needs
to be different from end_of_function_needs when there is no epilogue.
The patch below seemed better.

Tested on mips64-linux-gnu.  OK to install?

Richard


gcc/
        * resource.c (init_resource_info): Only consider EXIT_IGNORE_STACK
        if there is in epilogue.

Index: gcc/resource.c
===================================================================
--- gcc/resource.c      2011-11-26 14:38:30.000000000 +0000
+++ gcc/resource.c      2011-11-26 14:40:04.000000000 +0000
@@ -1145,11 +1145,11 @@ init_resource_info (rtx epilogue_insn)
   basic_block bb;
 
   /* Indicate what resources are required to be valid at the end of the current
-     function.  The condition code never is and memory always is.  If the
-     frame pointer is needed, it is and so is the stack pointer unless
-     EXIT_IGNORE_STACK is nonzero.  If the frame pointer is not needed, the
-     stack pointer is.  Registers used to return the function value are
-     needed.  Registers holding global variables are needed.  */
+     function.  The condition code never is and memory always is.
+     The stack pointer is needed unless EXIT_IGNORE_STACK is true
+     and there is an epilogue that restores the original stack pointer
+     from the frame pointer.  Registers used to return the function value
+     are needed.  Registers holding global variables are needed.  */
 
   end_of_function_needs.cc = 0;
   end_of_function_needs.memory = 1;
@@ -1162,11 +1162,11 @@ init_resource_info (rtx epilogue_insn)
 #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
       SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
 #endif
-      if (! EXIT_IGNORE_STACK
-         || current_function_sp_is_unchanging)
-       SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
     }
-  else
+  if (!(EXIT_IGNORE_STACK
+       && epilogue_insn
+       && frame_pointer_needed
+       && !current_function_sp_is_unchanging))
     SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
 
   if (crtl->return_rtx != 0)

Reply via email to