This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: forcing tail/sibling call optimization


On 03-Jan-2001, Richard Henderson <rth@redhat.com> wrote:
> On Thu, Jan 04, 2001 at 10:53:15AM +1100, Fergus Henderson wrote:
> > On 03-Jan-2001, Richard Henderson <rth@redhat.com> wrote:
> > > if the front end didn't really care if the tail
> > > call didn't happen, it could query the target before setting the bit.
> >
> > How can it query the target?  The query needed is not just "does this
> > target support tail calls", it is "does this target support *this*
> > tail call", and the answer can depend on lots of stuff that the front
> > end doesn't want to know about.
> 
> See FUNCTION_OK_FOR_SIBCALL; cfun->decl must be valid during the
> query so that the target can compare return types (see the x86
> version for why this matters).

But that's just one of the many ways in which sibling call optimization
can fail.  There's lots of other ways it can fail in expand_call()
[see below].  Note that quite a few of these ways are just limitations
of the current implementation, not inherent requirements.  It seems
like a bad idea to duplicate that logic in the language front-end. 

P.S.

For completeness here a list of some of the other ways it can
fail in expand_call(). 

 |      || args_size.var)
 ...
 | #ifdef HAVE_sibcall_epilogue
 |       !HAVE_sibcall_epilogue
 | #else
 |       1
 | #endif
 ...
 |       /* Doing sibling call optimization needs some work, since
 |          structure_value_addr can be allocated on the stack.
 |          It does not seem worth the effort since few optimizable
 |          sibling calls will return a structure.  */
 |       || structure_value_addr != NULL_RTX
 |       /* If the register holding the address is a callee saved
 |          register, then we lose.  We have no way to prevent that,
 |          so we only allow calls to named functions.  */
 |       /* ??? This could be done by having the insn constraints
 |          use a register class that is all call-clobbered.  Any
 |          reload insns generated to fix things up would appear
 |          before the sibcall_epilogue.  */
 |       || fndecl == NULL_TREE
 |       || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
 |       || TREE_THIS_VOLATILE (fndecl)
 |       || !FUNCTION_OK_FOR_SIBCALL (fndecl)
 |       /* If this function requires more stack slots than the current
 |          function, we cannot change it into a sibling call.  */
 |       || args_size.constant > current_function_args_size
 |       /* If the callee pops its own arguments, then it must pop exactly
 |          the same number of arguments as the current function.  */
 |       || RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
 |          != RETURN_POPS_ARGS (current_function_decl,
 |                               TREE_TYPE (current_function_decl),
 |                               current_function_args_size))
 ...
 |       /* Handle calls that return values in multiple non-contiguous locations.
 |          The Irix 6 ABI has examples of this.  */
 |       else if (GET_CODE (valreg) == PARALLEL)
 |         {
 ...
 |           /* We can not support sibling calls for this case.  */
 |           sibcall_failure = 1;


-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]