Should this perhaps be considered a bug? Below is a minimal test case for a type of calculation that occurs in my real code. It works as expected when compiled without optimization, but produces what seems like a wrong result when compiled with -O2, using both gcc 10.3.1 20210422 on Fedora and gcc 11.1.0-1 on Arch Linux. I realize there's a newer gcc release but it's not yet available for Arch, and looking at https://gcc.gnu.org/gcc-11/changes.html I didn't see anything to suggest that something relevant has changed.

<test-case>
#include <stdio.h>
#include <limits.h>

int test (int *pk, int n)
{
    int err = 0;

    if (*pk > n) {
        err = 1;
        if (*pk > 2e9) {
            int k = *pk + n - INT_MAX;

            *pk = k;
            if (k > 0) {
                printf("Got positive revised k = %d\n", k);
                err = 0;
            } else {
                printf("k = %d tests as non-positive?!\n", k);
            }
        }
    }

    return err;
}

int main (void)
{
    int k = INT_MAX - 10;
    int err;

    err = test(&k, 20);
    printf("main: err = %d\n", err);

    return 0;
}
</test-case>

What strikes me as "seems wrong" is that the "(k > 0)" branch in test() is not taken, although in the alternative branch it turns out that k = 10. This can be fixed by using the "volatile" keyword in front of the statement "int k = *pk + n - INT_MAX;" or by parenthesizing (n - INT_MAX) in that statement.

I can see the case for assuming that k can't be positive if one thinks of the expression as (*pk + n) - INT_MAX, since (*pk + n) can't be greater than INT_MAX in context, being the sum of two ints. All the same, since gcc does in fact end up assigning the value 10 to k the optimization seems a risky one.

--
Allin Cottrell
Department of Economics
Wake Forest University

Reply via email to