The same C11 atomics compile to three different RISC-V assembly outputs depending on the target ISA: baseline (RV64G), load-acquire/store-release (Zalasr), and Total Store Order (Ztso).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdatomic.h>

int load_acquire(_Atomic int *p) {
return atomic_load_explicit(p, memory_order_acquire);
}

void thread_load_fence(void) {
atomic_thread_fence(memory_order_acquire);
}

void store_release(_Atomic int *p, int v) {
atomic_store_explicit(p, v, memory_order_release);
}

void thread_store_fence(void) {
atomic_thread_fence(memory_order_release);
}

RVWMO (baseline, -march=rv64g)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
load_acquire:
lw a0,0(a0)
fence r,rw
ret
thread_load_fence:
fence r,rw
ret
store_release:
fence rw,w
sw a1,0(a0)
ret
thread_store_fence:
fence rw,w
ret

Zalasr (-march=rv64g_zalasr)

1
2
3
4
5
6
7
8
9
10
11
12
load_acquire:
lw.aq a0,0(a0)
ret
thread_load_fence:
fence r,rw
ret
store_release:
sw.rl a1,0(a0)
ret
thread_store_fence:
fence rw,w
ret

Ztso (-march=rv64g_ztso)

1
2
3
4
5
6
7
8
9
10
load_acquire:
lw a0,0(a0)
ret
thread_load_fence:
ret
store_release:
sw a1,0(a0)
ret
thread_store_fence:
ret