<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 8, 2016 at 1:51 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Hi Daniel,<br>
<br>
Daniel Berlin wrote:<br></span><span class="">
> Well, no.<br>
> If invariant end was readonly, it would value forward past invariant<br>
> ends, and extend the range in the case it was like this:<br>
><br>
> %a =invariant.start<br>
> ...<br>
> invariant.end(%a)<br>
><br>
> <non-memory affecting instructions><br>
><br>
> %b=invariant.start<br>
> ...<br>
> invariant.end(%b)<br>
><br>
> As long as there are no memory writing instructions in the middle,<br>
> things will believe the two invariant starts produce the same value, and<br>
> forward it :)<br>
<br></span>
I have to think about it a bit more before I can commit to this, but<br>
at least intuitively the above seems fine -- if there are no memory<br>
clobbering instructions between the two ranges then they should be<br>
merged.</blockquote><div><br></div><div><br></div><div>FWIW: I've pretty much not thought about it at all.</div><div>The main use case, as far as i remember, was to support specifying invariantness that otherwise could not be inferred through analysis.</div><div>I believe the only use case in my part of the world (C++) is const objects of various sorts, or write-once objects.</div><div><br>Neither would be broken by this kind of merging.</div><div><br></div><div>If we do think the above kind of merging is okay, we should mark invariant.end readonly as well and teach a small set of things not to hoist them/eat them, so that we gain the benefits of them not blocking optimization either (for example, any readnone/readonly function that uses invariants is still going to be marked readwrite due to the invariant.end)</div><div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">  This can even be a valuable optimization in cases where the<br>
"<non-memory affecting instruction>" bits were hidden behind a call<br>
that was later inlined.<br>
<br>
The way I see it is that invariant_start and invariant_end denote the<br>
boundaries of a region that can be assumed to not have stores to a<br>
specific location[1].  To preserve this property we only need to avoid<br>
stores floating into the region, and for that readonly semantics is<br>
sufficient for non-atomic accesses (and potentially some kinds of<br>
atomic accesses too).  Readonly semantics may even be stronger than we<br>
need, since I think we can allow stores floating *out* of the region.<br></blockquote><div><br></div><div>Yes, that sounds right. <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I'm not yet fully confident that the above semantics will hold under<br>
pressure, since it fails the test of "can I write an implementation of<br>
invariant_start and invariant_end that will give me the guarantees I<br>
need?".  The best I can do with invariant_start and invariant_end as<br>
specified is:<br>
<br>
  void* invariant_start(iN* ptr) {<br>
    cell = malloc(sizeof(iN));<br>
    *(iN*)cell = ptr;<br>
    return cell;<br>
  }<br>
<br>
  void invariant_end(void* cell, iN* ptr) {<br>
    assert(*(iN*)cell == *ptr);<br>
  }<br>
<br>
<br>
which still allows the transform:<br>
<br>
x = invariant_start(ptr)<br>
int val = *ptr;<br>
print(val);<br>
invariant_end(x, ptr)<br>
<br>
==><br>
<br>
x = invariant_start(ptr)<br>
int val_backup = *ptr;<br>
*ptr = 400;<br>
*ptr = val_backup;<br>
int val = *ptr;<br>
print(val);<br>
invariant_end(x, ptr)<br>
<br>
<br>
That's not a clear problem (after all, intrinsics are allowed to have<br>
special semantics that may not be "implementable" in IR), but it is a<br>
"slightly red" flag.<br></blockquote><div><br></div><div><br>yeah. I guess it would be interesting to know what real world uses for this currently exist.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
[1]: An alternate framing would be: no stores to that specific<br>
  location change the contained value.<span class="HOEnZb"><font color="#888888"><br>
<br>
-- Sanjoy</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
><br>
> GVN is not quite smart enough yet, but it's about to be.<br>
><br>
> GCC even has testcases that we both eliminate and PRE pure/const<br>
> (readonly/readnone) calls.<br>
</div></div></blockquote></div><br></div></div>