<div dir="ltr">Thanks, Jeroen, that really helps.<br><br>A follow-up question, if you don't mind. What if we have code somewhat similar to your example in assign3() but it's in C++ and the pointer derived from x is stored in a class member field:<br><br><font size="4"><span style="font-family:monospace">class S {<br>public:<br> S(int *d): data(d) {}<br> int *getData() { return data; }<br>private:<br> int *__restrict__ data;<br>};<br><br>void assign4(int *pA, long N) {<br> int *__restrict__ x = pA;<br> int tmp;<br> {<br> S s(x + N);<br> tmp = *s.getData();<br> }<br> *x = tmp;<br>}</span></font><br><br><div>I see that the full restrict implementation says that the load and the store do not alias. Is this by design?</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 15, 2020 at 9:00 AM Jeroen Dobbelaere <<a href="mailto:Jeroen.Dobbelaere@synopsys.com">Jeroen.Dobbelaere@synopsys.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div lang="EN-US">
<div class="gmail-m_-8319608733668172708WordSection1">
<p class="MsoNormal">Hi Alexey,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">This is defined in 6.7.3.1 paragraph 4:<u></u><u></u></p>
<p class="MsoNormal">'... Every other lvalue used to access the value of X shall also have its address based on P ...'<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">For 'assign1': <u></u><u></u></p>
<p class="MsoNormal">- x is a restrict pointer and is assumed to point to its own set of objects<u></u><u></u></p>
<p class="MsoNormal">- y is a normal pointer, based on x<u></u><u></u></p>
<p class="MsoNormal">- all access to the set of objects pointed by x are done through a pointer based on x<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">for 'assign2':<u></u><u></u></p>
<p class="MsoNormal">- x is a restrict pointer and is assumed to point to its own set of objects<u></u><u></u></p>
<p class="MsoNormal">- y is also a restrict pointer, based on x, but it is assumed to point to its own set of objects for the scope of y<u></u><u></u></p>
<p class="MsoNormal">- because of that, *x and *y must never overlap, as all accesses to the objects of y must be done based on a pointer derived from y<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">As such, a N=0 will trigger undefined behavior in assign2<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Doing the assignment to *x outside the inner block, makes the code valid again:<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><span style="font-size:13.5pt;font-family:"Courier New"">void assign3(int *pA, long N) {<br>
int *restrict x = pA;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:13.5pt;font-family:"Courier New""> int tmp;<br>
{<br>
int *restrict y = x + N;<br>
tmp = *y;<br>
}<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:13.5pt;font-family:"Courier New""> *x = tmp; // may alias with *y<br>
}</span><br>
<br>
<u></u><u></u></p>
<p class="MsoNormal">Greetings,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Jeroen Dobbelaere<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<div style="border-color:currentcolor currentcolor currentcolor blue;border-style:none none none solid;border-width:medium medium medium 1.5pt;padding:0in 0in 0in 4pt">
<div>
<div style="border-color:rgb(225,225,225) currentcolor currentcolor;border-style:solid none none;border-width:1pt medium medium;padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> Alexey Zhikhartsev <<a href="mailto:alexey.zhikhar@gmail.com" target="_blank">alexey.zhikhar@gmail.com</a>> <br>
<b>Sent:</b> Friday, February 14, 2020 22:52<br>
<b>To:</b> via Llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>><br>
<b>Cc:</b> Jeroen Dobbelaere <<a href="mailto:dobbel@synopsys.com" target="_blank">dobbel@synopsys.com</a>>; <a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a><br>
<b>Subject:</b> Given one restrict pointer based on another, should they never alias?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<p class="MsoNormal">We recently found an issue when using the full restrict implementation developed by Jeroen; it surfaces when compiling an obscure combination of std::valarray and std::indirect_array but I don't want to bore you with all the details. What
it boils down to is this basic question about restrict:<br>
<br>
Given one restrict pointer based on another, should they never alias?<br>
<br>
As far as I understand the formal definition of "restrict" in section 6.7.3.1 of the C standard [1], in the function below, pointer `y` is based on "restrict" pointer `x`; hence, the compiler will assume that accesses *x and *y might alias:<br>
<br>
<span style="font-size:13.5pt;font-family:"Courier New"">void assign1(int *pA, long N) {<br>
int *restrict x = pA;<br>
{<br>
int *y = x + N;<br>
*x = *y;<br>
}<br>
}</span><br>
<br>
<br>
However, what if y itself is declared "restrict": can the compiler assume that *x and *y will never alias?<br>
<br>
<span style="font-size:13.5pt;font-family:"Courier New"">void assign2(int *pA, long N) {<br>
int *restrict x = pA;<br>
{<br>
int *restrict y = x + N;<br>
*x = *y;<br>
}<br>
}</span><br>
<br>
Both Jeroen's and Hal's implementation (the intrinsic-based one) will say "NoAlias" for the accesses in assign2() but shouldn't x and y be in the same restrictness "bucket" since y is based on x?<br>
<br>
[1] <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__port70.net_-7Ensz_c_c11_n1570.html-236.7.3.1&d=DwMFaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=ELyOnT0WepII6UnFk-OSzxlGOXXSfAvOLT6E8iPwwJk&m=xMDqkSAlj-YCOS4JMDXAENpBS-eaCcLYSkIm1qK68fs&s=B3LRzqpd9bD1724nvhG0FtpFh3QPsQ4FTBGQ4qJn1cA&e=" target="_blank">
http://port70.net/~nsz/c/c11/n1570.html#6.7.3.1</a><u></u><u></u></p>
</div>
</div>
</div>
</div>
</blockquote></div>