<div>Hey Eli,</div><div><br></div>On Thu, Feb 14, 2013 at 5:45 PM, Eli Bendersky <span dir="ltr"><<a href="mailto:eliben@google.com" target="_blank">eliben@google.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hello,<br>
<br>
While investigating one of the existing tests<br>
(test/CodeGen/X86/tailcallpic2.ll), I ran into IR that produces some<br>
interesting code. The IR is very straightforward:<br>
<br>
define protected fastcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4) {<br>
entry:<br>
ret i32 %a3<br>
}<br>
<br>
define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {<br>
entry:<br>
%tmp11 = tail call fastcc i32 @tailcallee( i32 %in1, i32 %in2, i32<br>
%in1, i32 %in2)<br>
ret i32 %tmp11<br>
}<br>
<br>
define i32 @foo(i32 %in1, i32 %in2) {<br>
entry:<br>
  %q = call fastcc i32 @tailcaller(i32 %in2, i32 %in1)<br>
  %ww = sub i32 %q, 6<br>
  ret i32 %ww<br>
}<br>
<br>
Built with (ToT LLVM):<br>
llc < ~/temp/z.ll  -march=x86 -tailcallopt -O3<br>
<br>
The produced code is (cleaned up a bit)<br>
<br>
tailcallee:                             # @tailcallee<br>
  movl  4(%esp), %eax<br>
  ret  $12<br>
<br>
tailcaller:                             # @tailcaller<br>
  subl  $12, %esp<br>
  movl  %edx, 20(%esp)<br>
  movl  %ecx, 16(%esp)<br>
  addl  $12, %esp<br>
  jmp  tailcallee              # TAILCALL<br>
<br>
foo:                                    # @foo<br>
  subl  $12, %esp<br>
  movl  20(%esp), %ecx<br>
  movl  16(%esp), %edx<br>
  calll  tailcaller<br>
  subl  $12, %esp<br>
  addl  $-6, %eax<br>
  addl  $12, %esp<br>
  ret<br>
<br>
A number of questions arise here:<br>
<br>
1) Notice that 'tailcaller' goes beyond its own stack frame when<br>
arranging arguments for 'tailcallee'. It subs 12 from %esp, but then<br>
writes to 20(%esp). Clearly, something in the fastcc convention allows<br>
it to assume that stack space will be available there? What is it? </blockquote><div><br></div><div>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.</div>
<div><br></div><div>I suspect that this is legal since tailcallee is a leaf function and the writes are into the "red zone".</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
2) Note the %esp dance 'tailcaller' is doing - completely useless sub<br>
followed by add. Does this have an inherent goal or can it be<br>
eliminated?<br>
<br>
3) The %esp dance of 'foo' is even stranger:<br>
<br>
  subl  $12, %esp<br>
  addl  $-6, %eax<br>
  addl  $12, %esp<br>
<br>
The subl and addl to %esp cancel out, and with an unrelated operation<br>
in between. Why are they needed?<br></blockquote><div><br></div><div>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, </div>
<div><br></div><div>  subl  $12, %esp <= Matches the "ret $12" from tailcallee's epilogue.<br>  addl  $-6, %eax <br>  addl  $12, %esp <= Matches the "subl  $12, %esp" from foo's prologue.</div>
<div><br></div><div>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.</div>
<div><br></div><div>-Cameron</div></div>