[LLVMdev] lifetime.start/end clarification

Philip Reames listmail at philipreames.com
Wed Nov 5 15:56:54 PST 2014


On 11/05/2014 01:48 PM, Reid Kleckner wrote:
> On Wed, Nov 5, 2014 at 11:17 AM, Philip Reames 
> <listmail at philipreames.com <mailto:listmail at philipreames.com>> wrote:
>
>
>     On 11/05/2014 10:54 AM, Reid Kleckner wrote:
>>
>>         This seems fine to me.  The optimizer can (soundly) conclude
>>         that %p is dead after the "lifetime.end" (for the two
>>         instructions), and dead before the "lifetime.start" (for the
>>         *single* instruction in that basic block, *not* for the
>>         previous BB).  This seems like the proper result for this
>>         example, am I missing something?
>>
>>
>>     What if I put that in a loop, unroll it once, and prove that the
>>     lifetime.start is unreachable? We would end up with IR like:
>>
>>     loop:
>>       ... use %p
>>       call void @lifetime.end( %p )
>>       ... use %p
>>       call void @lifetime.end( %p )
>>       br i1 %c, label %loop, label %exit
>>
>>     Are the second uses of %p uses of dead memory?
>     It's hard to discuss this without being specific about the
>     starting IR and transforms.  My general response is that either a)
>     such a transform wouldn't be valid or b) the behaviour of the
>     original program was undefined.
>
>
> The starting IR would be something that jumps into the middle of a 
> lifetime region, like the example that Arnaud gave. This was assuming 
> the current state of the world where we haven't added a second 
> lifetime start call prior to the goto branch.
>
> Start with something like:
>
> void f(int x) {
>   while (x) {
>     goto skip_start;
>     {
>       int y; // lifetime.start
> skip_start:
>       y = g();
>       x -= y;
>       // lifetime.end
>     }
>   }
> }
>
> The block containing the lifetime start of y is unreachable and can be 
> deleted.
If I'm understanding you right, we'd have something like this:

void f(int x) {
   (space for y reserved, no lifetime start)
   while (x) {
     {
       y = g();
       x -= y;
       // lifetime.end
     }
   }
}

I don't see the problem here.

We have a BB (or set of BBs) which contains:
{
       y = g();
       x -= y;
       // lifetime.end(y)
}
with *two* predecessors.  *One* of those predecessors contains the 
lifetime.end, the other does not.  Thus there is a path where the store 
for y is defined.

If I'm interpreting the original code correctly, that's exactly the 
right semantic.  This code is poorly defined if-and-only-if the backedge 
is taken.  To say this differently, the original program had a dynamic 
trace (before optimization) where two "ends" where not separated by a 
"start".  That's a bug in the frontend. To fix it, the frontend needs a 
lifetime.start in the source of the goto.

(We haven't actually settled the semantics of a sequence of 
end,start,end.  My view is there are reasonable semantics - which I'm 
using here - for that sequence and important use cases in loops.  As the 
actual documentation says at this point, the lifetime markers would have 
to be outside the loop.  That's just "obviously" silly though.)

Philip

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141105/aa738e5b/attachment.html>


More information about the llvm-dev mailing list