I have a program with an addition function for int8_t that is intended to check
for overflow.  Regardless of whether the test works, I get different results
from the program if I compile it with -O1 vs compiling with -O2.  It appears
that GCC is performing optimisations it shouldn't across the process boundaries
that lead to the wrong behaviour.  In particular, GCC is effectively saying
that it has the value 128 in an int8_t.  This is not specifically a printf
problem, as the overflow is not set with -O1, and is set with -O2.  Running
with -O1, the program runs all the tests successfully.  With -O2, there is a
failure, where GCC says it is adding the int8_t values 0 and 128 during the
loop.  Compare that with the earlier lines where it correctly says it is trying
to add 0 and -128 in the standalone tests.  Here's the complete code of the
reduced test-case (the .i file is no different apart from the included headers,
and the includes are all standard C headers):

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <limits.h>
#include <stdio.h>

int g_overflow;

static inline int8_t add_int8_t (int8_t, int8_t, const char *);
static inline int8_t add_int8_t (int8_t a, int8_t b, const char *pos) {
        printf("int8_t : adding %d and %d\n", (int)a, (int)b);
        if (((b<1)&&(-128-b<=a)) || ((b>=1)&&(127-b>=a))) {
                return a + b;
        } else {
                g_overflow = 1; return 0;
        }
}

int main(int argc, char** argv)
{
        g_overflow = 0;
        const int8_t result = add_int8_t(-128,0,"");
        printf("-128 + 0, result: %d, overflow: %d", (int)result, g_overflow);

        g_overflow = 0;
        const int8_t resultB = add_int8_t(0,-128,"");
        printf("-128 + 0, result: %d, overflow: %d", (int)resultB, g_overflow);

        // Test commutativity:
        int done_x_once = 0;
        for (int8_t x = 0; !(x == 0 && done_x_once == 1);x++) {
                done_x_once = 1;
                int done_y_once = 0;
                for (int8_t y = 0; !(y == 0 && done_y_once == 1);y++) {
                        done_y_once = 1;

                        g_overflow = 0;
                        const int8_t r0 = add_int8_t(x,y,"");
                        const int overflow_earlier = g_overflow;

                        g_overflow = 0;
                        const int8_t r1 = add_int8_t(y,x,"");
                        const int overflow_later = g_overflow;

                        if ((overflow_later == 1 && overflow_earlier == 1) ||
                          (overflow_earlier == 0 && overflow_later == 0 && r0
== r1)) {
                                //Passed
                        } else {
                                printf("Comm failed, non-commutative with %d,
%d (overflow: %d, %d) (res: %d, %d)\n",
                                  (int)x, (int)y, overflow_earlier,
overflow_later, r0, r1);
                                goto failed_comm;
                        }
                }
        }
        failed_comm:;


        return 0;
}


Here is my gcc -v output (I'm using the latest standard GCC on Ubuntu):

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu11'
--with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared
--with-system-zlib --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3
--program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug
--enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release
--build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu11)

Command-line to get correct behaviour (pasting the above code into gccbug.c)
is: gcc -std=gnu99 gccbug.c -O1
Command-line to trigger the bug is: gcc -std=gnu99 gccbug.c -O2

There is no compiler output, and adding -Wall still gives no compiler output.


-- 
           Summary: Optimisation with inline function causes invalid
                    behaviour
           Product: gcc
           Version: 4.3.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: gcc at twistedsquare dot com
 GCC build triplet: i486-linux-gnu
  GCC host triplet: i486-linux-gnu
GCC target triplet: i486-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38929

Reply via email to