<div dir="ltr">Would it make sense to count the return value as an escape point?  ie it seems (and hopefully is programmed to be) incorrect to infer a readnone attribute for a pointer that gets passed to a non-readnone function, or stored to a global variable, etc.  In that sense the pointer seems to also escape if returned from the function, because the function can't guarantee any longer that no reads or writes happen to that value.  So my take would have been that get_pntr() shouldn't get annotated with readnone...</div>

<div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, May 23, 2014 at 11:56 AM, Nick Lewycky <span dir="ltr"><<a href="mailto:nlewycky@google.com" target="_blank">nlewycky@google.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="">On 23 May 2014 09:42, Robert Lougher <span dir="ltr"><<a href="mailto:rob.lougher@gmail.com" target="_blank">rob.lougher@gmail.com</a>></span> wrote:<br>



<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Nick,<br>
<br>
Thanks for replying.  Bug filed: <a href="http://llvm.org/bugs/show_bug.cgi?id=19842" target="_blank">http://llvm.org/bugs/show_bug.cgi?id=19842</a></blockquote><div><br></div></div><div>Thank you!</div><div class=""><div>

<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">


Strangely enough, my first conclusion was that %p was being marked<br>
readnone incorrectly as it wasn't handling the copy via @get_addr.<br></blockquote><div><br></div></div><div>Sorry -- saying %p alone is ambiguous because there's the %p parameter of @<span style="font-family:arial,sans-serif;font-size:13px">get_pntr and the %p parameter of @store. It is correct to mark %p readnone in @get_pntr. From function entrance to exit, it does not write to the pointer passed in. It is incorrect to mark %p readnone in @store, as it receives a pointer then writes to it. Supposing the @get_pntr loaded a pointer from some global variable then wrote through it, then @get_pntr could still mark its %p as being readnone, since the write was not through %p particularly, it just happens to be through a pointer that aliased it.</span></div>

<div class="">

<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">




