Assembly AVX支持是否意味着BMI1支持?
我有一些依赖AVX的代码。Assembly AVX支持是否意味着BMI1支持?,assembly,x86,64-bit,avx,bmi,Assembly,X86,64 Bit,Avx,Bmi,我有一些依赖AVX的代码。 在相同的代码库中,我还使用了TZCNT 后者是BMI1的一部分。我知道我可以使用CPUID测试这个指令,但我很懒,所以我没有真正实现它 为了测试支持,我只需执行一条AVX指令。如果我得到#UD未定义指令异常,我知道CPU不支持AVX。 但是tzcnt与bsf(或bsr-我总是忘记哪个是哪个),因此不会触发异常 如果我有AVX支持,这是否意味着BMI1支持? 作为记录,我现在测试的CPU上没有AVX2 否,AVX支持并不意味着BMI1支持 详见下表:
在相同的代码库中,我还使用了
TZCNT
后者是BMI1的一部分。我知道我可以使用CPUID测试这个指令,但我很懒,所以我没有真正实现它 为了测试支持,我只需执行一条AVX指令。如果我得到
#UD
未定义指令异常,我知道CPU不支持AVX。但是
tzcnt
与bsf
(或bsr
-我总是忘记哪个是哪个),因此不会触发异常
如果我有AVX
支持,这是否意味着BMI1
支持?作为记录,我现在测试的CPU上没有AVX2 否,AVX支持并不意味着BMI1支持 详见下表:
Intel AMD Year
---------------------------------------------------
AVX Sandy Bridge Bulldozer 2011
---------------------------------------------------
BMI1 Haswell Piledriver/Jaguar 2013
---------------------------------------------------
ABM Barcelona 2007
Haswell 2013
---------------------------------------------------
AVX2 Haswell 2013
Carrizo 2015
Ryzen 2017
---------------------------------------------------
BMI2 Haswell 2013
Excavator 2015
Ryzen 2017
大多数处理器都支持两者,但AVX比BMI1早两年。除此之外,
tzcnt
和bsf
对于标志具有不同的语义。如果要强制执行
#UD
异常,可以使用
资料来源:维基百科:
如果要使用CPUID:
BMI1 -> CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]
(ANDN, BEXTR, BLSI, BLSMSK, BLSR, TZCNT)
BMI2 -> CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]
(BZHI, MULX, PDEP, PEXT, RORX, SARX, SHLX, SHRX)
LZCNT -> CPUID.(EAX=80000001H) ECX.LZCNT[bit 5]
POPCNT -> CPUID.(EAX=01H) :ECX.POPCNT [Bit 23]
请注意,即使CPUID指示(英特尔)处理器不支持
popcnt
,它通常也支持 如果您想将它们添加到您的答案中:BMI1(ANDN,BEXTR,BLSI,BLSMSK,BLSR,TZCNT)->CPUID.(EAX=07H,ECX=0H):EBX.BMI1[位3]
BMI2(BZHI,MULX,PDEP,PEXT,RORX,SARX,SHLX,SHRX)->CPUID.(EAX=07H,ECX=0H):EBX.BMI2[位8]
LZCNT.EAX=800000h:ECX->。这是英特尔的术语:CPUID.EAX=8000001h:ECX.LZCNT[bit 5]
表示AMD处理器上的ABM(即popcnt
+LZCNT
)(因为popcnt
有自己的CPUID位和ABM->popcnt
但不是相反)。我不确定和是否到处都有陷阱。VEX前缀毕竟只是lds,我不确定所有旧CPU在看到lds具有无效操作数组合时是否都会引发异常。但是,在64位模式下,这不应该是一个问题,因为lds和les是非法的。哪些英特尔CPU可以正确执行popcnt
,但不设置CPUID功能位?它在我的第一代Core2(Conroe/Merom:SSSE3,但不是SSE4.1)上出现故障。虚拟机可以公开它们想要的任何CPUID标志组合。虽然他们在没有AVX的情况下启用BMI的可能性要比反之大得多,因为AVX意味着额外的体系结构状态。因此,在方便的时候,您应该避免根据已发布的硬件进行假设。(这与决定要创建的函数版本有关。例如,避免依赖AVX版本函数中的BMI是有意义的。但在执行运行时CPU检测时,应测试所有相关功能位。)您只需在初始化时执行一次CPU功能检测,并在全局位字段中设置标志。这样,它非常便宜,而且您永远不必担心检查的成本。即使您不想测试BMI支持,当您不关心输入为0时的行为时,通常也应该使用tzcnt
(rep bsf
)tzcnt
比AMD CPU上的bsf
快得多。在英特尔Skylake(及更高版本?)上,它避免了对bsf
所具有的只写目标寄存器的错误依赖。(popcnt
在SKL上仍然有假dep,就像早期Intel CPU上的lz/tzcnt
一样。)