[PATCH] D74935: [LangRef][AliasAnalysis] Clarify `noalias` affects only modified objects
Jeroen Dobbelaere via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 5 14:49:32 PST 2020
jeroen.dobbelaere added a comment.
In D74935#1907939 <https://reviews.llvm.org/D74935#1907939>, @jdoerfert wrote:
> In D74935#1907100 <https://reviews.llvm.org/D74935#1907100>, @jeroen.dobbelaere wrote:
>
> > Just to give an example:
> >
> > int foo(int* restrict *pA, int* restrict *pB) {
> > int tmp=**pB;
> > **pA=42;
> > return tmp - **pB; // **pA and **pB can refer to the same objects
> > }
> >
> >
> > [...]
>
>
> `*pA` and `*pB` are both restrict qualified pointers, are they not?
> If so, why can they point to the same location?
For the original example, *pA and *pB might be the same restrict pointer:
int* restrict pC = ....;
foo(&pC, &pC);
> I mean, w/o the side channel stuff the two `int *` values may alias
> even if you have `noalias` on the arguments (https://godbolt.org/z/J9v_gK).
And that is correct, as *pA might be equal to *pB for that case (even if pA and pB are not equal).
Restrictness adds additional information (ignoring for a moment the 'read only' case (see note *4)):
// case A
int * restrict prC;
int * restrict prD;
// pC and pD are separate (*1) restrict pointers => they point to their own separate sets of objects set(prC), set(prD), aka prC != prD (*2)
// case B
int * restrict * prpE;
int * restrict * prpF;
// prpE and prpF are _not_ restrict pointers, so prpE could be equal to prpF (prpE == prpF) or not (prpE != prpF)
// *prpE and *prpF are restrict pointers. When prpE == prpF, they represent the same restrict pointer.
// *prpE could point to prC or prD or a different restrict pointer => set(*prpE) =union(set(prC), set(prD), ...)
// also *prpF can point to union(set(prC), set(prD), ...)
// case C
int * restrict * restrict prprG;
int * restrict * restrict prprH;
// prprG and prprH are separate (*3) restrict pointers => they point to their own separate sets of objects set(prprG) and set(prprH)
// because of that: prprG != prprH
// and *prprG and *prprH represent also separate (see previous line) restrict points
// So *prprG and *prprH must point to their own separate sets of objects set(*prprG) and set(*prprH)
// The difference between between case B and case C is that in B, prpE could be equal to prpF (mayAlias), and because of that, *prpE could be equal to *prpF.
// By proving that prprG != prprH, it automatically follows that *prprG != *prprH (except for (*4))
// Notes:
// (*1) &prC != &prD
// (*2) it actually is: for all i,j for which prC[i] and prD[j] are 'valid', &prC[i] != &prD[j]
// (*3) &prprG != &prprH
// (*4) The restrict definition contains a relaxation when restrict pointers are only used for reading memory:
// In that case, separate restrict pointers are allowed to point to the same set of objects... except for:
// But: it also states that (6.7.3.1 paragraph 4 : '.. Every access that modifies X shall be considered also to modify P,for the purposes of this subclause. .. '
// Which means that if your write to **prprG, it is _as if_ you also write to *prprG and because of that, both prprG and *prprG must point to their own set of objects set(prprG) and set(*prprG)
// and those sets must also be different from set(prprH) and set(*prprH)
Now, in the original example, we have 'case B'. pA could be equal to pB (mayAlias), and because of that, *pA could be equal to *pB.
int foo(int* restrict *pA, int* restrict *pB);
When we can proof that pA != pB (noalias), then *pA and *pB represent different restrict pointers and *pA != *pB. (different restrict pointers point to their own set of objects)
So, adding the 'noalias' attribute to %pA and %pB will change the behavior of foo().
hmm... this explanation is maybe getting too long ?
The short conclusion should be:
- adding 'noalias' to a pointer argument, because it is only used to read memory, might lead to 'wrong code'
- two 'noalias' pointer arguments should not overlap
or relaxed:
- two 'noalias' pointer arguments can only overlap if they (at any level of indirection) are never used to write to memory.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74935/new/
https://reviews.llvm.org/D74935
More information about the cfe-commits
mailing list