__popcnt()和_mm_popcnt_u32()之间有什么区别?

时间:2012-06-20 06:32:26

标签: x86 sse intrinsics sse4

MS Visual C ++在带有SSE4.2的CPU上支持2种popcnt指令:

  1. __popcnt()
  2. _mm_popcnt_u32()
  3. 我发现的唯一区别是__popcnt()的文档被标记为“Microsoft特定”,_mm_popcnt_u32() seems to be an intrinsic command name(非特定于MS)。

    这是唯一的区别,MS __popcnt()只调用了硬件_mm_popcnt_u32()吗?

1 个答案:

答案 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表示:

  

在应用程序尝试使用POPCNT指令之前,必须检查该指令   处理器支持SSE4.2(如果CPUID.01H:ECX.SSE4_2 [bit 20] = 1)和POPCNT(如果   CPUID.01H:ECX.POPCNT [bit 23] = 1)。

AMD的AMD64 Architecture Programmer's Manual Volume 3: General Purpose and System Instructions

  

由CPUID返回的ECX位23(POPCNT)表示支持POPCNT指令   功能0000_0001h。软件必须在每个程序或库初始化时检查一次CPUID位   在使用POPCNT指令之前,可能会导致不一致的行为。

我看不出为什么popcnt需要存在SSE4.2的原因,所以我认为检查ECX的第23位就足以确定popcnt的存在。


AMD的第一款拥有popcnt的AMD CPU没有完全实现SSE4,因此英特尔架构手册可能会提出一种确定存在的方法,该方法可以在英特尔CPU上运行,甚至可以在合格的AMD CPU上运行。

英特尔目前的documentation for popcnt在他们的vol.2指令集参考手册中只说#UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0 所以反竞争建议会导致软件无法利用{某些没有SSE4.2的AMD CPU上的{1}}消失了。