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]
Other format: [Raw text]

_Nomodify extension idea for optimization and safety


Hi, I've thought of a simple optimization.
I'm sending this because I'd like feedback on it,
and I might submit a C proposal a few years later.

This (https://theartofmachinery.com/2019/08/12/c_const_isnt_for_performance.html)
blog post inspired me. The summary is that the const-ness of const pointers
in function prototypes can be cast away.

I've thought of _Nomodify as a stricter const, but it can
only be used in function parameters that are pointers. (Thus it implies
const, except that it can be modified without the need of casting away,
details are in the paragraph that starts with Moreover)

Example of casting away const:

void a(char * h) {}

void b(const char * x) {
    a(x);
}

void c(void) {
    char x[3] = {1, 2, 3};
    b(x);
}

which only gives a warning. For safety, if _Nomodify were used instead
of const, the compiler should've given an error (or we can just flag it as
UB and optimize it?) since if a function had a parameter that was declared
in one of the caller functions' parameters as _Nomodify, the callee's that
parameter should also be tagged as _Nomodify.

(i.e. if b's x parameter is _Nomodify, so should be a's h parameter)

----

Moreover, I've thought of a way to extend its usage:

- A function may change the value pointed by a _Nomodify pointer,
given that the function guarantees to restore the value before returning
to the caller body.

Like this:

void a(_Nomodify char * h) {}

void b(_Nomodify char * x) {
    *x ^= 1;
    a(x);
    *x ^= 1;
}

void c(void) {
    char x[3] = {1, 2, 3};
    b(x);
}

The only problems with this idea are not-injective functions.
While multiplying real numbers by a (nonzero) coefficient is
injective, neither int nor float multiplication is injective.
(For example (a*2)/2 may not be a for a = 2147483647)
This might open security vulnerabilities, but they could
just copy the value pointed by the pointer to a temporary
variable, and then restore it before returning.

----

Something I'm not sure about is, since it only affects pointers,
should it be used like restrict:

void a(int * _Nomodify);

or const:

void a(int _Nomodify *);

----

One way to implement this in the compilers is making the compiler read

void a(some_t * _Nomodify);

void b(some_t * x) {
    a(x);
}

as

void a(some_t * _Nomodify);

void b(some_t * x) {
    const some_t r = *x;
    a(&r);
}

as highlighted in the blog post I linked. This'd allow one to see how
much this optimization can help their code.

Besides, it should be able to be applied only to function parameters (or at
least it makes sense to only do so)

Lastly, it can't be added as an __attribute__, because it should work
for pointers-of-pointers-of-... but each __attribute__ can be used once for
a variable IIRC.

Please help me develop this idea by leaving feedback about possible flaws.
I'm asking for feedback here, because programmers involved in compilers
have lots of experience related to optimizations and safety warnings,
so please, let's improve this draft.


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