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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits