<div dir="ltr"><div>My pleasure, thanks for looking into it.</div><div><br></div><div>To clarify, is it correct to say that assign3 and assign4 are conceptually the same? That is, it makes no difference that a restrict pointer is a member variable, and it is private.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Feb 20, 2020 at 9:42 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_2027429453916289701WordSection1">
<p class="MsoNormal">Hi Alexey,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Thanks for the bug report !<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">this should indeed behave the same as 'assign3'. With this code, you triggered a 'FIXME' in the full restrict patches ;)<u></u><u></u></p>
<p class="MsoNormal">(See: <a href="https://reviews.llvm.org/D68512#inline-681480" target="_blank">
https://reviews.llvm.org/D68512#inline-681480</a> )<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">I hope to find some time in March to resurrect the activity on those patches...<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Jeroen<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> Thursday, February 20, 2020 01:56<br>
<b>To:</b> Jeroen Dobbelaere <<a href="mailto:dobbel@synopsys.com" target="_blank">dobbel@synopsys.com</a>><br>
<b>Cc:</b> via Llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>; <a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a><br>
<b>Subject:</b> Re: 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" style="margin-bottom:12pt">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>
<span style="font-size:13.5pt;font-family:"Courier New"">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><u></u><u></u></p>
<div>
<p class="MsoNormal">I see that the full restrict implementation says that the load and the store do not alias. Is this by design?<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal">On Sat, Feb 15, 2020 at 9:00 AM Jeroen Dobbelaere <<a href="mailto:Jeroen.Dobbelaere@synopsys.com" target="_blank">Jeroen.Dobbelaere@synopsys.com</a>> wrote:<u></u><u></u></p>
</div>
<blockquote style="border-color:currentcolor currentcolor currentcolor rgb(204,204,204);border-style:none none none solid;border-width:medium medium medium 1pt;padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<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;</span><u></u><u></u></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>
  }</span><u></u><u></u></p>
<p class="MsoNormal" style="margin-bottom:12pt"><span style="font-size:13.5pt;font-family:"Courier New"">  *x = tmp; // may alias with *y<br>
}</span><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-style:none none none solid;border-width:medium medium medium 1.5pt;padding:0in 0in 0in 4pt;border-color:currentcolor currentcolor currentcolor blue">
<div>
<div style="border-style:solid none none;border-width:1pt medium medium;padding:3pt 0in 0in;border-color:currentcolor">
<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>
</div>
</div>
</div>

</blockquote></div>