x64支持是否暗示BMI1支持?

问题描述 投票:0回答:1

可以安全地假设x64构建可以使用TZCNT而不通过cpu标志检查其支持吗?

assembly x86-64 instruction-set bmi
1个回答
0
投票

不,当然不是! x86-64是2003年底的新产品(AMD K8),仅具有传统的bsfbsr位扫描指令,而BMI1的其余部分均没有。

[2013年,第一个支持BMI1的Intel CPU是Haswell。(还引入了BMI2。)2012年,第一个支持BMI1的AMD CPU是PILEDRIVER。在K10和更高版本的AMD CPU中,AMD ABM (Advanced Bit Manipulation)仅添加了popcntlzcnt,没有添加tzcnt

维基百科Bit Manipulation Instruction Sets: Supporting CPUs


由于您特别提到了tzcnt,因此其机器代码编码为rep bsf,因此较旧的CPU将把它作为BSF执行。如果输入为非零,则产生与tzcnt相同的结果。即[tzcnt在输入非零时在所有x86 CPU上运行(自386起)。

但是当它为零时,tzcnt将产生操作数大小(例如64),但是tzcnt保留目标寄存器不变。 bsf根据结果设置FLAGS,bsf根据输入设置。 AMD在其ISA参考手册中记录了未经修改的行为。英特尔仅将其记录为“未定义的值”,但至少在现有CPU中实现了与AMD相同的行为。

(这就是tzcnt / bsf对所有CPU都具有输出依赖性的原因。不幸的是bsf / bsr对Skylake之前的Intel Sandybridge系列也有虚假的依赖性:tzcnt。为什么[C0 ]在Ice Lake之前对SnB系列进行操作,因为lzcnt。)


[Why does breaking the "output dependency" of LZCNT matter?在AMD上明显更快,因此针对“通用”或AMD CPU进行调整的编译器通常会使用popcnt而不是it shares the same execution unit而不检查CPU功能。

例如对于GNU C tzcnt。该内在函数对于input = 0具有未定义的行为,因此允许它仅使用tzcnt而不检查0。因此,由于在任何情况下都不保证结果,因此也允许使用bsf

__builtin_ctz

bsf不存在这种向后/向前兼容。将其解码为tzcnt,而忽略无意义的Why does TZCNT work for my Sandy Bridge processor?前缀,则会得到lzcnt,即位索引。 rep bsr

一个方便的技巧是rep,因为OR很便宜(至少对于32位常量而言),并且保证31 - lzcnt(x)总是有一个非零的位可以找到。但不会更改任何非零https://fgiesen.wordpress.com/2013/10/18/bit-scanning-equivalencies/的结果,因为它是ctz( x | 0x80000000 )的最后一位。对于bsf / x,这是一个更好的技巧。

© www.soinside.com 2019 - 2024. All rights reserved.