<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Infinite loop in atomic function when built with -O0 on AArch64"
   href="https://llvm.org/bugs/show_bug.cgi?id=25611">25611</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Infinite loop in atomic function when built with -O0 on AArch64
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>FreeBSD
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: AArch64
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>andrew@fubar.geek.nz
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>When building the following with -O0 it generates code that may, on some
hardware, enter an infinite loop. This is because it is implementation defined
if any store will leave the local-monitor in exclusive mode or not.

int
test(int *ptr, int old_value, int new_value)
{
        return __sync_val_compare_and_swap(ptr, old_value, new_value);
}

When building with -O0 on clang trunk I get the following asm. This is broken
on ThunderX as the local monitor will leave exclusive-mode when it executes the
store at address 40 below.

0000000000000000 <test>:
   0:   d100c3ff        sub     sp, sp, #0x30
   4:   f90017e0        str     x0, [sp,#40]
   8:   b90027e1        str     w1, [sp,#36]
   c:   b90023e2        str     w2, [sp,#32]
  10:   f94017e0        ldr     x0, [sp,#40]
  14:   b94027e1        ldr     w1, [sp,#36]
  18:   b94023e2        ldr     w2, [sp,#32]
  1c:   f9000fe0        str     x0, [sp,#24]
  20:   b90017e1        str     w1, [sp,#20]
  24:   b90013e2        str     w2, [sp,#16]
  28:   f9400fe8        ldr     x8, [sp,#24]
  2c:   885ffd09        ldaxr   w9, [x8]             // Load-exclusive
  30:   2a0903e0        mov     w0, w9
  34:   2a0003e9        mov     w9, w0
  38:   b94017ea        ldr     w10, [sp,#20]
  3c:   6b0a013f        cmp     w9, w10
  40:   b9000fe9        str     w9, [sp,#12]         // Unrelated store
  44:   54000101        b.ne    64 <test+0x64>
  48:   b94013e8        ldr     w8, [sp,#16]
  4c:   2a0803e9        mov     w9, w8
  50:   2a0903e8        mov     w8, w9
  54:   f9400fe9        ldr     x9, [sp,#24]
  58:   880afd28        stlxr   w10, w8, [x9]        // Store-exclusive
  5c:   35fffe6a        cbnz    w10, 28 <test+0x28>
  60:   14000003        b       6c <test+0x6c>
  64:   d5033f5f        clrex
  68:   14000001        b       6c <test+0x6c>
  6c:   b9400fe0        ldr     w0, [sp,#12]
  70:   9100c3ff        add     sp, sp, #0x30
  74:   d65f03c0        ret

The following example will print a different value based on if WITH_STORE is
defined or not.

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
        uint32_t tmp, a, val, *pa;
        uint32_t b, *pb;
        int res;

        a = 1;
        val = 1;
        pa = &a;
        pb = malloc(sizeof(int));;
        __asm __volatile(
            "1: ldxr    %w0, [%2]      \n"
            "   add     %w0, %w0, %w3  \n"
#if WITH_STORE
            "   str     %w0, [%4]      \n"
#endif
            "   stxr    %w1, %w0, [%2] \n"
            : "=&r"(tmp), "=&r"(res) : "r" (pa), "r" (val), "r" (pb)
            : "cc", "memory"
        );
        printf("res = %x\n", res);
        printf("a = %u\n", a);

        return (0);
}

# clang atomic_test.c -DWITH_STORE
# ./a.out
res = 1
a = 1
# clang atomic_test.c
# ./a.out
res = 0
a = 2</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>