Hi,

On Thu, 5 May 2005, Daniel Berlin wrote:

> You can do it, but apparently restrict isn't as simple as "a and b are
> both restrict pointers and therefore can never alias", because that's
> not the actual definition of restrict. It says stuff about pointers
> "based on" restricted objects, etc.
> 
> Joseph Myers has shown some very weird but legal things you can do with
> restrict that make it all but pointless to try to handle, at least for
> the non function argument case.

Disagreement here.  Some of Josephs weird examples were things like:
  void f(int* restrict a, int * restrict b) {
    for (i=0; i < N; i+=2) a[i] = 2*b[i];
  }
  int array[N];
  f (&array[0], &array[1]);

I.e. interleaving the pointers in a way that they both point into the 
same object.  This is not forbidden by restrict, but it also poses no 
problem.  The two restrict pointers still may not actually point to the 
same memory objects (individual array elements here), so the compiler can 
still trivially apply the "two restrict pointers don't alias" rule.

Then there is the problem of "based on".  This allows a non-restrict
pointer to sometimes alias a restrict pointer.  One could ignore this
rule at first, for ease of implementation, and say that a unrestricted
pointer can alias everything again.  restricted pointers themself can only
be based on other restricted pointers under very narrow circumstances,
which effectively prevents them again to be aliased at their points of
dereference.

User actually using restrict in their programs will most probably use
restrict for each pointer possible, so just handling that two restrict
pointers can't alias alone would probably catch 90% of all cases. (I've
actually had one user who was very confused that the vectorizer didn't do
anything on his very simple two-line function, although he made all three
pointer arguments be restricted).

As you said the most important would probably be to handle restrict 
pointers in function arguments.  I would add to that also those pointers 
which are not used in any RHS of any statement (except for being 
dereferenced of course).  This would ensure that no other pointer is based 
on them.  And it would allow users to write code like:
  void f(int* a, int *b, int n) {
    if (a > b+n || b > a+n) {  // arrays don't overlap
      int * restrict ar = a;
      int * restrict br = b;
      /* Make this nonaliasing known to the compiler */
      for (int i = 0; i < n; i++) ar[i] += br[i];
    } else {
      /* They overlap, can't optimize as much */
      for (int i = 0; i < n; i++) a[i] += b[i];
    }
  }


Ciao,
Michael.

Reply via email to