gcc-13 bug

Yes, this turned out to be an instance of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117287 

I hit what more and more looks like a bug in the standard Ubuntu 24 gcc version. Here is a minimal reproducer that I with great pain extracted from 12KLOC sources:

struct foo {
        int   seq;
        void *data;
};

struct bar {
        struct foo rung[1];
};

static int used;

static char ll(const struct foo *n) {
        return *(char *)n->data;
}

int main(int argc, char **argv) {
        struct bar p = {};
        int result = 0;
        used = 0;
        __asm__ __volatile__("": : :"memory");
        for (int i = 0; i <= used && result == 0; ++i) {
                struct foo *r = &p.rung[i];
                __attribute__((assume(i <= 0 || ll(r) + 1 == ll(r - 1))));
                if (!(r->seq == 0 && (i <= 0 || ll(r) + 1 == ll(r - 1)))) {
                        result = -1;
                }
        }
        return 0;
}

Compile as gcc -O1 gcc-13-bug.c, it crashes with SIGSEGV. Note that because the loop iterates only once, i == 0 in the body of the loop, so ll(r) should not be called. Yet, ll(r) and ll(r-1) are both called.

The reproducer is minimal in the sense that it is locally optimal: any small random change eliminates the effect. For example,

Move used = 0 over the asm-barrier (or simply remove the barrier).

Remove result == 0 from the loop guard.

Replace struct bar p = {} with struct foo[1] p = {} mutatis mutandis. This one is especially surprising.