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

Adi*_*vit 9 x86 sse intrinsics sse4

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

  1. __popcnt()
  2. _mm_popcnt_u32()

我发现的唯一区别是文档__popcnt()被标记为"Microsoft Specific",并且_mm_popcnt_u32() 似乎是一个内在的命令名称(非MS特定的).

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

mat*_*t88 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,两种实现都是二进制兼容的,尽管它们的内在名称不同.

英特尔架构手册指出:

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

AMD的AMD64架构程序员手册第3卷:通用和系统指令

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

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


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

英特尔在其vol.2指令集参考手册中的当前文档popcnt仅表示#UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0如此反竞争的建议将导致软件popcnt在没有SSE4.2的情况下在某些AMD CPU上不利用.