<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-04-06 23:47 GMT+02:00 Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Piotr,<br>
<br>
On April 6, 2017 at 9:28:58 AM, Piotr Padlewski<br>
<span class="">(<a href="mailto:piotr.padlewski@gmail.com">piotr.padlewski@gmail.com</a>) wrote:<br>
> Hi Sanjoy,<br>
> My point is that this it is exactly the same way as normal !dereferenceable<br>
> introduces UB.<br>
><br>
> ptr = load i8*, i8** %ptrptr, !dereferenceable !{i64 8}<br>
> if (false) {<br>
> int val = *ptr;<br>
> }<br>
<br>
</span>These are two different things.<br>
<br>
In the above example, your original program executes a load that was<br>
supposed to produce a dereferenceable value, but it did not.  This<br>
means the original program is undefined, so we can optimize it to do<br>
whatever we want.<br>
<br>
OTOH, look at this program:<br>
<br>
void main() {<br>
  if (false) {<br>
    // ptrptr does not contain a dereferenceable pointer, but is<br>
itself dereferenceable<br>
    ptr = load i8*, i8** %ptrptr, !dereferenceable !{i64 8}, !global<br>
    int val = *ptr;<br>
  }<br>
}<br>
<br>
What is the behavior of the above program?  It better be well defined,<br>
since it does nothing!<br>
<br>
However, if we follow your rules, we can first xform it to<br>
<br>
void main() {<br>
  ptr = load i8*, i8** %ptrptr, !dereferenceable !{i64 8}, !global<br>
<span class="">  if (false) {<br>
    int val = *ptr;<br>
  }<br>
}<br>
<br>
</span>and then to<br>
<br>
void main() {<br>
  ptr = load i8*, i8** %ptrptr, !dereferenceable !{i64 8}, !global<br>
<span class="">  int val = *ptr;<br>
  if (false) {<br>
  }<br>
}<br>
<br>
</span>which introduces UB into a program that was well defined to begin<br>
with.<br>
<span class=""><br>
> If frontend says that something is dereferenceable, which is not actually<br>
> dereferenceable, then it is UB and everything can happen - like the<br>
> execution of dead instruction.<br>
> This is exactly the same with the global properties - we are giving a<br>
> guarantee that pointer it is dereferenceable even if we would hoist or sink<br>
> it, and if it is not true then it is UB.<br>
<br>
</span>But then you're saying dead code (code that would not actually execute<br>
in the original program) can affect program behavior, and: "if (false)<br>
X;" is not a no-op for some values of X.  It is in this respect that<br>
your proposal is similar to the speculatable proposal.<br>
<span class="HOEnZb"><font color="#888888"><br></font></span></blockquote><div>Hi Sanjoy, </div><div>But we already have that behavior with dereferenceable variables.</div><div><br></div><div>void foo(i8* dereferenceable(8) %ptr) {</div><div>  if (false) {</div><div>    ; what if %x is not actually dereferenceable?</div><div>    %x = load i8, i8* %ptr</div><div>  }</div><div>}</div><div>Now we can hoist the load, even that it would be never executed. </div><div>This is the same with global properties - it gives us guarantee that property holds non locally and if it doesn't then it is UB </div><div>and things like this might happen.</div><div><br></div><div>I understand your concerns about the speculate function attribute, the examples that you showed in the review are pretty disturbing,</div><div>but loads and stores seems to be much safere in that maner. Maybe you know some examples like this, but with load and stores?</div><div>It just seems weird to me that we already depend on very similar mechanics, but this one seems like a bad idea.</div><div><br></div><div>Best</div><div>Piotr </div><div><br></div><div> </div></div><br></div></div>