gcc -O2 generates wrong code

Bug #158799 reported by Unai Uribarri
2
Affects Status Importance Assigned to Milestone
gcc-4.1 (Ubuntu)
Invalid
Undecided
Unassigned

Bug Description

Binary package hint: gcc-4.1

When compiling this code with the -O2 flag the result is different than when compiling with -O, or when disabling tree-pre or strict-aliasing optimizations.

$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --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.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
$ gcc -O test.c ; ./a.out
$ gcc -O2 test.c ; ./a.out
Ohhh
$ gcc -O2 -fno-tree-pre test.c ; ./a.out
$ gcc -O2 -fno-strict-aliasing test.c ; ./a.out
$ cat test.c
#include <stdlib.h>
#include <stdio.h>

int bmemcmp(void *a1, void *a2, unsigned len)
{
        int dwlen = len / 4;
        while (dwlen)
        {
                int res = *(int *)a1 - *(int *)a2;
                if (res)
                        return res;

                --dwlen;
                ++*(int **)&a1;
                ++*(int **)&a2;
        }
        return 0;
}

int main(int argc, char *argv[])
{
        int *p1 = (int*)calloc(sizeof(int), 1024 * 1024 * 4);
        int *p2 = (int*)calloc(sizeof(int), 1024 * 1024 * 4);
        p1[3] = 1;
        if (bmemcmp(p1, p2, 1024 * 1024 * 4) == 0)
                printf("Ohhh\n");
        return 0;
}

Revision history for this message
Unai Uribarri (unaiur) wrote :

I believe that compiler is optimizing this lines:
                int res = *(int *)a1 - *(int *)a2;
                if (res)
                        return res;

So bmemcmp always return 0.

description: updated
Unai Uribarri (unaiur)
description: updated
Revision history for this message
Unai Uribarri (unaiur) wrote :

Please, can someone close this bug as invalid? I'm violating C aliasing rules at ++*(int **)aX;.

Revision history for this message
Unai Uribarri (unaiur) wrote :

                ++*(int **)&a1;
                ++*(int **)&a2;

you are accessing a void* as an int* which violates C/C++ aliasing rules so you
are invoking undefined behavior.

Changed in gcc-4.1:
status: New → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.