This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/50065] New: -Os, -O2, -O3 optimization breaks LD/ST ordering on 32-bit SPARC


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

             Bug #: 50065
           Summary: -Os, -O2, -O3 optimization breaks LD/ST ordering on
                    32-bit SPARC
    Classification: Unclassified
           Product: gcc
           Version: 4.6.1
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: tanzhangxi@gmail.com


Considering the following C code.

static inline int spinlock_trylock(char* lock)
{
    int reg;
    __asm__ __volatile__ ("ldstub [%1],%0" : "=r"(reg) : "r"(lock) : "memory",
"cc");
    return reg;
}

static inline int spinlock_is_locked(char* lock)
{
    int reg;
    __asm__ __volatile__ ("ldub [%1],%0" : "=r"(reg) : "r"(lock) : "memory");
    return reg;
}


static inline void spinlock_lock(char* lock)
{
    while(spinlock_trylock(lock))
      while(spinlock_is_locked(lock));
}

static inline void spinlock_unlock(char* lock)
{
    *(volatile unsigned char*)lock = 0;
}

char remap_lock;
int remap_barrier;

void inc_remap_barrier()
{

  spinlock_lock(&remap_lock);
  remap_barrier++;
  spinlock_unlock(&remap_lock);
}

A simple ++ counter is protected by a spinlock implemented with the ldstub
atomic instruction on SPARC.

If I use -Os/-O2/-O3 to optimize the code, e.g.
sparc-ramp-gcc -c -Os test.c -o test.o

gcc will generate the following code
00000000 <inc_remap_barrier>:
   0:   03 00 00 00     sethi  %hi(0), %g1
   4:   10 80 00 06     b  1c <inc_remap_barrier+0x1c>
   8:   82 10 60 00     mov  %g1, %g1   ! 0 <inc_remap_barrier>
   c:   c4 08 40 00     ldub  [ %g1 ], %g2
  10:   80 a0 a0 00     cmp  %g2, 0
  14:   12 bf ff fe     bne  c <inc_remap_barrier+0xc>
  18:   01 00 00 00     nop 
  1c:   c4 68 40 00     ldstub  [ %g1 ], %g2
  20:   80 a0 a0 00     cmp  %g2, 0
  24:   12 bf ff fa     bne  c <inc_remap_barrier+0xc>
  28:   05 00 00 00     sethi  %hi(0), %g2
  2c:   c0 28 40 00     clrb  [ %g1 ]
  30:   c6 00 a0 00     ld  [ %g2 ], %g3
  34:   86 00 e0 01     inc  %g3
  38:   81 c3 e0 08     retl 
  3c:   c6 20 a0 00     st  %g3, [ %g2 ]


instruction 2C, clrb [%g1] corresponds to inline function 'spinlock_unlock'
    *(volatile unsigned char*)lock = 0;

This happens before the lock protected content 'remap_barrier++', i.e.

  30:   c6 00 a0 00     ld  [ %g2 ], %g3
  34:   86 00 e0 01     inc  %g3
  38:   81 c3 e0 08     retl 
  3c:   c6 20 a0 00     st  %g3, [ %g2 ]     ---> use the branch delay slot

This is wrong and will cause serious lock issues under a multithreading
environment.

However, the same code works fine with -O1 and -O0

This problem happens with couple of cross GCC builds (4.3.2 / 4.6.1) at our
side with various configurations (with glibc or a bare metal setting).
It breaks with the following configurations:

1. 
COLLECT_GCC=sparc-ramp-gcc
COLLECT_LTO_WRAPPER=/home/charming/toolchain/sparc-ramp/libexec/gcc/sparc-ramp-elf/4.6.1/lto-wrapper
Target: sparc-ramp-elf
Configured with: /home/charming/toolchain/.build/src/gcc-4.6.1/configure
--build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu
--target=sparc-ramp-elf --prefix=/home/charming/toolchain/sparc-ramp
--with-local-prefix=/home/charming/toolchain/sparc-ramp/sparc-ramp-elf/sysroot
--disable-multilib --disable-libmudflap
--with-sysroot=/home/charming/toolchain/sparc-ramp/sparc-ramp-elf/sysroot
--with-newlib --enable-threads=no --disable-shared
--with-pkgversion='crosstool-NG 1.12.0' --disable-__cxa_atexit
--with-gmp=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--with-mpfr=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--with-mpc=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--with-ppl=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--with-cloog=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--with-libelf=/home/charming/toolchain/.build/sparc-ramp-elf/build/static
--enable-lto
--with-host-libstdcxx='-L/home/charming/toolchain/.build/sparc-ramp-elf/build/static/lib
-lpwl' --enable-target-optspace --disable-libgomp --disable-libmudflap
--disable-nls --enable-languages=c --with-cpu=v8
Thread model: single
gcc version 4.6.1 (crosstool-NG 1.12.0) 

2.
Using built-in specs.
COLLECT_GCC=sparc-ramp-gcc
COLLECT_LTO_WRAPPER=/home/xtan/toolchain/sparc-ramp/libexec/gcc/sparc-ramp-linux-gnu/4.6.1/lto-wrapper
Target: sparc-ramp-linux-gnu
Configured with: /home/xtan/toolchain/.build/src/gcc-4.6.1/configure
--build=x86_64-build_unknown-linux-gnu --host=x86_64-build_unknown-linux-gnu
--target=sparc-ramp-linux-gnu --prefix=/home/xtan/toolchain/sparc-ramp
--with-sysroot=/home/xtan/toolchain/sparc-ramp/sparc-ramp-linux-gnu/sysroot
--enable-languages=c,c++ --disable-multilib
--with-pkgversion=crosstool-NG-1.11.3 --enable-__cxa_atexit
--disable-libmudflap --disable-libgomp --disable-libssp
--with-gmp=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-mpfr=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-mpc=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-ppl=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-cloog=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-libelf=/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static
--with-host-libstdcxx='-L/home/xtan/toolchain/.build/sparc-ramp-linux-gnu/build/static/lib
-lpwl' --enable-threads=posix --enable-target-optspace
--with-local-prefix=/home/xtan/toolchain/sparc-ramp/sparc-ramp-linux-gnu/sysroot
--disable-nls --enable-symvers=gnu --enable-c99 --enable-long-long
Thread model: posix
gcc version 4.6.1 (crosstool-NG-1.11.3)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]