[prev in list] [next in list] [prev in thread] [next in thread] 

List:       llvm-dev
Subject:    Re: [llvm-dev] Well-formed @llvm.lifetime.start and @llvm.lifetime.end intrinsics
From:       Daniel Berlin via llvm-dev <llvm-dev () lists ! llvm ! org>
Date:       2017-03-31 17:32:34
Message-ID: CAF4BwTVUr6f5rLPuLKxBjr7ubfqwDtYjTOsf2yk4aVLhr+fKMg () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


On Fri, Mar 31, 2017 at 6:22 AM, Michael Kruse <llvmdev@meinersbur.de>
wrote:

> 2017-03-31 15:00 GMT+02:00 Than McIntosh <thanm@google.com>:
> > Hi all,
> >
> > Just to clarify: the code I'm seeing in the stack coloring dumps is a
> little
> > different from what is being discussed in previous spots in this thread.
> The
> > example that Michael cited earlier on was
> >
> >     if (c) {
> >       llvm.lifetime.start(&var)
> >     }
> >     [...]
> >     llvm.lifetime.end(&var)
> >
> > however what I'm seeing is:
> >
> >     entry block:
> >     [...]
> >     if (c) {           // conditional branch terminating entry block
> >       llvm.lifetime.start(&var)
> >       [...]
> >       exit(..);        // this is a no-return-call
> >     }
> >     [...]
> >     llvm.lifetime.end(&var)
> >
> > In the first example there is a path from the lifetime start op to uses
> of
> > the variable. In the second example (which is what I see when I look at
> the
> > stack coloring dumps) there is no such path.
> >
> > Looking at the code in clang (e.g. CodeGenFunction::EmitAutoVarAlloca)
> it is
> > pretty clear to me that when the lifetime marker is first manufactured,
> it
> > is placed into the entry block. I don't know enough about how Polly
> operates
> > to understand why it is migrating the lifetime in question down into the
> > block containing the exit... but it seems to me that this is really the
> crux
> > of the problem.
>
> Thank you for the clarification. I indeed did not consider that the
> exit/unreachable makes a difference.
>
> This is what happens in Polly:
>
>   llvm.lifetime.start(&var)
>   if (c) {
>     call void @_z10exit_usagepkc
>     unreachable // because exit_usage is no-return
>   }
>
> - Optimistically assume that no functions are executed or control flow
> ends in an unreachable. It can determine the condition c1 for when no
> such thing ever appears (in which case c1 is just "true")
> - Version the old code and the new code:
>
> if (c1) {
>   // optimized code without lifetime markers
>   ...
> } else {
>  // Orginal code, not modified by Polly
>   llvm.lifetime.start(&var);
>   if (c) {
>     call void @_z10exit_usagepkc
>     unreachable // because exit_usage is no-return
>   }
> }
>
>

> In this case c happens to be equal to c1, in which case I guess some
> pass removes the inner inner conditional because it is always true.
>
> How do you think code versioning in general should handle this?


Assuming you don't want to drop them:

If you are only duplicating code structurally, and not moving it past any
statements, and assuming we fix the semantics:
When you start, the lifetime starts for a pointer should jointly (IE
considered as a set) dominate the lifetime ends.
The lifetime ends for a pointer should jointly post-dominate each lifetime
start.

Thus, when duplicating, you would copy into program points to make that
true. That is if you want to try to remain optimal.
Trivially, you can always just hoist lifetime.start and sink lifetime.end
until the above is true again.
Note;
You may not move a lifetime.start past a memory using statement unless you
can prove the memory using statement is noalias the lifetime'd pointer.

otherwise, trivially:

int *a;
int *b;
intptr_t c;

lifetime.start(a)
c = inttoptr (a)
b = ptrtoint(c)
load b

->
c = inttoptr (a)
b = ptrtoint(c)
load b
lifetime.start(a)

->
GVN or something smart will prove a == b, and replace them.

load a
lifetime.start(a)

whoops






I
> looked into LoopVersioning.cpp (used by LLVM's vectorizer), but could
> not see how it handles this situation. Maybe it is not affected
> because lifetime markers usually do not cross loop bounds.
>
Yes, the other things won't do this because lifetime.start is
side-effecting so they won't move it.

Note: MemorySSA also ignores the side-effects of lifetime.start, but we
expect clients to handle it.

[Attachment #5 (text/html)]

<div dir="ltr"><div><br></div><div class="gmail_extra"><br><div \
class="gmail_quote">On Fri, Mar 31, 2017 at 6:22 AM, Michael Kruse <span \
dir="ltr">&lt;<a href="mailto:llvmdev@meinersbur.de" \
target="_blank">llvmdev@meinersbur.de</a>&gt;</span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div \
class="gmail-h5">2017-03-31 15:00 GMT+02:00 Than McIntosh &lt;<a \
href="mailto:thanm@google.com">thanm@google.com</a>&gt;:<br> &gt; Hi all,<br>
&gt;<br>
&gt; Just to clarify: the code I&#39;m seeing in the stack coloring dumps is a \
little<br> &gt; different from what is being discussed in previous spots in this \
thread. The<br> &gt; example that Michael cited earlier on was<br>
&gt;<br>
&gt;        if (c) {<br>
&gt;           llvm.lifetime.start(&amp;var)<br>
&gt;        }<br>
&gt;        [...]<br>
&gt;        llvm.lifetime.end(&amp;var)<br>
&gt;<br>
&gt; however what I&#39;m seeing is:<br>
&gt;<br>
&gt;        entry block:<br>
&gt;        [...]<br>
&gt;        if (c) {                 // conditional branch terminating entry \
block<br> &gt;           llvm.lifetime.start(&amp;var)<br>
&gt;           [...]<br>
&gt;           exit(..);            // this is a no-return-call<br>
&gt;        }<br>
&gt;        [...]<br>
&gt;        llvm.lifetime.end(&amp;var)<br>
&gt;<br>
&gt; In the first example there is a path from the lifetime start op to uses of<br>
&gt; the variable. In the second example (which is what I see when I look at the<br>
&gt; stack coloring dumps) there is no such path.<br>
&gt;<br>
&gt; Looking at the code in clang (e.g. CodeGenFunction::<wbr>EmitAutoVarAlloca) it \
is<br> &gt; pretty clear to me that when the lifetime marker is first manufactured, \
it<br> &gt; is placed into the entry block. I don&#39;t know enough about how Polly \
operates<br> &gt; to understand why it is migrating the lifetime in question down \
into the<br> &gt; block containing the exit... but it seems to me that this is really \
the crux<br> &gt; of the problem.<br>
<br>
</div></div>Thank you for the clarification. I indeed did not consider that the<br>
exit/unreachable makes a difference.<br>
<br>
This is what happens in Polly:<br>
<br>
   llvm.lifetime.start(&amp;var)<br>
   if (c) {<br>
      call void @_z10exit_usagepkc<br>
      unreachable // because exit_usage is no-return<br>
   }<br>
<br>
- Optimistically assume that no functions are executed or control flow<br>
ends in an unreachable. It can determine the condition c1 for when no<br>
such thing ever appears (in which case c1 is just &quot;true&quot;)<br>
- Version the old code and the new code:<br>
<br>
if (c1) {<br>
   // optimized code without lifetime markers<br>
   ...<br>
} else {<br>
  // Orginal code, not modified by Polly<br>
   llvm.lifetime.start(&amp;var);<br>
   if (c) {<br>
      call void @_z10exit_usagepkc<br>
      unreachable // because exit_usage is no-return<br>
   }<br>
}<br>
<br></blockquote><div>  <br></div><blockquote class="gmail_quote" style="margin:0px \
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> In this case \
c happens to be equal to c1, in which case I guess some<br> pass removes the inner \
inner conditional because it is always true.<br> <br>
How do you think code versioning in general should handle \
this?</blockquote><div><br></div><div>Assuming you don&#39;t want to drop \
them:</div><div><br></div><div>If you are only duplicating code structurally, and not \
moving it past any statements, and assuming we fix the semantics:</div><div>When you \
start, the lifetime starts for a pointer should jointly (IE considered as a set) \
dominate the lifetime ends.</div><div>The lifetime ends for a pointer should jointly \
post-dominate each lifetime start.</div><div><br></div><div>Thus, when duplicating, \
you would copy into program points to make that true. That is if you want to try to \
remain optimal.</div><div>Trivially, you can always just hoist lifetime.start and \
sink lifetime.end until the above is true again.</div><div>Note;<br>You may not move \
a lifetime.start past a memory using statement unless you can prove the memory using \
statement is noalias the lifetime&#39;d pointer.</div><div><br></div><div>otherwise, \
trivially:</div><div><br></div><div>int *a;</div><div>int *b;</div><div>intptr_t \
c;</div><div><br></div><div>lifetime.start(a)<br></div><div>c = inttoptr \
(a)</div><div>b = ptrtoint(c)<br></div><div>load \
b<br></div><div><br></div><div>-&gt;</div><div><div>c = inttoptr (a)<br></div><div>b \
= ptrtoint(c)<br></div><div>load \
b<br></div></div><div><div>lifetime.start(a)<br></div></div><div><br></div><div>-&gt; \
</div><div>GVN or something smart will prove a == b, and replace \
them.</div><div><div><div><br></div><div>load \
a<br></div></div><div>lifetime.start(a)<br></div></div><div><br></div><div>whoops</div \
><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><blockquote \
> class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid \
> rgb(204,204,204);padding-left:1ex"> I<br>
looked into LoopVersioning.cpp (used by LLVM&#39;s vectorizer), but could<br>
not see how it handles this situation. Maybe it is not affected<br>
because lifetime markers usually do not cross loop bounds.<br></blockquote>Yes, the \
other things won&#39;t do this because lifetime.start is side-effecting so they \
won&#39;t move it.</div><div class="gmail_quote"><br></div><div \
class="gmail_quote">Note: MemorySSA also ignores the side-effects of lifetime.start, \
but we expect clients to handle it.</div><div \
class="gmail_quote"><br><div><br></div></div></div></div>


[Attachment #6 (text/plain)]

_______________________________________________
LLVM Developers mailing list
llvm-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic