https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61196
Bug ID: 61196
Summary: Optimizer does not handle memory accesses with two
pointers to same location correctly
Product: gcc
Version: 4.5.3
Status: UNCONFIRMED
Severity: major
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: bjoern.m.haase at web dot de
Created attachment 32800
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=32800&action=edit
testcase program
The following test case program boils down an issue with gcc.4.5.3 on the
cygwin platform. The bug is not present in the mingw version 4.7.2 that I also
have on my system. It, thus, might be fixed, but adding the test case might be
worth the effort to check for regressions.
When compiling with -O0 -O1 it outputs the expected result, when compiling with
-O2 or -O3, it produces an error.
The code is somewhat strange but I stumbled over this segment in production
code of the libsodium crypto library. Since it's a wrong code bug on an
important platform (X86), I did classify it as "major" bug.
Output of "gcc testcase.c -O0 -o test.exe && test.exe" :
bbccddee
66778899
22334455
ff001122
Output of "gcc testcase.c -O3 -o test.exe && test.exe" :
0
28d41c
28ac88
49435341
We had an error.
Output of "gcc testcase.c -O2 -o test.exe && test.exe" :
bbccddee
28d41c
28ac68
2d465455
We had an error.
Declaring the tp pointer in the testcase as volatile fixes the problem. For
this reason, I doubt that it's rather the middle end than the X86 backend.
////////////////////////////////////////////////////////////////////
///
/// File testcase.c
///
////////////////////////////////////////////////////////////////////
#include <stdio.h>
typedef unsigned long int uint32;
typedef struct {
unsigned long long a;
unsigned long long b;
} int128;
int128 x = {0x1234567,0x1234567};
void copy2(int128 *r, const int128 *x)
{
r->a = x->a;
r->b = x->b;
}
void shufd(int128 *r, const int128 *x, const unsigned int c)
{
int128 t;
uint32 *tp = (uint32 *)&t;
const uint32 *xp = (const uint32 *)x;
tp[0] = xp[c&3];
tp[1] = xp[(c>>2)&3];
tp[2] = xp[(c>>4)&3];
tp[3] = xp[(c>>6)&3];
copy2(r,&t);
}
int main (void)
{
int didErrorOccur = 0;
x.a = 0x112233445566778899ll;
x.b = 0xaabbccddeeff001122ll;
shufd (&x,&x,0x93);
printf ("%x \n", x.a);
printf ("%x \n", (x.a >> 32));
printf ("%x \n", x.b);
printf ("%x \n", (x.b >> 32));
if (x.a != 0x66778899bbccddeell)
{
didErrorOccur = 1;
}
if (x.b != 0xff00112222334455ll)
{
didErrorOccur = 1;
}
if (didErrorOccur)
{
printf ("We had an error.\n");
}
}