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