[LLVMdev] RFC: Tail call optimization X86

Dale Johannesen dalej at apple.com
Fri Oct 5 11:00:47 PDT 2007


On Oct 5, 2007, at 10:41 AM, Evan Cheng wrote:

>
> On Oct 5, 2007, at 2:42 AM, Arnold Schwaighofer wrote:
>
>> Hi Evan,
>> I incoporated the changes you request but to the following i have got
>> a question:
>>
>>> Also, moving the option
>>> there will allow us to change fastcc ABI (callee popping arguments)
>>> only when this option is on. See Chris' email:
>>
>> I am not to sure on that. because that would make modules compiled
>> with the flag on incompatible with ones compiled without the flag off
>> as stack behaviour would mismatch.
>> It would be no problem to make the behaviour dependent on the -tail-
>> call-opt flag. i am not sure that this is a good idea?
>
> In theory, any function can be marked fastcc. But llvm-gcc c / c++
> frontend does *not* mark any external functions fastcc.

The user can specify the "fastcall" and "stdcall" attributes, and it  
looks
to me like llvm-gcc honors that.  Certainly it should.

> Also, the
> optimizer only changes the calling convention of internal functions
> to fastcc. We can set a policy of treating fastcc external functions
> as c functions. Then there is no chance of introducing ABI
> incompatibility.
>
>>
>> pseudocode:
>>
>> module 1: with -tailcallopt enabled
>> fastcc int callee(int arg1, int arg2) {
>> ...
>> -> onreturn: pops 8 byte
>> }
>>
>> module 2: no -tailcallopt
>> fastcc int caller() {
>> 	int x= call fastcc callee();
>> 	//!! caller pops the arguments => stack mismatch
>>
>> callee pops the arguments but caller also wants to pop the arguments
>> of the stack
>>
>> Apparently i forgot to send the answer email to chris reponse. sorry
>> for that.
>>>
>>>> Hmmm. Ok. So this is due to X86CallingConv.td changes?  
>>>> Unfortunately
>>>> that's not controlled by options. Ok then.
>>>>
>>>
>>> Sure it can be, you can set up custom predicates, for example the
>>> X86CallingConv.td file has:
>>>
>>> class CCIfSubtarget<string F, CCAction A>
>>>   : CCIf<!strconcat("State.getTarget().getSubtarget<X86Subtarget>
>>> ().", F), A>;
>>>
>>> It would be straight-forward to have a CCIf defined to check some
>>> command
>>> line argument.  I think enabling this as llcbeta for a few nights
>>> makes
>>> sense before turning it on by default.
>> No not directly. The code related to "caller/callee cleans arguments
>> off the stack" is not controlled by the .td. It's controlled in code
>> by the operands of CALLSEQ_END.
>
> Ok, that's even easier to have it be controlled by the command line
> option.
>
> Evan
>
>>
>> for example in SDOperand X86TargetLowering::LowerCCCCallTo:
>> ...
>>    if (CC == CallingConv::X86_StdCall || CC == CallingConv::Fast) {
>>      if (isVarArg)
>>        NumBytesForCalleeToPush = isSRet ? 4 : 0;
>>      else
>>        NumBytesForCalleeToPush = NumBytes;
>>      assert(!(isVarArg && CC==CallingConv::Fast) &&
>>              "CallingConv::Fast does not support varargs.");
>>    } else {
>>      // If this is is a call to a struct-return function, the callee
>>      // pops the hidden struct pointer, so we have to push it back.
>>      // This is common for Darwin/X86, Linux & Mingw32 targets.
>>      NumBytesForCalleeToPush = isSRet ? 4 : 0;
>>    }
>>
>>    NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
>>    Ops.clear();
>>    Ops.push_back(Chain);
>>    Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
>>    Ops.push_back(DAG.getConstant(NumBytesForCalleeToPush,  
>> getPointerTy
>> ()));
>>    Ops.push_back(InFlag);
>>    Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size
>> ());
>>    InFlag = Chain.getValue(1);
>>
>>    The third operand is the number of bytes the callee pops of the
>> stack on return (on x86). This gets lowered to a ADJCALLSTACKUP
>> pseudo machineinstruction.
>>
>> Later when X86RegisterInfo::eliminateCallFramePseudoInstr is called
>> and framepointerelimination is enabled the following code gets  
>> called:
>> ...
>>    else if (I->getOpcode() == X86::ADJCALLSTACKUP) {
>>      // If we are performing frame pointer elimination and if the
>> callee pops
>>      // something off the stack pointer, add it back.  We do this
>> until we have
>>      // more advanced stack pointer tracking ability.
>>      if (uint64_t CalleeAmt = I->getOperand(1).getImm()) {
>>        unsigned Opc = (CalleeAmt < 128) ?
>>          (Is64Bit ? X86::SUB64ri8 : X86::SUB32ri8) :
>>          (Is64Bit ? X86::SUB64ri32 : X86::SUB32ri);
>>        MachineInstr *New =
>>          BuildMI(TII.get(Opc), StackPtr).addReg(StackPtr).addImm
>> (CalleeAmt);
>>        MBB.insert(I, New);
>>      }
>>    }
>>
>> I am not sure about a command line switch would toggling the stack
>> adjusting behaviour of a function. Because if the function is called
>> from a different module which was compiled with the opposite command
>> line switch all hell would break loose (because it assumes callee
>> pops arguments when it does not).
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
> _______________________________________________
> 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