Kro*_*oma 4 assembly loops x86-64 conditional-statements
(如果是这样的话,我会自己做的.)
我的问题:
为方便起见,我倾向于避免间接/索引寻址模式.
作为替代,我经常使用立即,绝对或寄存器寻址.
代码:
; %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;
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个序列化的组合(dec和jnz),它可以防止正常的乱序执行(依赖).
有没有办法避免/破坏dep?(我不是装配专家).
在针对Intel CPU进行优化时,请始终将标志设置指令放在条件跳转指令之前(如果它是下表中列出的简单指令之一),这样它们就可以在解码器中进行宏熔合.
对于不进行宏融合的旧CPU来说,这样做并没有明显更糟.提前设置标志可以通过让更快地检测到错误预测来将这种CPU的分支误预测惩罚缩短一个.我没有基准测试,但我不认为日益稀少的CPU的小缺点证明错过了进行融合的CPU的前端吞吐量优势(解码和问题).总的uop吞吐量通常可能成为瓶颈.
AMD Bulldozer/Piledriver/Steamroller可以test/cmp与任何jcc,但test/cmp不是任何其他ALU指令融合.所以肯定把分支比较.
来自Agner Fog的微型指南,表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
Run Code Online (Sandbox Code Playgroud)
所以基本上,只要条件只依赖于被修改的位,inc/dec就可以宏熔合.jccinc/dec
(否则,它们不会进行宏融合,并且你会得到一个额外的uop来合并标志(就像你eax写完后读的那样al).或者在早期的CPU上,部分标志停止.)
Core2/Nehalem在宏观融合能力方面受到更多限制(仅适用于具有更多有限JCC组合的CMP/TEST),而Core2根本无法在64位模式下进行宏观融合.
如果您还没有,请阅读Agner Fog优化的asm和C指南.他们充满了基本知识.