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. 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
On 5 Oct 2007, at 19:41, 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. Also, the > optimizer only changes the calling convention of internal functions > to fastcc.well i hope llvm-gcc won't stay the only front-end (hoping to see some functional languages like ocaml ;)> We can set a policy of treating fastcc external functions > as c functions. Then there is no chance of introducing ABI > incompatibility.this means limiting tail call opt to protected/invisible functions within a module? a little limiting i think. but i think if it is documented that there will be a incompatibility between modules compiled with tailcallopt on/off that is okay? and this would only happen if someone other than llvm-gcc used llvm as a backend anyway. so i will make tailcallopt toggle the stack adjusting behaviour. with llvm-gcc this won't be a problem and if someone other using llvm as a backend runs in to a problem than there is the documentation and the maillist that will help. is that okay? regards arnold
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
On 5 Oct 2007, at 20:00, Dale Johannesen wrote:>>> 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.This would imply one fastcc abi (callee pops args on return) to rule them all? That is only if fastcall translates to llvm fastcc of course. regards
On 2007-10-05, at 13:56, Arnold Schwaighofer wrote:> well i hope llvm-gcc won't stay the only front-end (hoping to see > some functional languages like ocaml ;):) — Gordon -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20071005/a4fe6650/attachment.html>
On Oct 5, 2007, at 10:56 AM, Arnold Schwaighofer wrote:> >> We can set a policy of treating fastcc external functions >> as c functions. Then there is no chance of introducing ABI >> incompatibility. > this means limiting tail call opt to protected/invisible functions > within a module? > a little limiting i think.It makes sense to be extra careful at this point. The policy can be changed when we enable tail call optimization by default.> > but i think if it is documented that there will be a incompatibility > between > modules compiled with tailcallopt on/off that is okay? > and this would only happen if someone other than llvm-gcc used llvm > as a backend > anyway.Documentation isn't going to be enough. We will do everything possible to ensure there isn't abi incompatibility. But at this point, it's important the patch does not impact codegen in any way when tail call optimization is off. This allows us to get a true sense of the performance impact. Evan> > so i will make tailcallopt toggle the stack adjusting behaviour. with > llvm-gcc this won't be a problem > and if someone other using llvm as a backend runs in to a problem > than there is the documentation > and the maillist that will help. > > is that okay? > > regards arnold > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
On 2007-10-05, at 13:56, Arnold Schwaighofer wrote:> On 5 Oct 2007, at 19:41, Evan Cheng wrote: > >> In theory, any function can be marked fastcc. But llvm-gcc c / c++ >> frontend does *not* mark any external functions fastcc. Also, the >> optimizer only changes the calling convention of internal >> functions to fastcc. > > well i hope llvm-gcc won't stay the only front-end (hoping to see > some functional languages like ocaml ;)Just chiming in here since a stated goal is something I'm working on. Tail calls and calling conventions aren't yet a problem for me, but they're definitely on the radar. As context, my current goal is to support the existing Ocaml runtime with my LLVM-based compiler, despite the peculiarities of the runtime. Ocaml supports tail calls by never pushing arguments onto the stack. On x86, the first five arguments are passed using %eax, %ebx, %ecx, % edx, and %esi (left to right) and the sole return value is passed in % eax. (Ocaml never performs dynamic allocas, and so always performs frame pointer elimination. Floats are passed by reference.) The front- end will address the case of additional arguments. For my implementation of ocamlopt, the most useful LLVM features in this area would be would be support for the above cc, and tail calls for the inreg case. The former seems to be fairly well trivial; hopefully your work could be tweaked to accomplish the latter. — Gordon