Marking select(2) as restrict

Mark Millard marklmi26-fbsd at yahoo.com
Sun Feb 25 23:32:08 UTC 2018


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.)

Section 7.1 of the C Rationale says:

"The restrict keyword allows the prototype to express what was
previously expressed by words."

But it turns out that not all the words can be eliminated if one
is to know the actual criteria for what the caller is allowed to
do while staying within defined behavior.

There is a lot of wording for which the "example 3"
h(100, a, b, b) example usage being well defined is not
obvious. Such wording is without any specific such context
to reference and tends to assume that all restricted pointers
are used to modify the matching objects (when const does not
prevent such). This need not be the case.

===
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