使用 _Atomic float

问题描述 投票:0回答:1

我有以下代码:

static _Atomic float testf;
void func() {
   testf=1.0f;
   float f=testf;
   printf("%f\n", f);
}

运行它会导致程序在 vcruntime_c11_atomic_support.h:417 处命中调试断言、内存顺序无效。 (MSVC 版本 19.37.32822.0)。

我不太熟悉 x64 调用约定,但看起来生成的程序集没有正确调用 _Atomic_store32 或 _Atomic_load32 之一:

inline void _Atomic_store32(volatile int* _Ptr, int _Desired, int _Order);
inline int _Atomic_load32(const volatile int* _Ptr, int _Order);
; 41   :     testf=1.0f;

    mov r8d, 5    ; !!This seems to be _Order, corresponding to _Atomic_memory_order_seq_cst
    movss   xmm1, DWORD PTR __real@3f800000
    lea rcx, OFFSET FLAT:testf
    call    _Atomic_store32   ; !!Where is EDX? That should contain _Desired.

; 42   :     float f=testf;

    movss   xmm1, DWORD PTR __real@40a00000
    lea rcx, OFFSET FLAT:testf
    call    _Atomic_load32    ; !!EDX should have _Order.
    movss   DWORD PTR f$[rsp], xmm0

MSVC 原子支持是否有问题,或者我做错了什么?

c visual-c++ c11 stdatomic compiler-bug
1个回答
1
投票

该 asm 输出看起来像是编译器错误。

这就像编译器想要调用

_Atomic_store32(void*, float)
,因为它在 XMM1 中传递第二个参数。但我认为这与它用于整数的函数相同,所以实际的 arg 需要位于 EDX 中。将其视为可变参数函数将适用于 Win x64 调用约定,因为这些函数需要将 XMM 参数复制到相应的整数寄存器。

对于加载,

movss   xmm1, DWORD PTR __real@40a00000
正在将具有位模式
0x40a00000
的浮点常量加载到第二个参数传递寄存器(对于FP参数)。该位模式代表
5.0f
,因此 MSVC 对某些事情感到非常困惑,对这些参数类型执行
_Atomic_load32(&testf, (float)memory_order_seq_cst)

发出这样的代码绝对是编译器错误的迹象。 (构建一个最小的测试用例并显示相关的汇编,这真是太好了。您可以将这个确切的示例提交给 MS 的编译器团队,他们很快就会看到错误的症状。)

© www.soinside.com 2019 - 2024. All rights reserved.