像“_mm256_set1_epi64x”这样的内在函数中后缀 "x" 的含义
Meaning of suffix "x" in intrinsics like "_mm256_set1_epi64x"
在某些内在函数中,他们使用后缀 x
,例如 _mm256_set1_epi64x
。这是什么意思?作为参考,_mm256_set1_epi32
没有此后缀。
TL:DR: MMX->SSE2 转换内在函数使用了非 x _mm_set/set1_epi64
名称。
这都是基于当前函数名称、已知历史和一些编译器行为的猜测:
第一个英特尔 SIMD 内在函数用于 MMX。 __m64
是 SSE2 __m128i
和 AVX2 __m256i
的 MMX 等价物。当时没有 64 位 x86 CPU,所以最宽的 set
内在是 __m64 _mm_set_pi32 (int e1, int e0)
。根据 intrinsic-finder,movq mm0, rax
仍然没有任何内在函数。我认为你 can/should 只是将 int64_t
转换为 __m64
。 (虽然上次我在去年左右进行了实验,但 gcc 或 clang(我忘了是哪个)在优化 MMX asm 方面做得很差。老化的编译器支持是新项目避免使用 MMX 的另一个原因。)
引入 SSE2 时 in 2001, AMD64 / x86-64 still wasn't released yet, and wouldn't be supported by Intel for a few years. (At that time they were hoping that IA-64 / Itanium 将成为未来并取代 x86)。我没有检查旧手册,但我猜
__m128i _mm_set1_epi64 (__m64 a)
当时可用,
__m128i _mm_set1_epi64x (__int64 a)
可能不是。 (请注意,__int64
不是 <stdint.h>
中的 int64_t
。但它是 64 位整数类型,无需担心。)
epi
代表扩展(?)压缩整数。 epi
而不是 pi
告诉您它是 SSE 内在的,而不是 MMX 内在的。对于从一个元素宽度转换为另一个元素宽度的内在函数,如果明确标识操作(至少对于我查看的那些),则内在函数使用源宽度。例如_mm_packs_epi32
(packssdw
) 或 _mm_unpackhi_epi16
(punpckhwd
)。 PMOVZX 需要两个数字,因为有 _mm_cvtepu8_epi32
(pmovzxbd
),_mm_cvtepu8_epi64
(pmovzxbq
,等等
编译器当然支持 32 位模式下的 64 位整数,因此英特尔包含与它们一起使用的内在函数是有意义的。但是 IIRC,在某些编译器中,64x
内在函数仅在编译 64 位代码时可用。 64x
仅与转换 to/from 标量 64 位整数相关,因此您找不到 x
版本的 _mm_add_epi64
或类似的东西。
根据编译器的不同,_mm256_set1_epi64x
可能仍然存在这种仅存在于 64 位中的东西,但无论哪种方式,历史都解释了为什么 64x
而不是 32x
.
(抱歉,我很懒惰,没有在 Godbolt 上进行实验以检查当前编译器是否具有 -m32
。看看你从铸造中得到什么样的 asm 可能会很有趣 int64_t
到 __m64
并使用 32 位代码中的 _mm_set
内在函数。)
在某些内在函数中,他们使用后缀 x
,例如 _mm256_set1_epi64x
。这是什么意思?作为参考,_mm256_set1_epi32
没有此后缀。
TL:DR: MMX->SSE2 转换内在函数使用了非 x _mm_set/set1_epi64
名称。
这都是基于当前函数名称、已知历史和一些编译器行为的猜测:
第一个英特尔 SIMD 内在函数用于 MMX。 __m64
是 SSE2 __m128i
和 AVX2 __m256i
的 MMX 等价物。当时没有 64 位 x86 CPU,所以最宽的 set
内在是 __m64 _mm_set_pi32 (int e1, int e0)
。根据 intrinsic-finder,movq mm0, rax
仍然没有任何内在函数。我认为你 can/should 只是将 int64_t
转换为 __m64
。 (虽然上次我在去年左右进行了实验,但 gcc 或 clang(我忘了是哪个)在优化 MMX asm 方面做得很差。老化的编译器支持是新项目避免使用 MMX 的另一个原因。)
引入 SSE2 时 in 2001, AMD64 / x86-64 still wasn't released yet, and wouldn't be supported by Intel for a few years. (At that time they were hoping that IA-64 / Itanium 将成为未来并取代 x86)。我没有检查旧手册,但我猜
__m128i _mm_set1_epi64 (__m64 a)
当时可用,
__m128i _mm_set1_epi64x (__int64 a)
可能不是。 (请注意,__int64
不是 <stdint.h>
中的 int64_t
。但它是 64 位整数类型,无需担心。)
epi
代表扩展(?)压缩整数。 epi
而不是 pi
告诉您它是 SSE 内在的,而不是 MMX 内在的。对于从一个元素宽度转换为另一个元素宽度的内在函数,如果明确标识操作(至少对于我查看的那些),则内在函数使用源宽度。例如_mm_packs_epi32
(packssdw
) 或 _mm_unpackhi_epi16
(punpckhwd
)。 PMOVZX 需要两个数字,因为有 _mm_cvtepu8_epi32
(pmovzxbd
),_mm_cvtepu8_epi64
(pmovzxbq
,等等
编译器当然支持 32 位模式下的 64 位整数,因此英特尔包含与它们一起使用的内在函数是有意义的。但是 IIRC,在某些编译器中,64x
内在函数仅在编译 64 位代码时可用。 64x
仅与转换 to/from 标量 64 位整数相关,因此您找不到 x
版本的 _mm_add_epi64
或类似的东西。
根据编译器的不同,_mm256_set1_epi64x
可能仍然存在这种仅存在于 64 位中的东西,但无论哪种方式,历史都解释了为什么 64x
而不是 32x
.
(抱歉,我很懒惰,没有在 Godbolt 上进行实验以检查当前编译器是否具有 -m32
。看看你从铸造中得到什么样的 asm 可能会很有趣 int64_t
到 __m64
并使用 32 位代码中的 _mm_set
内在函数。)