所有正式尊重依赖关系的CPU是否都允许独立依赖关系?

时间:2019-05-25 12:16:12

标签: c++ dependencies cpu-architecture cpu-cache stdatomic

问题的上下文是普通的高速缓存内存,例如C和C ++对象的内存。

许多CPU会不按顺序执行内存加载(这样做的好处是不会在缓存未命中时完全停止正在执行的线程),并且以后不检查是否有另一个内核没有要求更改它们的权限(*),因此在程序顺序中稍后出现的read早早已被有效地检索,并且另一个线程可能已在该间隔中取得了进展,这意味着在这两个与程序顺序一致的线程之间不可能就内存操作的顺序达成共识。

(*)通过要求本地缓存使包含它的缓存行无效,这是在可以支持常规线程编程的任何体系结构中更改值之前的先决条件。

许多允许该行为的CPU类型还保证,当值取决于先前加载的结果时,所有与该值相关的后续操作实际上会在加载之后发生,尤其是在从该值派生的地址处进行加载值。

但是可以知道,从另一个派生的值在数学上与参数无关。实际上,将寄存器设置为零的常见习惯是将其值与自身进行异或运算,这从语法上从前一个取值,而从语义上则不是。

所有跟踪值依赖关系的CPU是否保证基于基于先前加载的值的内存操作允许这种非语义依赖关系创建独立依赖关系以便对内存操作进行排序?这是否适用于按位运算或所有算术运算,包括但不限于使用吸收元素?

最明显的例子是:

  • x ^ x
  • x & 0
  • x | -1
  • x - x
  • x * 0
  • x / x(如果为零,则引发异常)

这个问题的目的显然是要理解编译器如何按照该功能的意图以最佳方式在这些体系结构上以C和C ++支持memory_order_consume(而不是通过将mo_consume定义为mo_acquire)。

问题陈述

问题是诸如

之类的代码的编译
r1 = x.load(memory_order_consume);
r2 = y | (r1&0);
r3 = z + (r1-r1);
r4 = (&E)[r1*0];

在中间代码中重命名r1并使之“易失性注册”(类似于易失性,不可优化,除非在寄存器中)的简单策略会产生正确的“消耗”(取决于值/地址的负载)每个操作的行为。

奖金问题

是否有任何CPU直接支持相关常数?这是一条“立即设置值”指令,它引入了常量与寄存器值的显式依赖关系:

load.i.dep r1,8,r4 ; sets r1 to 8 but dependency on value of r4 is respected
lea r0,r0,r1       ; r0 += r1, r0 depends on r4
load.w r2,r1       ; loads one word at r1 to r2 only after r4 is known

0 个答案:

没有答案