[Bug c++/52558] New: write introduction incorrect wrt the C++11 memory model

francesco.zappa.nardelli at gmail dot com gcc-bugzilla@gcc.gnu.org
Mon Mar 12 10:26:00 GMT 2012


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

             Bug #: 52558
           Summary: write introduction incorrect wrt the C++11 memory
                    model
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: francesco.zappa.nardelli@gmail.com


The program below:

int g_1 = 1;
int g_2 = 0;

int func_1(void) {
int l;
for (l = 0; (l != 4); l++) {
  if (g_1)
    return l;
  for (g_2 = 0; (g_2 >= 26); ++g_2)
    ;
}
}
int main (int argc, char* argv[]) {
func_1();
}

is miscompiled by 

  gcc -v :  gcc version 4.7.0 20120215 (experimental) (GCC)  

(a recent svn snapshot) on x86-64 when -O2 is passed.

Observe that the inner loop of func_1 is never executed, and this program
should never perform any read/write to g_2.  This means that func_1 might be
executed in a thread in parallel with another thread that performs:

 g_2 = 42;
 printf ("%d",g_2)

The resulting system is data-race free and the only value that should be
printed is 42.

However gcc -O2 generates the following x86-64 assembler for func_1:

func_1:
      movl    g_1(%rip), %edx
      movl    g_2(%rip), %eax
      testl   %edx, %edx
      jne     .L2
      movl    $0, g_2(%rip)
      ret
.L2:
      movl    %eax, g_2(%rip)
      xorl    %eax, %eax
      ret

and this code always performs a write to g_2.  If this asm code runs in
parallel with "g_2 = 42; printf g_2", then the system might also print 0: this
behaviour is introduced by the compiler and should not have happened.

The command line to generate the assembler above is:

$ g++ -std=c++11 read_and_write_introduced.c -O2 -S

It might be the case that in the C++11 memory model it is safe for the compiler
to introduce a write provided that there is an earlier write to the same
location, but this testcase shows that introducing a write is unsafe whenever
there are no previous writes.

I labelled this as g++, but the bug will also affect the (future) c11 memory
model.

For reference:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/home/riob/zappanar/tools/gcc-bin/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.7.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-src/configure --prefix=/home/zappanar/tools/gcc-bin
--with-gmp=/home/zappanar/tools/lib/ --with-mpfr=/home/zappanar/tools/lib/
--with-mpc=/home/zappanar/tools/lib/ --enable-languages=c,c++
Thread model: posix
gcc version 4.7.0 20120215 (experimental) (GCC)



More information about the Gcc-bugs mailing list