> >So a weaker `noalias` or a way to mark uses seems therefore required
for
> >`noalias` deduction.
>
> Appears to be that way. Can we do that w/o having a weaker restrict in the
> language spec?
The full restrict[0] implementation does not depend on the 'noalias'
attribute on
function arguments. The attribute is even too strong for just mapping a
'C99 restrict pointer argument' to a 'LLVM-IR noalias pointer
argument'.
For backwards compatibility, I kept the default mapping of restrict pointer
arguments
onto 'noalias' and provided the '-fno-noalias-arguments' option
to disable this mapping
For some code, this can result in a wrong 'based on' deduction.[1]
Given that, IMHO, it still makes sense to have a strong and a weaker version of
the
'noalias argument attribute'. At least, the stronger (current
'noalias') version can be
converted to the noalias scope/intrinsics mapping during inlining, keeping the
strong guarantees.
Converting a weaker version likely will need some more tweaking.
The noalias attribute is also used for a struct pointer argument when a function
returns a struct.
Greetings,
Jeroen Dobbelaere
[0] Full Restrict patches: https://reviews.llvm.org/D68484
[1] 'clang/test/CodeGen/restrict/arg_reuse.c' testcase in:
https://reviews.llvm.org/D68521
>
> -----Original Message-----
> From: Johannes Doerfert <johannesdoerfert at gmail.com>
> Sent: Wednesday, February 3, 2021 10:52 AM
> To: Jeroen Dobbelaere <Jeroen.Dobbelaere at synopsys.com>; Saito,
Hideki
> <hideki.saito at intel.com>; Kaylor, Andrew <andrew.kaylor at
intel.com>
> Cc: llvm-dev at lists.llvm.org
> Subject: Re: [llvm-dev] Memory barrier problem
>
>
> On 2/3/21 12:44 PM, Jeroen Dobbelaere wrote:
> >>>> W.r.t. restrict, I'd like to hear more from the
language lawyers on
> >>>> their
> >> original intent when the language construct was born and the
current
> >> interpretation of it in the presence of threading.
> >>> I would have assumed `__restrict` predates "common"
multi-processing in C.
> >> Since the language of restrict is to this day implying other
threads
> >> cannot access those pointers, I would not dare to argue we should
> >> weaken it in order to deduce `noalias`.
> >>> ~ Johannes
> >>>
> > Having interacted recently with wg14 to get a better understanding
> > about some of the corner cases around restrict, I can add the
following:
> >
> > One way to look at a restrict pointer[1], is as if you get a local
array.
> > That means that following code:
> >
> > void foo_a(int *restrict rpDest, int *restrict rpSrc, int n) {
> > for (int i=0; i<n; ++i)
> > rpDest[i] = rpSrc[i]+1;
> > }
> >
> > is allowed to behave as if it was written as follows:
> > void foo_b(int *pDest, int *pSrc, int n) {
> > int localDest[n];
> > int localSrc[n];
> > memcpy(&localDest[0], pDest, n*sizeof(int));
> > memcpy(&localSrct[0], pSrc, n*sizeof(int));
> > for (int i=0; i<n; ++i)
> > localDest[i] = localSrc[i]+1;
> > memcpy(pDest, &localDest[0], n*sizeof(int));
> > }
> >
> > Calling foo_a and foo_b with overlapping arrays can show different
> > results, depending on how the loop was optimized. That is an
> > indication that this usage of 'foo_a' is triggering undefined
behavior and
> should not be done.
>
> The way I interpret this is consistent with Eli's opinion and what we
> basically do so far, restrict is stronger than synchronization since the
local
> arrays are not synchronized across threads. If two threads access the same
> memory (even well synchronized) it breaks the restrict requirement and is
> therefor UB.
>
> So a weaker `noalias` or a way to mark uses seems therefore required for
> `noalias` deduction.
>
> ~ Johannes
>
>
> > Wrt to threading: as long as the restrict pointer (rpDest, rpSrc;
> > localDest, localSrc) is not escaping, a different thread should not be
able
> to access the memory, as there is no way it can get a pointer 'based
on'
> > the restrict pointer.
> >
> > Note [1]: things get more interesting when having a 'pointer to a
restrict
> pointer' (aka int *restrict *prp).
> >
> > Greetings,
> >
> > Jeroen Dobbelaere
> >