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

--- Comment #3 from H.J. Lu <hjl.tools at gmail dot com> 2011-09-30 18:37:42 
UTC ---
The same problem with

`TYPE __sync_add_and_fetch (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_sub_and_fetch (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_or_and_fetch (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_and_and_fetch (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_xor_and_fetch (TYPE *ptr, TYPE value, ...)'
`TYPE __sync_nand_and_fetch (TYPE *ptr, TYPE value, ...)'
     These builtins perform the operation suggested by the name, and
     return the new value.  That is,

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

[hjl@gnu-33 pr50583]$ cat z.i
int
foo (int *p)
{
  return __sync_and_and_fetch (p, 7);
}
[hjl@gnu-33 pr50583]$ gcc -O2 -S z.i
[hjl@gnu-33 pr50583]$ cat z.s
    .file    "z.i"
    .text
    .p2align 4,,15
    .globl    foo
    .type    foo, @function
foo:
.LFB0:
    .cfi_startproc
    movl    (%rdi), %eax
.L2:
    movl    %eax, %edx
    andl    $7, %edx
    lock cmpxchgl    %edx, (%rdi)
    jne    .L2
    movl    %edx, %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 pr50583]$ 

It is

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

If *ptr is changed between load and cmpxchg, we get an infinite loop.

Reply via email to