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)