【发布时间】:2019-10-05 21:39:20
【问题描述】:
为什么 GCC 和 Clang 会为此代码生成如此不同的 asm(x86_64,-O3 -std=c++17)?
#include <atomic>
int global_var = 0;
int foo_seq_cst(int a)
{
std::atomic<int> ia;
ia.store(global_var + a, std::memory_order_seq_cst);
return ia.load(std::memory_order_seq_cst);
}
int foo_relaxed(int a)
{
std::atomic<int> ia;
ia.store(global_var + a, std::memory_order_relaxed);
return ia.load(std::memory_order_relaxed);
}
GCC 9.1:
foo_seq_cst(int):
add edi, DWORD PTR global_var[rip]
mov DWORD PTR [rsp-4], edi
mfence
mov eax, DWORD PTR [rsp-4]
ret
foo_relaxed(int):
add edi, DWORD PTR global_var[rip]
mov DWORD PTR [rsp-4], edi
mov eax, DWORD PTR [rsp-4]
ret
Clang 8.0:
foo_seq_cst(int): # @foo_seq_cst(int)
mov eax, edi
add eax, dword ptr [rip + global_var]
ret
foo_relaxed(int): # @foo_relaxed(int)
mov eax, edi
add eax, dword ptr [rip + global_var]
ret
我怀疑这里的 mfence 有点矫枉过正,对吗?还是 Clang 生成的代码在某些情况下会导致错误?
【问题讨论】:
-
看起来,由于 atomic 是一个局部变量,clang 认识到只有一个线程可以访问它并完全避免为 atomic 生成代码。
-
所以GCC没有优化好mfence可以扔掉?
-
GCC 没有在核心语言级别获得原子,它们被视为库函数调用,想想
printf,从未删除。 Clang 生成预期的代码。 -
也许如果你能解释为什么你想要一个无意义的伪释放操作来产生一个栅栏,我们就可以解释为什么直觉是不正确的。向全世界发布你已经完成某事的拍摄,并设置了一面旗帜来说明这一点。你在向谁开枪,你在设置什么旗帜?
标签: c++ multithreading gcc clang atomic