MS Visual C ++在带有SSE4.2的CPU上支持2种popcnt指令:
__popcnt()
_mm_popcnt_u32()
我发现的唯一区别是__popcnt()
的文档被标记为“Microsoft特定”,_mm_popcnt_u32()
seems to be an intrinsic command name(非特定于MS)。
这是唯一的区别,MS __popcnt()
只调用了硬件_mm_popcnt_u32()
吗?
答案 0 :(得分:11)
这是同一台机器指令的两个不同的内在名称,这要归功于Intel和AMD。所有支持它的CPU上的指令都是相同的,不同的内在函数在C中也没有区别或者C ++。
__popcnt *()内置函数用于AMD的高级位操作(ABM)指令。见http://blogs.amd.com/developer/2007/09/26/barcelona-processor-feature-advanced-bit-manipulation-abm/
_mm_popcnt_u *()内在函数适用于英特尔的实现,它本身不属于SSE4.2,但大约在同一时间实现。见http://en.wikipedia.org/wiki/SSE4#POPCNT_and_LZCNT
根据https://www.chessprogramming.org/Population_Count,两种实现都是二进制兼容的,尽管它们的内在名称不同。
英特尔architecture manual表示:
AMD的AMD64 Architecture Programmer's Manual Volume 3: General Purpose and System Instructions说在应用程序尝试使用POPCNT指令之前,必须检查该指令 处理器支持SSE4.2(如果CPUID.01H:ECX.SSE4_2 [bit 20] = 1)和POPCNT(如果 CPUID.01H:ECX.POPCNT [bit 23] = 1)。
由CPUID返回的ECX位23(POPCNT)表示支持POPCNT指令 功能0000_0001h。软件必须在每个程序或库初始化时检查一次CPUID位 在使用POPCNT指令之前,可能会导致不一致的行为。
我看不出为什么popcnt需要存在SSE4.2的原因,所以我认为检查ECX的第23位就足以确定popcnt的存在。
英特尔目前的documentation for popcnt
在他们的vol.2指令集参考手册中只说#UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0
所以反竞争建议会导致软件无法利用{某些没有SSE4.2的AMD CPU上的{1}}消失了。