[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