[LLVMdev] Broke my tail (call)

Arnold Schwaighofer
Tue, 24 Feb 2009 14:54:12 -0000

On Tue, Feb 24, 2009 at 11:50 AM, Jon Harrop <jon at ffconsultancy.com>
wrote:

> Thanks for the clarification. That makes a lot more sense!
>
> LLVM's support for structs is wonderful but I don't think they can
be
> called "first-class structs" until all such arbitrary
restrictions have been
> removed, even though the workaround (using sret form) is trivial in this
> case.
>
> Shall I file this as a bug against LLVM?
Yes please do and maybe include the following code which already
exhibits the error in the bug report.

define fastcc { { i8*, i8* }*, i8*} @init({ { i8*, i8* }*, i8*}, i32) {
entry:
      %2 = tail call fastcc { { i8*, i8* }*, i8* } @init({ { i8*,
i8*}*, i8*} %0, i32 %1)
      ret { { i8*, i8* }*, i8*} %2
}

> Assuming this gets fixed, will it be more efficient that the sret form?
Don't expect this to be fixed soon as i am currently on a leave of
absence from llvm busy with bringing tail calls to another vm and
writing a thesis about it ;).

Whether it will be more efficient i can't answer off hand. Sorry. But
probably not  because the code generated should be quite similar.

For the sret version the move of the result is performed before the return.
  store { i8*, i8* } %15, { i8*, i8* }* %19
  ret i32 0

For the struct return version this would be performed as part of
moving the result from the result registers to whatever virtual
register is expecting the result. If the register allocator decides to
merge the virtual register with the result registers than no further
move is needed.
%2 = tail call fastcc { { i8*, i8* }*, i8* } @init({ { i8*, i8*}*,
i8*} %0, i32 %1)

Note that if you have a series of sequential recursive tail calls this
move will only performed once (at the bottom of the recursion,
respectively when the recursion returns) so it's impact on performance
should be minimal.

regards
arnold