gpt4 book ai didi

c++ - 为什么 GCC 在 Clang 不使用它的地方插入 mfence?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:33:12 27 4
gpt4 key购买 nike

为什么 GCC 和 Clang 会为此代码 (x86_64, -O3 -std=c++17) 生成如此不同的 asm?

#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);
}

海湾合作委员会 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 生成的代码在某些情况下会导致错误?

最佳答案

更现实example :

#include <atomic>

std::atomic<int> a;

void foo_seq_cst(int b) {
a = b;
}

void foo_relaxed(int b) {
a.store(b, std::memory_order_relaxed);
}

gcc-9.1:

foo_seq_cst(int):
mov DWORD PTR a[rip], edi
mfence
ret
foo_relaxed(int):
mov DWORD PTR a[rip], edi
ret

clang-8.0:

foo_seq_cst(int):                       # @foo_seq_cst(int)
xchg dword ptr [rip + a], edi
ret
foo_relaxed(int): # @foo_relaxed(int)
mov dword ptr [rip + a], edi
ret

gcc 使用 mfence,而 clang 使用 xchg 作为 std::memory_order_seq_cst

xchg 表示 lock 前缀。 lockmfence都满足std::memory_order_seq_cst的要求,即无重排序和全序。

来自 Intel 64 和 IA-32 架构软件开发人员手册:

MFENCE—Memory Fence

Performs a serializing operation on all load-from-memory and store-to-memory instructions that were issued prior the MFENCE instruction. This serializing operation guarantees that every load and store instruction that precedes the MFENCE instruction in program order becomes globally visible before any load or store instruction that follows the MFENCE instruction. The MFENCE instruction is ordered with respect to all load and store instructions, other MFENCE instructions, any LFENCE and SFENCE instructions, and any serializing instructions (such as the CPUID instruction). MFENCE does not serialize the instruction stream.

8.2.3.8 Locked Instructions Have a Total Order

The memory-ordering model ensures that all processors agree on a single execution order of all locked instructions, including those that are larger than 8 bytes or are not naturally aligned.

8.2.3.9 Loads and Stores Are Not Reordered with Locked Instructions

The memory-ordering model prevents loads and stores from being reordered with locked instructions that execute earlier or later.

lock was benchmarked to be 2-3x faster than mfence在可能的情况下,Linux 从 mfence 切换到 lock

关于c++ - 为什么 GCC 在 Clang 不使用它的地方插入 mfence?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56205324/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com