This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/26337] New: aliasing causes stale data to be used
- From: "gcc-bugzilla at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 17 Feb 2006 11:58:13 -0000
- Subject: [Bug c++/26337] New: aliasing causes stale data to be used
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
We are targetting the compilers for a system-on-chip solution we are
developing based on an ARM 926 which is without an FPU so we have
defaulted on SOFTWARE FLOATING POINT.
#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | \
ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
We run the executables either on a third party (ARM 926) development
boa
rd or
an our chip simulator. However the bug can be shown in the assembler
output.
We have come across a problem which is present in 3.4.1 compiler and
when we investigated (by quickly building) a 3.4.5 compiler we came
across the same bug. The samllest program which illustrates the bug is
brokenPointer.cxx;
/* ----- START ---- */
#ifdef DEBUG
#include <stdio.h>
#endif
typedef unsigned int uint32_t;
typedef uint32_t Data[2];
void dump( Data *data, uint32_t count )
{
uint32_t i;
for( i = 0; i < count; i++ )
#ifdef DEBUG
printf( "0x%08X <- 0x%08X\n", data[i][0], data[i][1] );
#else
data[i][0] += data[i][1] ;
#endif
}
float sx, sy;
void moo( float fx[2], float fy[2], uint32_t size[2], uint32_t params[2] )
{
sx = (fx[1] - fx[0]) / size[0];
sy = (fy[1] - fy[0]) / size[1];
Data data[] = {
{ 0, 0xAA55AA55 },
{ 1, 0 },
{ 2, 1 },
{ 3, 2 },
{ 6, 16 },
{ 7, params[0] },
{ 8, params[1] },
{ 9, *((uint32_t *) &sx) },
{ 10, *((uint32_t *) &sy) },
};
dump( data, sizeof(data) / sizeof(*data) );
}
int main( int argc, char *argv[] )
{
float fx[2] = { -2, 2 };
float fy[2] = { -2, 2 };
uint32_t size[2] = {64, 64};
uint32_t params[2] = {16, 4};
moo( fx, fy, size, params );
}
/* ----- END ---- */
The program we compile, brokenPointer.cxx, produces the output:
# arm-3d-linux-g++ -Os -DDEBUG brokenPointer.cxx
0x00000000 <- 0xAA55AA55
0x00000001 <- 0x00000000
0x00000002 <- 0x00000001
0x00000003 <- 0x00000002
0x00000006 <- 0x00000010
0x00000007 <- 0x00000010
0x00000008 <- 0x00000004
0x00000009 <- 0x3D800000
0x0000000A <- 0x00000000
When compiled and run on an (x86,say) host the final line is
correctly output as:
:: ::
0x0000000A <- 0x3D800000
We can illustrate the bug in the assembler code
arm-3d-linux-g++ -S -Os brokenPointer.cxx
illustrates the bug in brokenPointer.s
The source code section going wrong is:
-- extract start --
sy = (fy[1] - fy[0]) / size[1]; /* true value computed */
Data data[] = {
::
{ 10, *((uint32_t *) &sy) }, /* wrong value saved
he
re */
-- extract finish --
::
bl __divsf3 /* sy = (fy[1] - fy[0]) / size[1]; */
ldr r3, .L13+8
ldr r6, [r5, #4]
ldr r7, [r7, #0]
ldr r5, [r5, #0]
str r3, [fp, #-104]
mov r3, #3
str r3, [fp, #-84]
add r3, r3, r3
str r3, [fp, #-76]
add r3, r3, #10
mov ip, #1
str r3, [fp, #-72]
sub r3, r3, #9
mov lr, #2
mov r4, #9
ldr r8, [sl, #0] /* BUG: this is "early" y being load
ed */
str r3, [fp, #-68]
add r3, r3, ip
mov r2, #0
str r0, [sl, #0] @ float /* r0 is the __divsf3 result so is t
he true "y" result */
str r3, [fp, #-60]
mov r1, r4
add r3, r3, lr
sub r0, fp, #108
str r2, [fp, #-96]
str ip, [fp, #-88]
str lr, [fp, #-80]
str r3, [fp, #-44]
str r5, [fp, #-64]
str r6, [fp, #-56]
str r7, [fp, #-48]
str r8, [fp, #-40] /* BUG: "*((uint32_t *) &sy" is taking the
"early" value */
str r2, [fp, #-108]
What happens is that the compiler has not stored the reult of the "__divsf
3"
which is in r0 until very late in the day. In the meantime it loads r8
from where it thinks the result is but at the time r8 is loaded it has not
yet stored r0 !
Environment:
System: Linux federation.3dlabs.com 2.4.21-27.ELsmp #1 SMP Mon Feb 28 16:43:09
EST 2005 i686 athlon i386 GNU/Linux
Architecture: i686
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: arm-3d-linux-gnu
configured with: /homes/spelis/dopt/gnu/gcc-3.4.5/configure
--prefix=/homes/spelis2/3.4.5gcc --with-gnu-as --with-gnu-ld
--with-as=/opt/s2tools/lx/bin/arm-3d-linux-as
--with-ld=/opt/s2tools/lx/bin/arm-3d-linux-ld
--srcdir=/homes/spelis/dopt/gnu/gcc-3.4.5 --target=arm-3d-linux
--with-cpu=arm926ejs --enable-languages=c,c++ --disable-shared --without-newlib
--disable-threads
How-To-Repeat:
Any arm target compiler should reproduce the bug with "-Os" and SOFTWAR
E
floating point ( -mfpu=softvfp ) which allows the problem to be
identified by assembler output.
arm-3d-linux-gcc -v -save-temps -Os -S brokenPointer.cxx
Reading specs from /homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.4.5/s
pecs
Configured with: /homes/spelis/dopt/gnu/gcc-3.4.5/configure --prefix=/homes/spe
lis2/3.4.5gcc --with-gnu-as --with-gnu-ld --with-as=/opt/s2tools/lx/bin/arm-3d-
linux-as --with-ld=/opt/s2tools/lx/bin/arm-3d-linux-ld --srcdir=/homes/spelis/d
opt/gnu/gcc-3.4.5 --target=arm-3d-linux --with-cpu=arm926ejs --enable-languages
=c,c++ --disable-shared --without-newlib --disable-threads
Thread model: single
gcc version 3.4.5
/homes/spelis2/3.4.5gcc/libexec/gcc/arm-3d-linux/3.4.5/cc1plus -E -quiet -v -D
_GNU_SOURCE brokenPointer.cxx -mcpu=arm926ejs -Os -o brokenPointer.ii
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5/arm-3d-linux"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5/backward"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../arm-3d-linux/sys-include"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../arm-3d-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.4.5/include
End of search list.
brokenPointer.cxx:1:19: stdio.h: No such file or directory
federation!spelis 19 ^Cm-3d-linux-gcc -v -save-temps -Os -S brokenPointer.cxx >
federation!spelis 19 vi brokenPointer.cxx
federation!spelis 20 arm-3d-linux-gcc -v -save-temps -Os -S brokenPointer.cxx >
Reading specs from /homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.4.5/specs
Configured with: /homes/spelis/dopt/gnu/gcc-3.4.5/configure --prefix=/homes/spe
lis2/3.4.5gcc --with-gnu-as --with-gnu-ld --with-as=/opt/s2tools/lx/bin/arm-3d-
linux-as --with-ld=/opt/s2tools/lx/bin/arm-3d-linux-ld --srcdir=/homes/spelis/d
opt/gnu/gcc-3.4.5 --target=arm-3d-linux --with-cpu=arm926ejs --enable-languages
=c,c++ --disable-shared --without-newlib --disable-threads
Thread model: single
gcc version 3.4.5
/homes/spelis2/3.4.5gcc/libexec/gcc/arm-3d-linux/3.4.5/cc1plus -E -quiet -v -D
_GNU_SOURCE brokenPointer.cxx -mcpu=arm926ejs -Os -o brokenPointer.ii
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5/arm-3d-linux"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../include/c++/3.4.5/backward"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../arm-3d-linux/sys-include"
ignoring nonexistent directory "/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.
4.5/../../../../arm-3d-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/homes/spelis2/3.4.5gcc/lib/gcc/arm-3d-linux/3.4.5/include
End of search list.
/homes/spelis2/3.4.5gcc/libexec/gcc/arm-3d-linux/3.4.5/cc1plus -fpreprocessed
brokenPointer.ii -quiet -dumpbase brokenPointer.cxx -mcpu=arm926ejs -auxbase br
okenPointer -Os -version -o brokenPointer.s
GNU C++ version 3.4.5 (arm-3d-linux)
compiled by GNU C version 3.4.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
------- Comment #1 from spelis at federation dot 3dlabs dot com 2006-02-17 11:58 -------
Fix:
Our workarounds include (i) not using the optimiser, or (ii) using a
union instead of the "*((uint32_t *) &sy" style to obtain the
floating point (result) pattern.
--
Summary: aliasing causes stale data to be used
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: spelis at federation dot 3dlabs dot com
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: arm-3d-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26337