[PATCH] Teach DeadArgElimination not to eliminate return valuesof functions with 'returned' arguments

Nuno Lopes nunoplopes at sapo.pt
Mon Jun 24 14:43:43 PDT 2013


> On Sun, Jun 23, 2013 at 10:57 AM, Stephen Lin 
> <swlin at post.harvard.edu>wrote:
>
>> > This does conflict with the theoretical separation of concerns between
>> > optimizer and codegen in LLVM though. This patch does not promote
>> subsequent
>> > mid-level optimization opportunities; treating values as live when they
>> are
>> > actually unused may actually obscure other mid-level optimization
>> > opportunities.
>> >
>> > Dan
>> >
>>
>> I understand, and I'm not thrilled about it either, but is there an
>> alternative course of action you can think of? The problem is that the
>> return value provides potentially valuable information, and there's no
>> good way (as far as I can tell) to get it back at the CodeGen level if
>> it's dropped from the IR because it would require interprocedural
>> coordination of code generation.
>>
>
> No, I don't have any alternatives, other than interprocedural coordination
> of code generation. Do you have any alternatives?
>
>
>> Also, in theory, some mid level optimization could be done, even if it
>> is not done now. A 'returned' argument implies the argument and return
>> value are aliases of each other in all code dominated by the function
>> call, so IR optimizers would be free to replace one with the other. As
>> mentioned in other e-mails, it is, the problem is that, in the general
>> case, it is difficult to know which alternative to pick; however, an
>> IR pass could, at a minimum, canonicalize this:
>>
>>   %struct.A = type { i32 }
>>
>>   declare %struct.A* @a_ctor(%struct.A* returned)
>>   declare void @bar(%struct.A*)
>>
>>   define %struct.A* @foo() {
>>   entry:
>>     %a = alloca %struct.A, align 4
>>     %b = call %struct.A* @a_ctor(%struct.A* %a)
>>     call void @bar(%struct.A* %a)
>>     ret %struct.A* %b
>>   }
>>
>
> The canonical form would be:
>
> %struct.A = type { i32 }
>
>  declare %struct.A* @a_ctor(%struct.A* returned)
>  declare void @bar(%struct.A*)
>
>  define %struct.A* @foo() {
>  entry:
>    %a = alloca %struct.A, align 4
>    %b = call %struct.A* @a_ctor(%struct.A* %a)
>    call void @bar(%struct.A* %a)
>    ret %struct.A* %a
>  }
>
> In other words, it's advantageous to see the actual value, and there's no
> mid-level optimizer benefit to seeing the return value.

The problem is this canonical form inhibits tail calls, which is an 
important optimization.  We could have a smarter tail call pass to recover 
the information later on, though.
(I must confess I only skimmed through this thread, so sorry if this comment 
has been made before.  Just wanted to make sure you remembered of this 
detail).

Nuno 




More information about the llvm-commits mailing list