# Why \`compare\_exchange\_weak\` generates loop on RISC-V?

**URL:** <https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996>\
**Category:** help\
**Created:** [May 26, 2025, 12:05pm UTC](https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996 "2025-05-26T12:05:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![newpavlov](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/newpavlov/32/6207_2.png) [@newpavlov](https://users.rust-lang.org/u/newpavlov)\
**Post date:** [May 26, 2025, 12:05pm UTC](https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996/1 "2025-05-26T12:05:46Z")

</div>

Let's take a look at this [snippet](https://rust.godbolt.org/z/KPMsnaEjc):

```rust
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:

```asm
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](https://en.wikipedia.org/wiki/Load-link/store-conditional) 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?

---

<div class="post-metadata">

**Author:** ![nerditation](https://avatars.discourse-cdn.com/v4/letter/n/e79b87/32.png) [@nerditation](https://users.rust-lang.org/u/nerditation)\
**Post date:** [May 26, 2025, 12:27pm UTC](https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996/2 "2025-05-26T12:27:40Z")

</div>

> [@newpavlov](#):
>
> or is it just a sub-optimal codegen by LLVM?

either this, or some arcane llvm codegen options are missing.

for the record, the `compare_exchange_weak()` is lowering to a single llvm operation:

```llvm
; 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
}

```

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/newpavlov/32/6207_2.png) [@newpavlov](https://users.rust-lang.org/u/newpavlov)\
**Post date:** [May 26, 2025, 12:32pm UTC](https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996/3 "2025-05-26T12:32:46Z")

</div>

The `cmpxchg weak` part looks like a pretty explicit way to convey our intent to LLVM. I guess I will create an LLVM issue for this.

UPD: LLVM issue: [`cmpxchg weak` generates re-try loop on RISC-V · Issue #141488 · llvm/llvm-project · GitHub](https://github.com/llvm/llvm-project/issues/141488)

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [August 24, 2025, 12:33pm UTC](https://users.rust-lang.org/t/why-compare-exchange-weak-generates-loop-on-risc-v/129996/4 "2025-08-24T12:33:38Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
