内在函数中后缀“x”的含义,如“_mm256_set1_epi64x”

Ser*_*tch 6 x86 x86-64 simd vectorization intrinsics

在某些内在函数中,它们使用后缀,x_mm256_set1_epi64x. 它的意义是什么?作为参考,_mm256_set1_epi32没有这个后缀。

Pet*_*des 6

TL:DR: MMX->SSE2 转换内在函数采用非 x_mm_set/set1_epi64名称。

这都是基于当前函数名称、已知历史和一些编译器行为的猜测:

第一个英特尔 SIMD 内在函数用于 MMX。 __m64是 SSE2__m128i和 AVX2的 MMX 等价物__m256i。当时没有 64 位 x86 CPU,所以最宽的set内在函数是__m64 _mm_set_pi32 (int e1, int e0). 根据内在查找器,仍然没有任何内在 for movq mm0, rax。我认为你可以/应该只是投射int64_t__m64. (虽然我上次试验是在去年左右,gcc 或 clang(我忘了哪个)在优化 MMX asm 方面做得很差。老化的编译器支持是避免新项目使用 MMX 的另一个原因。)

SSE2于 2001年推出,AMD64 / x86-64 还没有发布,并且几年内都不会得到 Intel 的支持。(当时他们希望IA-64 / Itanium成为未来并取代 x86)。我没有检查过旧手册,但我想
__m128i _mm_set1_epi64 (__m64 a)当时可以使用,但
__m128i _mm_set1_epi64x (__int64 a)可能没有。(请注意,__int64它不是int64_t来自<stdint.h>。但它是 64 位整数类型,无需担心。)

epi代表扩展(?)压缩整数。 epi而不是pi告诉您它是 SSE 内在函数,而不是 MMX 内在函数。对于从一种元素宽度转换为另一种元素宽度的内部函数,如果明确标识操作(至少对于我查看的那些),则内部函数使用源宽度。例如_mm_packs_epi32packssdw)或_mm_unpackhi_epi16punpckhwd)。PMOVZX 需要两个数字,因为有_mm_cvtepu8_epi32( pmovzxbd)、_mm_cvtepu8_epi64(pmovzxbq等。


编译器当然支持 32 位模式下的 64 位整数,因此英特尔包含用于处理它们的内在函数是有意义的。但是 IIRC,在某些编译器中,64x内部函数仅在编译 64 位代码时可用。该64x只从标量64位整数转换为/,所以你不会找到一个相关x的版本_mm_add_epi64或类似的东西。

这个仅在 64 位中的东西可能仍然存在,_mm256_set1_epi64x具体取决于编译器,但无论哪种方式,历史都解释了为什么64x而不是32x.

(对不起,我很懒,没有在 Godbolt 上进行实验来检查当前的编译器-m32。看看你从转换int64_t__m64和使用_mm_set32 位代码中的内在函数得到什么样的 asm 可能会很有趣。)