<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"><<a href="mailto:llvmdev@meinersbur.de" target="_blank">llvmdev@meinersbur.de</a>></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 <<a href="mailto:thanm@google.com">thanm@google.com</a>>:<br>
> Hi all,<br>
><br>
> Just to clarify: the code I'm seeing in the stack coloring dumps is a little<br>
> different from what is being discussed in previous spots in this thread. The<br>
> example that Michael cited earlier on was<br>
><br>
> if (c) {<br>
> llvm.lifetime.start(&var)<br>
> }<br>
> [...]<br>
> llvm.lifetime.end(&var)<br>
><br>
> however what I'm seeing is:<br>
><br>
> entry block:<br>
> [...]<br>
> if (c) { // conditional branch terminating entry block<br>
> llvm.lifetime.start(&var)<br>
> [...]<br>
> exit(..); // this is a no-return-call<br>
> }<br>
> [...]<br>
> llvm.lifetime.end(&var)<br>
><br>
> In the first example there is a path from the lifetime start op to uses of<br>
> the variable. In the second example (which is what I see when I look at the<br>
> stack coloring dumps) there is no such path.<br>
><br>
> Looking at the code in clang (e.g. CodeGenFunction::<wbr>EmitAutoVarAlloca) it is<br>
> pretty clear to me that when the lifetime marker is first manufactured, it<br>
> is placed into the entry block. I don't know enough about how Polly operates<br>
> to understand why it is migrating the lifetime in question down into the<br>
> block containing the exit... but it seems to me that this is really the crux<br>
> 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(&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 "true")<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(&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'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'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>-></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>-> </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'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't do this because lifetime.start is side-effecting so they won'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>