You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译器是否允许合并relaxed内存序的重复原子存储?为何未做该优化?

问题

以下代码:

#include <atomic>

std::atomic_bool b;

void store2() {
    b.store(true, std::memory_order::relaxed);
    b.store(true, std::memory_order::relaxed);
}

GCC、MSVC和Clang均生成如下两条mov指令:

store2():
  mov     BYTE PTR b[rip], 1
  mov     BYTE PTR b[rip], 1
  ret
b:
  .zero   1

是否允许将这两次原子存储合并为一条mov指令?我认为这不会违反std::memory_order::relaxed的限制,因为其他线程观察到的效果与单次存储一致。

若该操作是允许的,为何主流编译器不执行这一简单优化?


是否允许合并?

是,这种合并完全符合C++标准。对于std::memory_order::relaxed的原子操作,标准仅要求两点:

  • 同一线程内的操作遵循程序顺序(线程自身能感知代码的执行顺序)
  • 对同一原子对象的所有操作,存在全局一致的修改顺序(所有线程看到的对象修改序列统一)

两次存储相同值的relaxed原子操作合并后,完全满足上述约束:其他线程观察到的对象状态变化和原代码完全一致,既不会破坏线程内的程序顺序,也不会打破修改顺序的一致性。

为什么主流编译器不做这个优化?

主要有以下几个原因:

  1. 优化性价比极低:这种连续存储相同值的relaxed原子操作在实际代码中出现频率极低,编译器团队会优先投入资源到收益更大的常见优化(比如循环展开、死代码消除、函数内联等)。
  2. 原子操作的优化约束:编译器对原子操作的优化有严格的安全限制,要实现这种合并,需要额外开发逻辑检测“连续存储相同值的relaxed原子操作”,会增加编译器的复杂度,还容易引入语义bug。
  3. 硬件已兜底优化:在x86等主流架构下,现代CPU会在执行阶段自动合并这类冗余存储,两次mov的实际执行开销和单次存储几乎无区别,编译器无需额外处理。
  4. 调试与可预测性:保留原始操作序列,能让开发者在调试时直观看到代码的原始意图,符合编译器“尽量保留用户代码行为可见性”的设计原则。

内容的提问来源于stack exchange,提问作者Jan Schultke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:40:03