<div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> > You don't have x1 and x2 in your example, assuming you mean:<br>
> ><br>
> > int i = 0;<br>
> > T A;<br>
> > T * y2 = ...<br>
> > {<br>
> > T * x1 = &A;<br>
> > a = x1[i];<br>
> > }<br>
> > {<br>
> > T * restrict x2 = y2;<br>
> > b = x2[i];<br>
> > }<br>
> ><br>
> > It should, no? by virtue of x2 being restrict you know that *x2<br>
> > doesn't alias A, and *x1 is A.<br>
><br>
> No, it doesn't. The fact that x2 is restrict does not mean that it<br>
> does not alias with any other potential accesses from variables live<br>
> in its block. It only means it does not alias with other accesses<br>
> with that occur in the block where x2 is live. There is no access to<br>
> A or x1 in that block, so we can say nothing about it.<br>
><br>
><br>
><br>
> It does. You can assume x2 is not aliased to A and still get<br>
> well-defined semantics, precisely because A is not referenced in the<br>
> scope of x2. That refinement would only get you into trouble if A is<br>
> referenced in the scope of x2, which would trigger UB.<br>
<br>
I don't understand exactly what you're saying here. You can do that at the source level where you still have the original blocks. The problem is that, at the IR level, these blocks don't remain separate basic blocks, and the distinction then matters.</blockquote><div><br></div><div>Agreed. My point is that if you preserve<font face="arial, helvetica, sans-serif"> the <div class="gmail_default" style="display:inline">​block boundaries​</div> yo</font>u <div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​</div><div class="gmail_default" style="display:inline"><font face="arial, helvetica, sans-serif">can use</font></div><font face="arial, helvetica, sans-serif"> <div class="gmail_default" style="display:inline">​better</div> </font>a<div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​​</div>liasing for the restricted pointers. You are already preserving the blo<font face="arial, helvetica, sans-serif">ck entry <div class="gmail_default" style="display:inline">​by introducing the </div></font>intrinsic<div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​;</div> the block exits could be similarly preserved.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
> Going further, logically the intrinsic should return a pointer to a<br>
> new object, disjoint from all other live objects. It is not aliased<br>
> to A, and is well defined even if it contains &A because A is not<br>
> referenced in the scope.<br>
<br>
This is essentially what is done, but only for accesses in the scope (or some sub-scope). I don't think the semantics allow for what you're suggesting. The specific language from 6.7.3.1p4 says:<br>
<br>
[from C]<br>
During each execution of B, let L be any lvalue that has &L based on P. If L is used to<br>
 access the value of the object X that it designates, ...,<br>
 then the following requirements apply: ... Every other lvalue<br>
 used to access the value of X shall also have its address based on P.<br>
[end from C]<br>
<br>
Where B is defined in 6.7.3.1p2 to be, essentially, the block in which the relevant declaration appears. And we can really only extrapolate from that to the other access in that block, and not to the containing block.<br></blockquote><div> </div><div><font face="arial, helvetica, sans-serif">Inside that block<div class="gmail_default" style="display:inline">​ (the lifetime of P)</div>, it is safe to assume that X is <div class="gmail_default" style="display:inline">​disjoint from an</div> arbitrary live object<div class="gmail_default" style="display:inline">​</div> A. It if was<div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​</div><div class="gmail_default" style="display:inline">n't</div><div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​</div>, either:</font></div><div>- A is independently referenced inside the block, so there is UB and all bets are off.</div><div>- A is not independently referenced inside the blo<font face="arial, helvetica, sans-serif">ck, <div class="gmail_default" style="display:inline">​so</div> t</font>here are no pairs of accesses to incorrectly reorder as all accesses to A in<div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​</div> the block are done through P. You just need to delimit the block with dataflow barriers<div class="gmail_default" style="font-family:verdana,sans-serif;display:inline">​,​</div> summar<font face="arial, helvetica, sans-serif">iz<div class="gmail_default" style="display:inline">​ing</div> the effect of the block at entry/exit.</font><br></div><div><br></div><div>This is similar to the way dummy args are implemented on Fortran compilers, extended to arbitrary scopes.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
This does require dataflow barriers on<br>
> entrance/exits to the scope, but those can be made no worse than the<br>
> original code.<br>
<br>
These don't turn into general scheduling barriers anyway. They'll be tagged as writing to memory, yes, but like with @llvm.assume, they'll get special treatment in BasicAA and a few other places so they don't hurt code motion too badly.<br>
<br>
><br>
><br>
><br>
> Aliasing x2 to A is not only unnecessary, but also pessimistic<br>
<br>
It is pessimistic, but only in the sense that the restrict qualifier does not say anything about it.<br>
<br>
> because in general you do not have access to the dynamic scope of<br>
> the restricted pointer.<br>
><br>
><br>
><br>
><br>
> T A, B;<br>
> T * x1 = .... // either &A or &B<br>
> T * y2 =​ .... // ​​maybe &A<br>
> {<br>
> T * restrict x2 = y2;<br>
> *​x1 = ...<br>
> *​x2 = ...<br>
> }<br>
><br>
> ><br>
> > In this case you'll be able to tell *x1 doesn't alias​ *x2, right?<br>
><br>
> In this case, yes, we can conclude that x1 and x2 don't alias<br>
> (because *x1 and *x2 cannot both legally refer to the same object).<br>
><br>
> > How about if you add restrict to x1?<br>
><br>
> The conclusion is the same, but if you add restrict to x1, you don't<br>
> need it on x2. x2 is definitely not based on x1, so if x1 is<br>
> restrict, then we know that x1 and x2 don't alias.<br>
><br>
> Agreed. So will your approach be able to catch both cases? It seemed<br>
> to me it wouldn't be able to catch the second one because it would<br>
> have a different scope, but probably I'm missing something.<br>
<br>
Yes, it will catch it. Just as in the current metadata design, the scope of each access is really a list of scopes. The accesses in the inner blocks get tagged with both the inner and the outer scopes, so they pick up the restrict from the outer scope.<br>
<br>
><br>
><br>
> Thanks for your patience,<br>
><br>
<br>
Not a problem; I appreciate the feedback!<br>
<br>
 -Hal<br>
<br>
><br>
><br>
> ><br>
><br>
> --<br>
> Hal Finkel<br>
> Assistant Computational Scientist<br>
> Leadership Computing Facility<br>
> Argonne National Laboratory<br>
><br>
<br>
--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br>
</blockquote></div></div>