[llvm-commits] [PATCH] Remove tail marker when changing an argument to an alloca.

Rafael EspĂ­ndola rafael.espindola at gmail.com
Fri Jan 10 19:03:49 PST 2014


Ping. I found this in a corner of my local git repo. A rebased patch
is attached.


> I guess I started going a bit off topic. The test I posted is not
> recursive as written, but can be optimized to one, but that is not the
> big issue. The issue are the cases where we don't have the full body
> to analyze and we are left with what guarantees the IL gives us.
>
> I think that an important case is:
>
> declare void @f(i32*)
> define void @g(i32* byval %a) {
>   tail call void @f(i32* %a)
>   ret void
> }
>
> Given the current rules, the above code is valid and, on x86-64 with
> the default calling convention, llc can produce:
>
>         leaq    8(%rsp), %rdi
>         jmp     f
>
> Note that this is valid even if f can write to its argument. This is
> so because g knows that it has its own copy of %a.
>
> In a different ABI, this might not be possible. If for example g is
> the one responsible for poping the storage used for %a, then it has to
> do a regular call to f. On on the normal x86 abi, g has to align the
> stack, and llc produces
>
>         subl    $12, %esp
>         leal    16(%esp), %eax
>         movl    %eax, (%esp)
>         calll   f
>         addl    $12, %esp
>         ret
>
>
> Also note that without knowing that f will not write to its argument,
> we cannot optimize g to
>
> define void @g(i32* %a) {
>   tail call void @f(i32* %a)
>   ret void
> }
> declare void @f(i32*)
>
> even if the ABI for g in both cases would match. In the new code g
> doesn't have its own copy of %a.
>
> Since the byval %a is allocated (and freed) in g's caller in most
> ABIs, I think this is a good argument for why we should not count
> byval as an alloca for the purposes of allowing the tail marker or
> not.
>
> In a way, what is happening in this optimization is that the function
> being tail called goes (in most ABIs) from accessing an alloca in the
> caller's caller to accessing an alloca in the caller, and therefore we
> have to remove the tail marker.
>
> While I acknowledge that this maintenance is an annoyance, it is not
> specific to this pass or even to byval. Consider a slightly modified
> example:
>
> declare  void @f(i32*)
> define void @g(i32* %a) {
>   tail call void @f(i32* %a)
>   ret void
> }
> define void @h(i32 %x) {
>   %b = alloca i32
>   store i32 %x, i32* %b
>   call void @g(i32* %b)
>   ret void
> }
>
> There is no byval in it and the tail marker is correct since f gets an
> alloca in h, not in g. When inlining, the inliner correctly drops it
> and h becomes:
>
> define void @h(i32 %x) {
>   %b = alloca i32
>   store i32 %x, i32* %b
>   call void @f(i32* %b)
>   ret void
> }
>
> In general, any pass that changes the arguments to a function has to
> be careful. If it now passes an local alloca as an argument, it has to
> drop the tail marker.
>
>> Ciao, Duncan.
>>
>
> Cheers,
> Rafael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: t.patch
Type: text/x-patch
Size: 1507 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140110/5fb15a0f/attachment.bin>


More information about the llvm-commits mailing list