https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502

--- Comment #42 from Alexander Cherepanov <ch3root at openwall dot com> ---
I've recently stumbled upon a straightforward description (from Hal Finkel, in
https://bugs.llvm.org/show_bug.cgi?id=34548#c77) for the thing that bothered me
in the second part of comment 17. Roughly speaking: instability is
inconsistency, which leads to logical contradictions, which leads to total
chaos. Instability taints everything around it and you cannot trust anything in
the end. A small modification to the example in comment 18 will hopefully
illustrate it:

----------------------------------------------------------------------
#include <stdio.h>

__attribute__((noipa)) // imagine it in a separate TU
static void *opaque(void *p) { return p; }

static void f(void *p, void *q, void *r)
{
    if (p != q && q == r)
        printf("%d\n", p == r);
}

int main()
{
    int x[5];
    int y[2];

    void *p = &x;
    void *q = &y + 1;

    opaque(q); // escaped
    void *r = opaque(p); // hide the provenance of p

    f(p, q, r);
}
----------------------------------------------------------------------
$ gcc -std=c11 -pedantic -Wall -Wextra -fno-partial-inlining -O3 test.c &&
./a.out
0
----------------------------------------------------------------------
gcc x86-64 version: gcc (GCC) 10.0.0 20200110 (experimental)
----------------------------------------------------------------------

Here `r` has the same value as `p` but the optimizer cannot see this. Comparing
them to `q` gives different results -- `p` is non-equal to `q` (at compile
time) and `r` is equal to `q` (at run time). Then, given these results, we ask
the optimizer to compare `p` and `r` and it happily concludes that they are
non-equal which is nonsense.

This example could be explained by conditional propagation of wrong provenance
but I see the optimization happening during the einline pass so it's probably
not it. (-fno-partial-inlining simplifies the analysis but doesn't affect the
result.) Even if this particular example triggers some other bug(s) in gcc the
logic in the previous paragraph is probably nice to have in the optimizer. But
it could not until the instability is fixed.

I guess this settles the question for me FWIW. Unless there is a magic way to
contain logical contradictions I think the right way is like this:
- the C standard could be changed to make comparison of the form `&x == &y + 1`
unspecified or not -- not that important;
- all (non-UB) things in practice should have stable behavior;
- comparison of the form `&x == &y + 1` in practice should give results
according to naive, literal reading of C11.

Reply via email to