This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: `__norestrict' type qualifier


Jamie Lokier wrote:
>     Reading an object of type A through a pointer of type `__norestrict B *'
>     shall have the same, implementation-defined behaviour as copying the A
>     into field `a' of a temporary of type `union { A a; B b; }', and then
>     reading field `b'.

Gak!  The above doesn't work, and neither does the byte array definition.

Both definitions only promise to preserve the _first_ pointed to object, as
they are written in terms of accessing _an_ object through a pointer to a
different type of object.  Real optimisations depend on the behaviour of
accessing parts of arrays.  In real life, fairly portable optimisations
work if the larger type is simply used to copy or compare for equality
small sequences of smaller objects.  The kernel and memcpy examples both do
this.

There are also complications with alignment, and undefined behaviour when
you access memory outside any object or array.

So what do folks think of this?  It's long I know...

  +------------------------------------------------------------------------+
    For copying, and conversion to other pointer types, pointers of type
    `__norestrict B *', for all B, behave exactly like `void *'.

    Reading and writing through the pointer are defined as follows.  Let A
    be the type of the actual object pointed to, and `__norestrict B *' be
    the type of pointer used for the read or write.  Let N = (sizeof (B) +
    sizeof (A) - 1) / sizeof (A).  I.e., N is the number of objects of
    sizeof (B) that fit within sizeof (A), including a possible partial
    object.

    If pointed to object is an element of an array, let MAX = S - P, where
    S is the number of elements in the array, and P is the offset of the
    pointed to object within the array.  Otherwise MAX is 1.

    If N > MAX, then the behaviour is undefined.  This implies access
    beyond the end of an array.  [ Or whatever the standard says about such
    accesses ].  Otherwise:

    Reading through the pointer of type `__norestrict B *' shall have the
    same, implementation-defined behaviour as copying the pointed to object
    into field a[0] of a temporary of type union `{ A a[N]; B b; }', and if
    N > 1, copying N-1 subsequent elements from the array containing the
    pointed to object into subsequent elements of the array in the union
    temporary, and then reading field `b' from the temporary.

    Writing through the pointer of type `__norestrict B *' shall have the
    same, implementation-defined behaviour as writing to field b of a
    temporary of type `union { A a[N]; B b; }', and then copying field a[0]
    into the pointed to object, and if N > 1, copying N-1 subsequent
    elements from the array in the union temporary to subsequent elements
    of the array containing the pointed to object.

    For reading and writing, the order of the N copies is not defined --
    they may occur simultaneously, independently or in any combination.  A
    volatile qualification on A does not change this.  A const
    qualification is honoured by disallowing writes in the usual way.
  +------------------------------------------------------------------------+

> > Yeah, and it might be simplest to just rename it "__typealias", define
> > its behavior in terms of GCC's aliasing assumptions, and forget about
> > every trying to standardize it.

It's so obviously what we're going to anyway :-)

But GCC's aliasing assumptions are not _that_ well defined, and we probably
want to be cautious about restrict future optimisations too.  So pinning
down what users can expect from __norestrict is a good idea.

-- Jamie


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]