Marking select(2) as restrict

Mark Millard marklmi26-fbsd at yahoo.com
Mon Feb 26 04:40:30 UTC 2018



On 2018-Feb-25, at 7:45 PM, Bruce Evans <brde at optusnet.com.au> wrote:

> On Sun, 25 Feb 2018, Mark Millard via freebsd-standards wrote:
> 
>> On 2018-Feb-25, at 12:48 PM, Tijl Coosemans <tijl at FreeBSD.org> wrote:
>> 
>>> On Thu, 22 Feb 2018 12:56:08 +0200 Konstantin Belousov <kostikbel at gmail.com> wrote:
>>>> Consider the recently changed devd code:
>>>> 	select(n + 1, &fd, &fd, &fd);
>>>> There, compiler can see that restrict is applied to arguments which are
>>>> given same values.  Since this leads to the self-contradicting statement
>>>> 	fd != fd
>>>> which cannot be true, compliler in its optimizing wisdom can assume that
>>>> the code is never executing and remove it.  I do not know whether clang
>>>> actually makes such transformation, but it does not sound unfeasible
>>>> looking at its other advances.
>>> 
>>> There's an example in the C99 standard that indicates such a call is not
>>> necessarily undefined so compilers cannot optimise it away:
>>> 
>>> EXAMPLE 3
>>> The function parameter declarations
>>> void h(int n, int * restrict p, int * restrict q, int * restrict r)
>>> {
>>> 	int i;
>>> 	for (i = 0; i < n; i++)
>>> 		p[i] = q[i] + r[i];
>>> }
>>> illustrate how an unmodified object can be aliased through two restricted
>>> pointers.  In particular, if a and b are disjoint arrays, a call of the
>>> form h(100, a, b, b) has defined behavior, because array b is not modified
>>> within function h.
>> 
>> Good point. In essence the restrictions on the caller can
>> not be known independently of how the parameters are used
>> in the called code --something that prototype does not specify.
>> This does constrain what the compiler can do about potential
>> aliasing that it might detect.
>> 
>> A prototype that would make h's restrictions clearer is
>> one that reports that q and r are not used to modify
>> memory:
>> 
>> void h(int n, int * restrict p, int const * restrict q, int const * restrict r);
>> 
>> With such a prototype, it is easier to known that q's "objects"
>> and r's "objects" both simply must not overlap p's "objects".
>> (See g from example 2 for its d+50 valid vs. d+1 invalid status.)
> 
> I think the example intentionally leaves out 'const'.  I think const
> already prevents aliasing.  'restrict' prevents it even more.  Using
> the combination in the exaple would make it less clear what the
> 'restrict' part does.

Agreed: the combination would make the example less clear
about restrict. So, agreed: likely deliberate for specifying
just restrict's semantics. I would not suggest my alternate
h prototype for that example in the standard: different
purposes served.

> . . . restrict is not needed for the input-only
> args since const suffices. 

Here you lost me.

With q and r having both the const and the restrict,
updates to p's "objects" can not change the
"object(s)" q and r validly can be used to access.
That can be important.

Without the "restrict" for q and r (but still
having the const for each) it is valid for updates
to p's "objects" to change what q and r then can
validly access.

The 2 restrict's in question do not seem redundant
to me as far as the prototype goes. They may enable
optimizations in some architectures: more order of
operation independence so more reordering possible.

A more general context could still require words
describing requirements, words beyond the restrict
and const use. I would not claim that adding const
where it fits would make all contexts well described.
This one just happened to be nicer for the person
reading the prototype. (But it would makes for a
worse specification of restrict of itself to have
the const's in place in example 3.)

===
Mark Millard
marklmi at yahoo.com
( markmi at dsl-only.net is
going away in 2018-Feb, late)



More information about the freebsd-standards mailing list