https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121213

            Bug ID: 121213
           Summary: Poor RV64 code generated for __atomic_exchange_n (llvm
                    seems to do it right)
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vincenzo.romano at gmail dot com
  Target Milestone: ---

>From -O0 to -O3 and -Os, the code generated by GCC for __atomic_exchange_n() is
rather poor under at least 2 points of view.

My C code is this:

    void test0(unsigned long* lock) {
      while (!__atomic_exchange_n(lock, 0, __ATOMIC_ACQUIRE));
    }


    void test1(unsigned* lock) {
      while (!__atomic_exchange_n(lock, 0, __ATOMIC_ACQUIRE));
    }

Produced code is this:

    test0:
    .L2:
      li a5,0
      amoswap.d.aq a5,a5,0(a0)
      beq a5,zero,.L2
      ret
    test1:
    .L5:
      li a5,0
      amoswap.w.aq a5,a5,0(a0)
      sext.w a5,a5
      beq a5,zero,.L5
      ret

(please, note the "reverse logic" used here: 0=locked 1=released)


1. It uses a5 register as the second argument to amoswap.d instead of zero

2. It adds a useless "sign extend" pseudo instruction for 32-bit word.

You can compare GCC vs CLANG results here:
https://godbolt.org/z/4dGc4Pc9f

Reply via email to