编译器是否可以优化两个原子负载?

Can and does the compiler optimize out two atomic loads?

在这种情况下,两个负载会合二为一吗? 如果这取决于体系结构,那么来自英特尔的现代处理器会是什么情况?我相信原子负载相当于英特尔处理器中的正常负载。

void run1() {
    auto a = atomic_var.load(std::memory_order_relaxed);
    auto b = atomic_var.load(std::memory_order_relaxed);
   // Some code using a and b;
}

void run2() {
    if (atomic_var.load(std::memory_order_relaxed) == 2 && /*some conditions*/ ...) {
         if (atomic_var.load(std::memory_order_relaxed) * somevar > 3) {
               /*...*/
         }
    }
}

run1()run2() 只是使用同一原子变量的两次加载的两种情况。编译器能否将这种两载的场景合并为一载重用?

GCC (6.3) 和 Clang (3.9) 目前都没有将两个负载优化为一个。

唯一知道的方法是查看生成的程序集:https://godbolt.org/g/nZ3Ekm

编译器可以优化掉原子负载吗?

您对 run1() 的实现可以安全地优化为

void run1() {
    auto a = atomic_var.load(std::memory_order_relaxed);
    auto b = a;
   // Some code using a and b;
}

在原始程序中,每次调用 run1() 时,这两个负载可能在 atomic_var 上的总访问顺序中彼此相邻。在那种情况下,相邻的 load() 操作会 return 相同的结果。

由于不能排除这种可能性,允许编译器优化掉第二种load()。这可以用于任何内存顺序参数,而不仅仅是用于松散的原子。

对于 run2() 这取决于。您没有指定 /*some conditions*/。如果有什么东西可能会对原子变量产生可见的副作用(比如不透明的函数调用或访问 volatile 变量等),那么就无法将其优化掉。否则它可能是可能的。

编译器是否优化了两个原子加载?

取决于您的编译器。并且可能取决于您传入的编译器选项。可能取决于您的平台。关于编译器是否应该优化原子的争论正在进行中。该主题以 N4455 No Sane Compiler Would Optimize Atomics and this video 开头。

GCC 和 clang 目前并未将两个 load() 操作优化为一个。