[llvm-dev] Memory barrier problem

Saito, Hideki via llvm-dev llvm-dev at lists.llvm.org
Wed Feb 3 11:03:53 PST 2021


>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?

-----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
>


More information about the llvm-dev mailing list