【发布时间】:2023-03-20 02:32:01
【问题描述】:
对于一个特定项目,我坚持使用 gcc 和在 i7 Core 上运行的 32 位 12.04 LTS Ubuntu,最多支持 AVX SIMD 指令。
由于是 32 位操作系统,我显然不能使用在 256 位上运行的 AVX 指令。我可以使用 128 位访问 SSE4.2 指令,并且 POPCNT 可以在 16、32 和 64 位数据上运行,因此看起来很有希望。但我尝试了几种方法向 POPCNT 提供 64 位数据,但均未成功。 GCC 4.6.3 返回
- “未知的寄存器名称” 用于 r8 到 r15,
- rax-rdx 的“错误寄存器名称”,
- 当试图提供 mm 寄存器或为我的内联汇编函数提供一些 uint64 或 long long 时,这些 uint64 或 long long 会受到此类寄存器的影响
方式:
uint64 a, b;
__asm__ volatile (“POPCNT %1, %0;”
:”=r”(b)
:”r”(a)
:
)
gcc 告诉 “popcnt 的操作数类型不匹配”,
- 写 POPCNTQ 会导致“popcnt 的指令后缀无效”。
如果 POPCNT 支持 128 位 xmm 寄存器,那就太好了...
在汇编中对 64 位数据应用 POPCNT 的任何解决方法?
PS:关于使用 shuffle 的 SSSE3 popcount 与 SSE4 POPCNT 性能比较的讨论在这里找到了结论http://danluu.com/assembly-intrinsics/ 并且仅仅是因为使用内在函数并不总是提供有效的汇编代码。使用内部函数快速优化 C/C++ 代码非常好,如果这足以满足需求,那很好。但是,与内在函数相比,我在汇编中使用 shuffle 获得了近 30% 的性能改进编码 popcount。
【问题讨论】:
-
我可能弄错了,但是在 32 位模式下,RAX 和 R15 到底是什么意思?它们是 GP 64 位寄存器的名称,根据定义,您在 32 位模式下没有这些名称。宽寄存器是向量“XMM”寄存器。虽然
"r"(a)似乎是一个无辜的语法,但它确实要求a适合GP 寄存器。 -
请注意,您使用的智能引号是 C 和 C++ 中的无效字符,因此甚至无法编译
标签: gcc assembly optimization 32bit-64bit hammingweight