为什么逻辑"与/或"的左操作数不携带对父求值的依赖项

Why do left operands of logical AND/OR not carry dependency to the parent evaluation?

本文关键字:quot 依赖 操作数 为什么      更新时间:2024-05-24

根据C++标准:

如果-A的值用作B的操作数,则求值A对求值B具有依赖关系,除非:

--B是对std::kill_dependency(29.3(或的任何专门化的调用

--A是内置逻辑AND(&&,请参见5.14(或逻辑or(||,请参见5.15(运算符或的左操作数

--A是条件(?:,见5.16(运算符或的左操作数

--A是内置逗号(,(运算符(5.18(的左操作数;(…(

我可以理解为什么在关系之前排序的依赖关系会在kill_dependency调用时停止,但为什么逻辑AND、OR、逗号等运算符也会破坏依赖链?

这是否意味着下面的代码有未定义的行为?

//thread1
int y = 2
atomicVal.store(true);
//thread2 
auto x = atomicVal.load(std::memory_order_consume);
cout << x && y;

memory_order_consume试图公开一个用于C++的asm级CPU功能。(它暂时被弃用,直到它可以被重新设计成编译器可以在实践中实现的东西,并且在源代码中不需要太多kill_dependency噪声(。理解CPU的行为是理解设计用来公开它的C++程序的关键

这一切都是关于数据依赖关系,而不是像条件分支那样的控制依赖关系。C++11:memory_order_relaxed和memory_order_sume之间的区别以及[[carries_dependency]]它的含义和如何实现有更多的细节。

例如,add x2, x2, x3指令在其两个输入寄存器都准备好之前不能执行,ldr w1, [x2]也不能在地址准备好之前执行加载,所以如果x2来自另一个加载,它会自动在这个加载之前排序。(假设CPU硬件的设计不会违反因果关系,例如,在极少数情况下,通过进行值预测或DEC Alpha所做的任何事情来违反因果关系(。但是cbz w1, reg_was_zero是可以预测的,所以让reg_was_zero: ldr w3, [x4]等待产生w1的负载是不够的。(这是AArch64 asm,BTW,一种保证依赖排序的弱排序ISA。(

||left && right的短路评估在逻辑上与if(left) right相同,因此即使左侧尚未执行,分支预测+推测执行也可以预期在右侧运行没有数据依赖,只有控制依赖

很明显,逗号left, right根本不会在两边之间建立任何连接,它基本上是将left; right;塞进一个表达式中的一种方式。

当然,如果在左侧和右侧都使用相同的变量,则数据依赖项可以以这种方式存在,但它不是由运算符创建的。