Loops x86_64-程序集-循环条件和故障 我不是在要求一个基准。
(如果是这样的话,我会自己做的。)Loops x86_64-程序集-循环条件和故障 我不是在要求一个基准。,loops,assembly,conditional-statements,x86-64,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 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?(我不是汇编专家)。为英特尔CPU进行优化时,始终将标志设置指令放在条件跳转指令之前(如果它是下表中列出的简单指令之一),以便它们可以在解码器中宏融合到一个uop中 对于不进行宏融合的旧CPU来说,这样做并没有明显的问题。较早地设置标志可能会将此类CPU的分支预测失误惩罚缩短1,但无序执行意味着较早地移动
dec
两条指令不会产生真正的区别。另见。为了真正发挥作用,您可以展开循环和/或在可以更简单地计算的对象上执行分支,理想情况下不依赖于缓慢的输入,因此OoO exec可以在处理循环体的较旧迭代时解决分支。i、 e.回路计数器dep链可以在主工作之前运行
我没有基准测试,但我不认为越来越少的CPU的一个小缺点可以证明错过了进行融合的CPU的前端吞吐量优势(解码和发布)。uop总吞吐量通常是一个瓶颈
AMD推土机/打桩机/蒸汽压路机可以将test/cmp
与任何jcc
进行融合,但只能将test/cmp
与任何其他ALU指令进行融合。因此,与分支机构相比,放在这里是绝对正确的。如果英特尔CPU能够在sandybridge系列上进行宏融合,那么将其他东西与分支放在一起仍然是很有价值的
来自Microach指南,表9.2(适用于Sandybridge/Ivybridge):
因此,基本上,inc/dec
可以与jcc
进行宏融合,只要条件仅取决于由inc/dec
修改的位
(否则,它们不会进行宏融合,您会插入一个额外的uop来合并标志(比如在写入al
后读取eax
),或者在早期的CPU上,部分标志会暂停。)
Core2/Nehalem的宏融合能力更有限(仅用于CMP/测试,JCC组合更有限),Core2根本无法在64位模式下进行宏融合
如果您还没有阅读Agner Fog的优化asm和C指南,也可以阅读。它们充满了必要的知识。让我直截了当地说:你想要一个条件跳转,它取决于上一条指令的结果,可以按照该指令的顺序执行吗?我认为这在逻辑上是不可能的。另外请注意,不建议使用
dec
,因为它会导致部分标志更新暂停。@Jester:那么我应该使用sub?您可以使用lea4(%esi),%esi
进行添加,而这不会影响标志,因此您可以在更高的位置插入subl$1,%ecx
。正如@davmac所说,除非你使用循环
指令,否则你无法摆脱依赖性,这也是不推荐的。如果可能的话,一定要展开循环,以分摊循环开销的成本。非常感谢Peter,我已经从他那里得到了“指令表”和“优化汇编”。虽然我没有完全阅读后者(因此我无知),但我现在就去读。谢谢彼得:)@Kroma:这张表来自microarchitecture.pdf。我忘了他是否在《优化asm指南》中提到过宏融合,但可能至少提到了它。可能值得一提的是,第一条指令和第二条指令必须在同一个16字节的解码段中才能工作(具有相同的地址,四舍五入到16字节)。想想Agner Fog在什么地方提到过这个。@Noah:首先,解码组并不总是对齐的。第二,Sandybridge系列保留组中的最后一条指令(如果它是融合候选指令),以防下一组中的第一条指令是分支。(因此,它牺牲了一些传统的解码吞吐量,以构建更紧凑的uop缓存线,并可能最大限度地减少ROB空间和其他后端资源消耗)。我想这已经在某个地方讨论过了,但没有具体的想法。不过,你可能会在谷歌上找到一些东西。
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