【发布时间】:2014-02-18 20:10:49
【问题描述】:
在对某些东西进行基准测试时,我测得的吞吐量比我计算的要低得多,我将其范围缩小到 LZCNT 指令(TZCNT 也会发生这种情况),如以下基准所示:
xor ecx, ecx
_benchloop:
lzcnt eax, edx
add ecx, 1
jnz _benchloop
还有:
xor ecx, ecx
_benchloop:
xor eax, eax ; this shouldn't help, but it does
lzcnt eax, edx
add ecx, 1
jnz _benchloop
第二个版本要快得多。不应该。 LZCNT 没有理由对其输出具有输入依赖性。与 BSR/BSF 不同,xZCNT 指令总是覆盖它们的输出。
我在 4770K 上运行它,所以 LZCNT 和 TZCNT 没有作为 BSR/BSF 执行。
这是怎么回事?
【问题讨论】:
-
也许
lzcnt不能被推测执行(它更新 CF、ZF)在jnz(ZF != 0) 之后。而xor打破了依赖链?但是由于add无论如何都会淘汰以前的标志,如果是这种情况,我不会。 -
只是为了确定:你能排除这是一个代码对齐问题,与lzcnt无关吗?
-
@PhiS 使用 3 字节
nop而不是xor eax, eax让它再次变慢 -
gcc 4.9.2 中添加了“xor”解决方法:gcc.gnu.org/PR62011
-
供未来访问者参考,这只是微架构勘误表(本质上是一个错误)。
LZCNT没有理由对其输出具有输入依赖性,但确实如此。POPCNT指令也有同样的bug,详见here。
标签: performance assembly x86 cpu-architecture micro-optimization