unexpected result with -O2 solved via "volatile"

Allin Cottrell cottrell@wfu.edu
Sun Sep 19 18:17:50 GMT 2021


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


More information about the Gcc mailing list