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

             Bug #: 50583
           Summary: Many __sync_XXX builtin functions are incorrect
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: hjl.to...@gmail.com
                CC: kirill.yuk...@intel.com, ubiz...@gmail.com


We have

`TYPE __sync_fetch_and_add (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_fetch_and_sub (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_fetch_and_or (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_fetch_and_and (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_fetch_and_xor (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_fetch_and_nand (TYPE *ptr, TYPE value, ...)'
     These builtins perform the operation suggested by the name, and
     returns the value that had previously been in memory.  That is,

          { tmp = *ptr; *ptr OP= value; return tmp; }
          { tmp = *ptr; *ptr = ~(tmp & value); return tmp; }   // nand

On x86, they may be implemented as

[hjl@gnu-33 gcc]$ cat /tmp/x.c
int
foo (int *p)
{
  return __sync_fetch_and_and(p, 7);
}
[hjl@gnu-33 gcc]$ gcc -S -O2 /tmp/x.c
[hjl@gnu-33 gcc]$ cat x.s
    .file    "x.c"
    .text
    .p2align 4,,15
    .globl    foo
    .type    foo, @function
foo:
.LFB0:
    .cfi_startproc
    movl    (%rdi), %eax
.L2:
    movl    %eax, %edx
    movl    %eax, %ecx
    andl    $7, %edx
    lock cmpxchgl    %edx, (%rdi)
    jne    .L2
    movl    %ecx, %eax
    ret
    .cfi_endproc
.LFE0:
    .size    foo, .-foo
    .ident    "GCC: (GNU) 4.6.0 20110603 (Red Hat 4.6.0-10)"
    .section    .note.GNU-stack,"",@progbits
[hjl@gnu-33 gcc]$ 

This isn't equivalent to 

 { tmp = *ptr; *ptr OP= value; return tmp; }

It is

 {
   tmp = *ptr;
   tmp1 = tmp OP value;
   return __sync_val_compare_and_swap (ptr, tmp, tmp1);
}

The only thing supported on x86 are


[hjl@gnu-33 gcc]$ cat /tmp/y.c 
int
foo1 (int *p)
{
  return __sync_fetch_and_add (p, 7);
}

int
foo2 (int *p)
{
  return __sync_fetch_and_sub (p, 7);
}
[hjl@gnu-33 gcc]$ gcc -S -O2 /tmp/y.c
[hjl@gnu-33 gcc]$ cat y.s
    .file    "y.c"
    .text
    .p2align 4,,15
    .globl    foo1
    .type    foo1, @function
foo1:
.LFB0:
    .cfi_startproc
    movl    $7, %eax
    lock xaddl    %eax, (%rdi)
    ret
    .cfi_endproc
.LFE0:
    .size    foo1, .-foo1
    .p2align 4,,15
    .globl    foo2
    .type    foo2, @function
foo2:
.LFB1:
    .cfi_startproc
    movl    $-7, %eax
    lock xaddl    %eax, (%rdi)
    ret
    .cfi_endproc
.LFE1:
    .size    foo2, .-foo2
    .ident    "GCC: (GNU) 4.6.0 20110603 (Red Hat 4.6.0-10)"
    .section    .note.GNU-stack,"",@progbits
[hjl@gnu-33 gcc]$

Reply via email to