[LLVMdev] RFC: Tail call optimization X86
Evan Cheng
evan.cheng at apple.com
Tue Sep 25 11:14:11 PDT 2007
On Sep 25, 2007, at 12:01 AM, Arnold Schwaighofer wrote:
>>> FastCC use to be caller pops arguments so there was no stack
>>> adjustment after the
>>> call to qux. Now FastCC has callee pops arguments on return
>>> semantics
>>> so the
>>> x86 backend inserts a stack adjustment after the call.
>>>
>>> _array:
>>> subl $12, %esp
>>> movss LCPI1_0, %xmm0
>>> mulss 16(%esp), %xmm0
>>> movss %xmm0, (%esp)
>>> call L_qux$stub
>>> subl $4, %esp << stack adjustment because qux pops
>>> arguments on return
>>> mulss LCPI1_0, %xmm0
>>> addl $12, %esp
>>> ret $4
>>
>> Ok. Please make sure for now this only takes effect if tail call
>> optimization is turned on though. Also, we need to fold the subl
>> into
>> addl if possible.
> I think you misunderstood me. I have not added code to insert this
> subl it is done already by the backend (before my changes) with
> certain calling conventions (callee pops arguments). There used to be
> already calling conventions e.g. x86_fastcall that would have cause
> the stack adjustment only fastcc was not one of them. Now that fastcc
> can cause tail call optimization i had to change the convention from
> caller pops arguments to callee pops arguments in order to allow tail
> call optimization in a general way.
Hmmm. Ok. So this is due to X86CallingConv.td changes? Unfortunately
that's not controlled by options. Ok then.
>>
>>>
>>>
>>>> Index: include/llvm/Target/TargetLowering.h
>>>> ===================================================================
>>>> --- include/llvm/Target/TargetLowering.h (revision 42247)
>>>> +++ include/llvm/Target/TargetLowering.h (working copy)
>>>> @@ -851,8 +851,18 @@
>>>> virtual std::pair<SDOperand, SDOperand>
>>>> LowerCallTo(SDOperand Chain, const Type *RetTy, bool
>>>> RetTyIsSigned,
>>>> bool isVarArg, unsigned CallingConv, bool
>>>> isTailCall,
>>>> - SDOperand Callee, ArgListTy &Args, SelectionDAG
>>>> &DAG);
>>>> + bool isNextInstRet, SDOperand Callee, ArgListTy
>>>> &Args,
>>>> + SelectionDAG &DAG);
>>>> + // IsEligibleForTailCallElimination - Check whether the call is
>>>> eligible for
>>>> + // tailcall elimination
>>>> + virtual bool IsEligibleForTailCallElimination(SelectionDAG& DAG,
>>>> + bool
>>>> IsNextInstRet,
>>>> + SDOperand Callee,
>>>> + unsigned CalleeCC)
>>>> const {
>>>> + return false;
>>>> + }
>>>> +
>>>>
>>>> I am not too keen on "isNextInstRet". We should never use
>>>> instruction
>>>> ordering before scheduling to determine whether it's possible to
>>>> perform an optimization. IsEligibleForTailCallElimination() should
>>>> determine the feasibility on its own, no?
>>>
>>> My assumption:
>>> Tail call optimization is performed if the instruction following the
>>> call is
>>> a return and the return uses the result of the call or is a void
>>> return.
>>
>> Ok. But using whether the next instruction is a return at this
>> time is
>> too restrictive. It's possible there may be instructions that are
>> between the call and the return that do not interfere with tail call
>> optimization.
>>
>>>
>>>
>>> The problem is that at the point (in TargetLowering:LowerCallTo)
>>> where
>>> IsEligibleForTailCallElimination is called the SDOperand node for
>>> the
>>> following instructions (we are looking for a return) has not been
>>> build.
>>> So IsEligibleForTailCallElimination can't determine - using
>>> 'Callee' -
>>> whether the instruction following the call is a return. That is the
>>> reason
>>> why i pass the IsNextInstRet flag to TargetLowering::LowerCallTo.
>>
>> Right. But I think the right way to deal with this is to assume all
>> the tail calls are eligible for tail call optimizations at this
>> point.
>> Then checks for eligibility and fix the call nodes after all the
>> instructions are lowered.
> I am not sure that i understand where this point would be. As I view
> it the only place would be in LegalizeDAG.cpp in
No, in SelectionDAGISel.cpp:BuildSelectionDAG(). After line 4610, the
complete DAG is available. You can add a call here to look at the
last call and the terminator to decide whether the call is really a
candidate for tail call optimization. You can fix it up at this point.
Evan
>
> SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
> ...
> case ISD::CALL:
> // The only option for this is to custom lower it.
> Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
>
> }
>
> would change to (pseudo code)
> SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
> SDOperand Result = Op;
> ...
> case ISD::CALL:
> // The only option for this is to custom lower it.
>
> Result =
> modifyCallSoThatTailAttributeReallyIndicatesWhetherThisCallIsEligibleF
> orTailCallOptimization(Result);
>
> Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
>
> }
>
> because any point after that (e.g. scheduling) would be to late
> because the target specific loweringcode (e.g. LowerCALL ->
> LowerCCCall)
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list