Why `compare_exchange_weak` generates loop on RISC-V?

โš“ rust    ๐Ÿ“… 2025-05-26    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 3      

surdeus

Warning

This post was published 34 days ago. The information described in this article may have changed.

Let's take a look at this snippet:

pub fn cmpx(a0: &AtomicU32, a1: u32, a2: u32) -> bool {
    a0.compare_exchange_weak(a1, a2, AcqRel, Relaxed).is_ok()
}

We get the following RISC-V assembly for it:

cmpx:
.LBB0_1:
        lr.w.aq a3, (a0)
        bne     a3, a1, .LBB0_3
        sc.w.rl a4, a2, (a0)
        bnez    a4, .LBB0_1
.LBB0_3:
        xor     a1, a1, a3
        seqz    a0, a1
        ret

compare_exchange_weak explicitly allows spurious failures. Its raison d'รชtre is to allow for efficient codegen on targets with LL/SC instructions. But in the snippet we see that the compiler has generated retry loop on failed conditional stores (the bnez a4, .LBB0_1 instruction), which goes against my expectations. In other words, we get the same assembly regardless whether compare_exchange_weak or compare_exchange was used!

Is there a reason for this behavior or is it just a sub-optimal codegen by LLVM?

3 posts - 2 participants

Read full topic

๐Ÿท๏ธ rust_feed