是否允许此编译器转换?

Is this compiler transformation allowed?

考虑这段代码,其中 xy 是整数:

if (x)
    y = 42;

是否允许以下​​编译器转换?

int tmp = y;
y = 42;

if (!x)
    y = tmp;

上下文:

这是来自 Bjarne Stroustrup 的常见问题解答:

// start with x==0 and y==0

if (x) y = 1;   // Thread 1 

if (y) x = 1;   // Thread 2

常见问题解答指出这是免费的数据竞争; xy 都是 0,应该写入变量的 none。
但是如果允许转换呢?

与我在错误评论中写的不同,如果 y 可能在线程之间共享并且编译器无法证明原始代码中存在任何现有 UB,则实际上不允许进行此转换。

标准明确表示:

Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this standard, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race.

[intro.multithread] N3337 中的 (1.10/22),N4141 中的 (1.10/25)。

因此,如果 x 始终为 0,则原始代码将是无竞争的,而转换后的代码则不会。因此转换是不合法的。

如果是,那么您将无法排除对可从全局变量或其他变量访问的任何对象的访问。编译器甚至可以在进行间接调用时试探性地调用从未调用过的函数,然后 "cancel" 通过恢复原始值来实现它们的效果。

沿着这条 opti-pessimisation 路径,它可以提前除以零,然后 "ignore" 如果除数为零,则结果,即使这是一个陷阱并且程序已停止。

这显然是荒谬的,无论标准是否如此,都必须拒绝。