[LLVMdev] Question about fastcc assumptions and seemingly superfluous %esp updates
Cameron McInally
cameron.mcinally at nyu.edu
Thu Feb 14 16:15:58 PST 2013
Hey Eli,
On Thu, Feb 14, 2013 at 5:45 PM, Eli Bendersky <eliben at google.com> wrote:
> Hello,
>
> While investigating one of the existing tests
> (test/CodeGen/X86/tailcallpic2.ll), I ran into IR that produces some
> interesting code. The IR is very straightforward:
>
> define protected fastcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32
> %a4) {
> entry:
> ret i32 %a3
> }
>
> define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
> entry:
> %tmp11 = tail call fastcc i32 @tailcallee( i32 %in1, i32 %in2, i32
> %in1, i32 %in2)
> ret i32 %tmp11
> }
>
> define i32 @foo(i32 %in1, i32 %in2) {
> entry:
> %q = call fastcc i32 @tailcaller(i32 %in2, i32 %in1)
> %ww = sub i32 %q, 6
> ret i32 %ww
> }
>
> Built with (ToT LLVM):
> llc < ~/temp/z.ll -march=x86 -tailcallopt -O3
>
> The produced code is (cleaned up a bit)
>
> tailcallee: # @tailcallee
> movl 4(%esp), %eax
> ret $12
>
> tailcaller: # @tailcaller
> subl $12, %esp
> movl %edx, 20(%esp)
> movl %ecx, 16(%esp)
> addl $12, %esp
> jmp tailcallee # TAILCALL
>
> foo: # @foo
> subl $12, %esp
> movl 20(%esp), %ecx
> movl 16(%esp), %edx
> calll tailcaller
> subl $12, %esp
> addl $-6, %eax
> addl $12, %esp
> ret
>
> A number of questions arise here:
>
> 1) Notice that 'tailcaller' goes beyond its own stack frame when
> arranging arguments for 'tailcallee'. It subs 12 from %esp, but then
> writes to 20(%esp). Clearly, something in the fastcc convention allows
> it to assume that stack space will be available there? What is it?
It looks like your call is being converted to a tailcall. I agree that
those stack writes are setting up the arguments for tailcallee. Although, I
haven't done the stack frame math to say for sure.
I suspect that this is legal since tailcallee is a leaf function and the
writes are into the "red zone".
> 2) Note the %esp dance 'tailcaller' is doing - completely useless sub
> followed by add. Does this have an inherent goal or can it be
> eliminated?
>
> 3) The %esp dance of 'foo' is even stranger:
>
> subl $12, %esp
> addl $-6, %eax
> addl $12, %esp
>
> The subl and addl to %esp cancel out, and with an unrelated operation
> in between. Why are they needed?
>
I'm not an expert in this area, but I believe that "ret $12" cleans up the
stack by adding 12 bytes to %esp; an artifact of the tailcall conversion.
So,
subl $12, %esp <= Matches the "ret $12" from tailcallee's epilogue.
addl $-6, %eax
addl $12, %esp <= Matches the "subl $12, %esp" from foo's prologue.
I suppose they're explicitly needed in case a stack operation occurs after
the call and before the return. I wonder if the spiller has not run yet
when the tailcall decision is made, or something similar.
-Cameron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130214/a4b6829c/attachment.html>
More information about the llvm-dev
mailing list