On 15-12-13 04:37, Alan Modra wrote:
On Sat, Dec 14, 2013 at 09:14:34PM +0100, Tom de Vries wrote:
I wonder if OUTGOING_REG_PARM_STACK_SPACE makes a difference here.
If OUTGOING_REG_PARM_STACK_SPACE == 0, it is the responsibility of
the callee to allocate the area reserved for arguments passed in
registers. AFAIU, both functions a and b would do that in their own
stack frame, and there's no need to test for reg_parm_stack_space !=
REG_PARM_STACK_SPACE (current_function_decl).
If OUTGOING_REG_PARM_STACK_SPACE != 0, it is the responsibility of
the caller to allocate the area reserved for arguments passed in
registers. Which means that function a and b share the space
allocated by the caller of function a.
AFAIU, what is required is reg_parm_stack_space <=
REG_PARM_STACK_SPACE (current_function_decl).
Hi Tom, I happened to be looking at this code a few weeks ago as part
of the PowerPC64 ELFv2 ABI work. I missed seeing the fndecl /
current_function_decl bug, but came to the same conclusion as
you do above regarding reg_parm_stack_space. In fact, I think you can
go a little further. Not all changes in OUTGOING_REG_PARM_STACK_SPACE
are bad. If the current function has OUTGOING_REG_PARM_STACK_SPACE
non-zero then a sibcall to a function with
OUTGOING_REG_PARM_STACK_SPACE zero ought to be OK. So..
#ifdef REG_PARM_STACK_SPACE
- /* If outgoing reg parm stack space changes, we can not do sibcall. */
- || (OUTGOING_REG_PARM_STACK_SPACE (funtype)
- != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl)))
- || (reg_parm_stack_space != REG_PARM_STACK_SPACE (fndecl))
+ || (OUTGOING_REG_PARM_STACK_SPACE (funtype)
+ && (!OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl))
+ || (reg_parm_stack_space
+ > REG_PARM_STACK_SPACE (current_function_decl))))
#endif
Hi Alan,
I agree.
FWIW, AFAIU you could take it even further with IPA. Say you have function a
tail-calling function b, and function b tail-calling function c, and
OUTGOING_REG_PARM_STACK_SPACEs 1 (a), 0 (b), and 1 (c).
The snippet above allows the call to function b to be a sibling call, but not
the call to function c.
Still the call to function c could be a sibling call, if the call to function b
is translated as a sibling call. The space needed by function c is then provided
by the caller of function a (if REG_PARM_STACK_SPACE (c) <= REG_PARM_STACK_SPACE
(a)).
Thanks,
Tom