在一般情况下,可以占用内存或寄存器操作数的指令怎么会比内存操作数更慢,然后是 mov + mov -> 指令 -> mov + mov
根据在Agner Fog 的指令表中找到的吞吐量和延迟(在我的案例中查看 Skylake,p238),我看到btr/bts
指令的以下数字:
instruction, operands, uops fused domain, uops unfused domain, latency, throughput
mov r,r 1 1 0-1 .25
mov m,r 1 2 2 1
mov r,m 1 1 2 .5
...
bts/btr r,r 1 1 N/A .5
bts/btr m,r 10 10 N/A 5
我看不出这些数字怎么可能是正确的。即使在最坏的情况下没有可用的寄存器并且您将一个存储在临时内存位置,它会更快:
## hypothetical worst-case microcode that saves/restores a scratch register
mov m,r // + 1 throughput , save a register
mov r,m // + .5 throughput , load BTS destination operand
bts r,r // + 1 throughput , do bts (or btr)
mov m,r // + 1 throughput , store result
mov r,m // + .5 throughput , restore register
bts m,r
在最坏的情况下,这比(4 < 5)具有更好的吞吐量。(编者注:当它们有不同的瓶颈时,将吞吐量相加是行不通的。您需要考虑 uops 和端口;这个序列应该是 2c 吞吐量,瓶颈是 1/clock 存储吞吐量。)
并且微码指令有自己的一组寄存器,因此看起来不太可能实际需要。任何人都可以解释为什么bts
(或通常任何指令)可以比使用最坏情况移动策略具有更高的内存吞吐量,寄存器操作数。
(编者注:是的,微码可以使用一些隐藏的临时寄存器。类似的东西add [mem], reg
至少在逻辑上只是加载到其中一个然后存储结果。)