This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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