Bug 26337 - aliasing causes stale data to be used
Summary: aliasing causes stale data to be used
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 26378 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-02-17 11:58 UTC by spelis@federation.3dlabs.com
Modified: 2006-02-20 10:51 UTC (History)
60 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: arm-3d-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description spelis@federation.3dlabs.com 2006-02-17 11:58:12 UTC
	

        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 spelis@federation.3dlabs.com 2006-02-17 11:58:12 UTC
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.
Comment 2 Eric Botcazou 2006-02-17 12:04:57 UTC
The code is invalid ISO C because "*((uint32_t *) &sy" breaks aliasing rules.

>          Our workarounds include (i) not using the optimiser,

-fno-strict-aliasing should be sufficient.

> or (ii) using a
>          union instead of the  "*((uint32_t *) &sy" style to obtain the
>          floating point (result) pattern.

Yep, the canonical method.  See the entry for -fstrict-aliasing in the manual.
Comment 3 Andrew Pinski 2006-02-17 12:48:54 UTC
Reopening to ...
Comment 4 Andrew Pinski 2006-02-17 12:49:12 UTC
Mark as a dup of bug 21920.

*** This bug has been marked as a duplicate of 21920 ***
Comment 5 Eric Botcazou 2006-02-20 10:51:04 UTC
*** Bug 26378 has been marked as a duplicate of this bug. ***