x86_64 - 汇编 - 循环条件和乱序

时间:2015-08-02 11:38:30

标签: loops assembly conditional-statements x86-64

要求基准。

如果是这种情况,我会自己做的。

我的问题:

为方便起见,我倾向于避免间接/索引寻址模式。

作为替代,我经常使用立即,绝对或寄存器寻址。

代码:

; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
    ... ;do whatever with %esi
    add $4, %esi
    dec %ecx
    jnz 0x98767;

这里,我们有一个序列化的组合(dec和jnz),它可以防止正常的乱序执行(依赖)。

有没有办法避免/破坏dep? (我不是装配专家)。

1 个答案:

答案 0 :(得分:8)

在针对Intel CPU进行优化时,始终将标志设置指令放在条件跳转指令之前(如果它是下表中列出的简单指令之一),这样它们就可以在解码器中宏熔合成一个uop。

对于不进行宏融合的旧CPU,这样做并没有明显更糟。提前设置标志可以通过让更快地检测到错误预测来将这种CPU的分支误预测惩罚缩短一个。我没有基准测试,但我不认为日益稀少的CPU的小缺点证明错过了进行融合的CPU的前端吞吐量优势(解码和问题)。总的uop吞吐量通常可能成为瓶颈。

AMD推土机/打桩机/压路机可以test/cmp与任何jcc融合,但只能test/cmp,而不是任何其他ALU指令。所以肯定把它与分支比较。

来自Agner Fog's微型指南,表9.2(适用于Sandybridge / Ivybridge):

First       | can pair with these  |  cannot pair with
instruction | (and the inverse)    |
---------------------------------------------
cmp         |jz, jc, jb, ja, jl, jg|   js, jp, jo
add, sub    |jz, jc, jb, ja, jl, jg|   js, jp, jo
adc, sbb    |none                  |
inc, dec    |jz, jl, jg            |   jc, jb, ja, js, jp, jo
test        | all                  |
and         | all                  |
or, xor, not, neg | none           |
shift, rotate     | none           |

Table 9.2. Instruction fusion

基本上,inc/dec可以与jcc进行宏融合,只要条件仅取决于由inc/dec修改的位。

(否则,它们不会进行宏融合,并且你会插入一个额外的uop来合并标志(就像你在写eax之后阅读al一样)。或者在早期的CPU上,部分旗帜失速。)

Core2 / Nehalem在宏观融合能力方面受到更多限制(仅适用于具有更多有限JCC组合的CMP / TEST),Core2无法在64位模式下进行宏观融合。

如果您还没有,请阅读Agner Fog优化的asm和C指南。他们充满了必要的知识。