Somebody (not here) then pointed out the readnone definition in the<br>
LangRef (specifically the "even though it may read or write<br>
<div>the memory that the pointer points to if accessed through other<br>
</div>pointers").  I decided the copy fell within this definition and<br>
changed my mind and decided GVN was at fault.  How should the<br>
definition be interpreted?<br></blockquote><div><br></div></div><div>Consider:</div><div><br></div><div>define void @example(i32* %p, i32* %q) {</div><div>  store i32 10, i32* %q</div><div>  %A = icmp ult i32* %p, %q</div>

<div>

  call void @use(i1 %A) readnone</div><div>  ret void</div><div>}</div><div><br></div><div>@example does not modify the memory pointed to by %p, unless it does it through a different pointer, hence it may mark that parameter readnone. A caller may choose to pass in %p == %q in which case the memory pointed-to may change, but @example still lives up to its contract.</div>



<div><br></div><div>The real-world implications of this are that callers may use this information to optimize themselves, combined with other information such as knowing that %p != %q, or better, that %p is a local alloca or freshly malloc'd memory and the pointer %p has not yet escaped (aka. been captured).</div>



<div><br></div><div>If we read the language as permitting the function to make copies of the pointers the this code would be valid:</div><div><br></div><div>define void @writes_over_everything(i32* readnone %p, i32* readnone %q) {</div>



<div>  %P = bitcast i32* %p to i32*</div><div>  %Q = bitcast i32* %p to i32*</div><div>  store i32 10, i32* %P</div><div><div>  store i32 10, i32* %Q</div></div><div>  ret void</div><div>}</div><div><br></div><div>and that's not useful for optimization.</div>

<span class="HOEnZb"><font color="#888888">

<div><br></div><div>Nick</div></font></span><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div><div>


On 23 May 2014 04:22, Nick Lewycky <<a href="mailto:nlewycky@google.com" target="_blank">nlewycky@google.com</a>> wrote:<br>
> Confirmed, this is a bug. This<br>
><br>
> define i32* @get_pntr(i32* %p) nounwind uwtable {<br>
> entry:<br>
>   ret i32* %p<br>
> }<br>
> define void @store(i32* %p) noinline nounwind uwtable {<br>
> entry:<br>
>   %call = call i32* @get_pntr(i32* %p)<br>
>   store i32 10, i32* %call, align 4<br>
>   ret void<br>
> }<br>
><br>
> run through opt -functionattrs gets a 'readnone' on @store's %p. That's<br>
> wrong, it clearly stores to it. The bug is due to incorrectly handling the<br>
> copy of the pointer made by @get_pntr, because @get_pntr itself is marked<br>
> 'readnone'.<br>
><br>
> Please file a bug.<br>
><br>
> Nick<br>
><br>
><br>
><br>
> On 22 May 2014 08:15, Robert Lougher <<a href="mailto:rob.lougher@gmail.com" target="_blank">rob.lougher@gmail.com</a>> wrote:<br>
>><br>
>> Hi Philip,<br>
>><br>
>> Thanks for the reply.<br>
>><br>
>> On 22 May 2014 01:31, Philip Reames <<a href="mailto:listmail@philipreames.com" target="_blank">listmail@philipreames.com</a>> wrote:<br>
>> ><br>
>> > On 05/21/2014 02:52 PM, Robert Lougher wrote:<br>
>> >><br>
>> >> On 21 May 2014 21:40, Robert Lougher <<a href="mailto:rob.lougher@gmail.com" target="_blank">rob.lougher@gmail.com</a>> wrote:<br>
>> >>><br>
>> >>> define i32* @get_pntr(i32* readnone %p) {<br>
>> >>> entry:<br>
>> >>>    ret i32* %p<br>
>> >>> }<br>
>> >>><br>
>> >>> define void @store(i32* nocapture readnone %p) {<br>
>> >>> entry:<br>
>> >>>    store i32 10, i32* %p, align 4, !tbaa !1<br>
>> >>>    ret void<br>
>> >>> }<br>
>> >>><br>
>> >> Further to my first post, based on the definition of readnone on an<br>
>> >> argument, this is also incorrect.  After get_pntr() has been inlined<br>
>> >> into store(), we are dereferencing %p, but it is still marked<br>
>> >> readnone.<br>
>> >><br>
>> >> So we seem to have a couple of issues.  First GVN seems to be making<br>
>> >> incorrect assumptions based on argument attributes, and secondly<br>
>> >> inlining can invalidate existing attributes?<br>
>> ><br>
>> > I'm not clear on the GVN issue, but looking at your example IR, the<br>
>> > readnone<br>
>> > attribute is definitely incorrect after inlining.<br>
>> ><br>
>><br>
>> Yes.  I haven't investigated it any further, but the parameter was<br>
>> already readnone before inlining, so it looks like the attributes<br>
>> aren't revisited afterwards.  But that is just a guess.<br>
>><br>
>> > A question worth asking here: does this definition of readnone make<br>
>> > sense?<br>
>> > I can see where it came from, but it seems to give very unintuitive<br>
>> > reasoning here.<br>
>> ><br>
>><br>
>> Exactly.  That was my point in asking here before I went any further.<br>
>> The definition in the LangRef seems odd.  If it could still be<br>
>> accessed by another pointer, I can't see where the information is<br>
>> useful.<br>
>><br>
>> > p.s. Is this with TOT or an earlier version?<br>
>><br>
>> Yes, this was with TOT as of yesterday (r209294).<br>
>><br>
>> Thanks,<br>
>> Rob.<br>
>><br>
>> ><br>
>> > Philip<br>
>> ><br>
>> > _______________________________________________<br>
>> > LLVM Developers mailing list<br>
>> > <a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
>> > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
>> _______________________________________________<br>
>> LLVM Developers mailing list<br>
>> <a href="mailto:LLVMdev@cs.uiuc.edu" target="_blank">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
><br>
</div></div></blockquote></div></div></div></div></div>
<br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div>