Patchwork Shrink-wrapping vs. EXIT_IGNORE_STACK

login
register
mail settings
Submitter Richard Sandiford
Date Nov. 27, 2011, 10:31 a.m.
Message ID <87fwh96emq.fsf@firetop.home>
Download mbox | patch
Permalink /patch/127881/
State New
Headers show

Comments

Richard Sandiford - Nov. 27, 2011, 10:31 a.m.
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.
Eric Botcazou - Dec. 4, 2011, 4:33 p.m.
> 	* resource.c (init_resource_info): Only consider EXIT_IGNORE_STACK
> 	if there is in epilogue.

OK, but keep the original order of the tests, i.e. EXIT_IGNORE_STACK is tested 
only after we know there is a frame pointer:

  if (!(frame_pointer_needed
        && EXIT_IGNORE_STACK
        && epilogue_insn
        && !current_function_sp_is_unchanging))
     SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);

Patch

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)