<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 5, 2016 at 1:11 PM, Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</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"><span class="">Hi Daniel,<br>
<br>
Daniel Berlin wrote:<br></span><span class="">
> Yes, i'm saying the  mechanism currently used to keep them from moving<br>
> is to say they read/write memory.<br>
><br>
>     That<br>
>     does not seem safe -- how does LLVM know that they won't segfault?<br>
><br>
><br>
><br>
> I'm not sure i understand.<br>
<br></span>
I meant given a call that is readonly, LLVM cannot generally hoist it<br>
out of control flow unless it has special knowledge that the call does<br>
not read invalid memory.  </blockquote><div> <br></div><div><br></div><div>Okay, so you are saying you don't believe it will cause the same problem because you don't believe anything will legally try to hoist these.</div><div><br></div><div>I'm willing to find out!</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">Otherwise it will introduce undefined<br>
behavior:</blockquote><div> </div><div>I'm not opposed to trying to mark these as readonly, but realize you are also assuming you know what the real invariant range is and what causes it :)</div><div><br></div><div>Given the following:<br><br></div><div>store(something that LLVM does not think aliases foo)</div><div>bar = invariant.start(foo, 5)</div><div>load foo</div><div>invariant.end(bar)</div><div><br></div><div>Transforming it into:<br><div><br class=""><div>bar = invariant.start(foo, 5)</div>store(something that LLVM does not think aliases foo)</div><div>load foo<br></div><div>invariant.end(bar)</div><div><br></div><div>Is equally as illegal by the langref, since you are now saying "during the operation of this store, the memory for foo is invariant", which is not what it said originally (though i can't think of cases this will break that don't involve threading).</div><div><br></div><div>I also don't honestly know if getModRefInfo is going to say this is legal or not.</div><div><br></div><div>That said, in theory:</div><div><div><br class="">%a = add 5, 3</div><div>bar = invariant.start(foo, 5)<br></div><div>load foo</div><div>invariant.end(bar)</div></div><div><br></div><div>to</div><div><div>bar = invariant.start(foo, 5)<br></div><div>%a = add 5, 3</div><div>load foo<br></div><div>invariant.end(bar)</div></div><div><br></div><div>is probably also illegal, and has the same issues :)</div><div><br></div><div>Now, i have no desire to be that pedantic (i'd rather just update the langref).</div><div><br></div><div><br></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"> </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
  if (always_false)<br>
    readonly_call_that_derefs_null<wbr>()<br>
<br>
==><br>
<br>
  readonly_call_that_derefs_null<wbr>()<br>
  if (always_false)<br>
    ...<span class=""><br>
<br>
> These are invariant start and end markers, they generate no real code.<br>
> If you move them, the problem is that the definition of invariant.start<br>
> says:<br>
> "This intrinsic indicates that until an|llvm.invariant.end|that uses the<br>
> return value, the referenced memory location is constant and unchanging.<br>
> "<br>
><br>
> So if you hoist/sink start or end , you change the bounds of where the<br>
> memory is unchanging.<br>
<br></span>
Yes. I can see why cannot move _stores_ across them, since<br>
<br>
<br>
  *ptr = 20<br>
  invariant_start(ptr)<br>
<br>
==><br>
<br>
  invariant_start(ptr)<br>
  *ptr = 20<br>
<br>
<br>
is bad -- we've moved a store to a region in which ptr needs to be<br>
unchanging.<br>
<br>
<br>
With the memdep changes we will allow reordering loads across the<br>
invarinat_start call:<br>
<br>
  int val = *ptr;<br>
  invariant_start(ptr)<br>
<br>
<==><br>
<br>
  int val = *ptr;<br>
  invariant_start(ptr)<br>
<br></blockquote><div><br></div><div>(you meant for the first one to have the load after invariant start, i presume)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
but that seems fine to me; that is I could not find a reason why<br>
reordering loads across invariant_start will be a problem.  </blockquote><div><br></div><div>Me either :)<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">But I<br>
don't have a deep reason why reordering loads is correct, so I won't<br>
be surprised if there are cases that reordering is a problem.</blockquote><div><br></div><div>I would be surprised if someone does not find a case where it is :) </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="">
<br>
> You could fix this, of course, by having the invariant.start and<br>
> invariant.end calls return pointers, and all things that are invariant<br>
> use those pointers (or pointers derived from those pointers).  IE<br>
> express the dependence in SSA directly.<br>
<br></span>
I remember a thread by Andy Trick a while back which intended to add<br>
this to LLVM.  But that didn't result in concrete patches.<span class=""><br>
<br>
> Then you can move the start/end calls wherever they are valid (IE<br>
> wherever they are dominated by their operands) and it will not change<br>
> the semantic effect.<br>
><br>
> But that's not the current design.<br>
><br>
><br>
>     >  We last tried this by saying they did not touch memory (which is<br>
>     >  correct), and peter had to revert the set of changes that gave<br>
>     them "The<br>
>     >  correct answer" because it broke on real code.<br>
><br>
>     Do you happen to remember any relevant revision numbers / zilla bugs<br>
>     for this?<br>
><br>
> The revert was: "[llvm] r270823 - MemorySSA: Revert r269678 and r268068;<br>
> replace with special casing in MemorySSA.<br>
> "<br>
><br>
> This is when we tried this with assume<br>
<br></span>
Oh, I remember that one.  But IIUC that was not a problem with<br>
speculation but with DCE'ing away assumes.  ReadNone can't be<br>
speculated in LLVM either since they can contain a divide-by-zero.<br>
<br>
I don't think that the same problem will occur here since unlike the<br>
assume patch, we're not telling LLVM that calls to invariant_start are<br>
readonly, but that they don't cause a dependency on any specific load<br>
instruction in the LLVM IR.  This is sort of like saying that the<br>
invariant_start call does write to memory, but just not to memory that<br>
can be observed via LLVM IR.<br></blockquote><div><br></div><div>I'm willing to give it a shot if you want, i'm just in the "we'll probably break something unexpected" camp :)</div><div><br></div><div><br></div></div></div></div>