Skip to content

cmpxchg weak generates re-try loop on RISC-V #141488

Closed
@newpavlov

Description

@newpavlov

I have the following Rust code (godbolt):

use core::sync::atomic::{AtomicU32, Ordering::{AcqRel, Relaxed}};

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

It lowers to the following LLVM IR:

; Function Attrs: mustprogress nofree norecurse nounwind nonlazybind willreturn memory(argmem: readwrite) uwtable
define noundef zeroext i1 @cmpx(ptr nocapture noundef nonnull align 4 %a0, i32 noundef %a1, i32 noundef %a2) unnamed_addr #0 {
start:
  %0 = cmpxchg weak ptr %a0, i32 %a1, i32 %a2 acq_rel monotonic, align 4
  %1 = extractvalue { i32, i1 } %0, 1
  ret i1 %1
}

Which in turn gets compiled to the following RISC-V assembly:

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

We can see that LLVM has generated re-try loop despite the fact that weak compare exchange explicitly allows spurious failures (after all, it's the reason why it was introduced). It means that replacing compare_exchange_weak with compare_exchange results in the same assembly, thus rendering the "weak" variant effectively useless!

Potentially relevant issue: #37521

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend:RISC-VquestionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions