gokturk added a comment.
Let me try my best to explain what's happening. The goal of this check is to
determine whether passing `-latomic` is required.
Let's start with the code used by `check_working_cxx_atomics64`
(https://github.com/llvm/llvm-project/blob/master/llvm/cmake/modules/CheckAtomic.cmake)
#include
#include
std::atomic x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
return 0;
}
If we compile this with `g++ -o atomic64 -march=rv64imafd atomic64.cpp`, it
produces the following assembly output:
06bc :
6bc: fe010113addisp,sp,-32
6c0: 00113c23sd ra,24(sp)
6c4: 00813823sd s0,16(sp)
6c8: 02010413addis0,sp,32
6cc: fe042023sw zero,-32(s0)
6d0: fe042703lw a4,-32(s0)
6d4: 000107b7lui a5,0x10
6d8: fff78593addia1,a5,-1 #
<__global_pointer$+0xd7ff>
6dc: 00070513mv a0,a4
6e0: 04efjal ra,720
<_ZStanSt12memory_orderSt23__memory_order_modifier>
6e4: 00050793mv a5,a0
6e8: fef42223sw a5,-28(s0)
6ec: 2797auipc a5,0x2
6f0: 97478793addia5,a5,-1676 # 2060
6f4: 0ffffence
6f8: 0007b783ld a5,0(a5)
6fc: 0ffffence
700: 0013nop
704: fef43423sd a5,-24(s0)
708: 0793li a5,0
70c: 00078513mv a0,a5
710: 01813083ld ra,24(sp)
714: 01013403ld s0,16(sp)
718: 02010113addisp,sp,32
71c: 8067ret
0720 <_ZStanSt12memory_orderSt23__memory_order_modifier>:
720: fe010113addisp,sp,-32
724: 00813c23sd s0,24(sp)
728: 02010413addis0,sp,32
72c: 00050793mv a5,a0
730: 00058713mv a4,a1
734: fef42623sw a5,-20(s0)
738: 00070793mv a5,a4
73c: fef42423sw a5,-24(s0)
740: fec42703lw a4,-20(s0)
744: fe842783lw a5,-24(s0)
748: 00f777b3and a5,a4,a5
74c: 0007879bsext.w a5,a5
750: 0007879bsext.w a5,a5
754: 00078513mv a0,a5
758: 01813403ld s0,24(sp)
75c: 02010113addisp,sp,32
760: 8067ret
Ignoring the fine details of the RISC-V assembly, if we just focus on `jal`
instructions that are used for function calls, we see that no actual calls to
libatomic are being made. This may be a separate bug of a false-positive
`check_working_cxx_atomics64` test that is not addressed by this patch.
If we tweak the example a little bit to introduce a post-increment for `x`:
@@ -2,6 +2,7 @@
#include
std::atomic x (0);
int main() {
+ x++;
uint64_t i = x.load(std::memory_order_relaxed);
return 0;
}
the post-increment generates these extra instructions in `main()`:
lia1,0
auipc a0,0x2
addi a0,a0,-1648 # 2060
jal ra,774 <_ZNSt13__atomic_baseImEppEi>
where `_ZNSt13__atomic_baseImEppEi` is:
0774 <_ZNSt13__atomic_baseImEppEi>:
774: fc010113addisp,sp,-64
778: 02813c23sd s0,56(sp)
77c: 04010413addis0,sp,64
780: fca43423sd a0,-56(s0)
784: 00058793mv a5,a1
788: fcf42223sw a5,-60(s0)
78c: fc843783ld a5,-56(s0)
790: fef43023sd a5,-32(s0)
794: 00100793li a5,1
798: fef43423sd a5,-24(s0)
79c: 00500793li a5,5
7a0: fcf42e23sw a5,-36(s0)
7a4: fe043783ld a5,-32(s0)
7a8: fe843703ld a4,-24(s0)
7ac: 0f5ffence iorw,ow
7b0: 04e7b6afamoadd.d.aq a3,a4,(a5)
7b4: 0013nop
7b8: 00068793mv a5,a3
7bc: 00078513mv a0,a5
7c0: 03813403ld s0,56(sp)
7c4: 04010113addisp,sp,64
7c8: 8067ret
Again ignoring the fine details of RISC-V assembly, we see that the
post-increment is provided primarily by the instruction at address `0x7b0`,
which is `amoadd.d` and stands for **`a`**tomic **`m`**emory **`o`**peration
for a **`d`**ouble word. As a result, no calls to libatomic are generated.
If we further modify our example to use `uint8_t` instead of `uint64_t`:
@@ -1,8 +1,8 @@
#incl