在某些内在函数中,它们使用后缀x
,例如_mm256_set1_epi64x
。它有什么意义呢?作为引用,_mm256_set1_epi32
没有此后缀。
最佳答案
TL:DR: MMX->SSE2 转换内在函数采用非 x _mm_set/set1_epi64
名称。
这都是基于当前函数名称、已知历史记录和一些编译器行为的猜测:
第一个英特尔 SIMD 内在函数是针对 MMX 的。 __m64
是 SSE2 __m128i
的 MMX 等价物和 AVX2 __m256i
。当时还没有64位x86 CPU,所以最宽的set
内在是__m64 _mm_set_pi32 (int e1, int e0)
。根据内在函数查找器, movq mm0, rax
仍然没有任何内在函数。 。我认为你可以/应该类型转换 int64_t
至__m64
。 (虽然我上次尝试是在去年左右,但 gcc 或 clang(我忘了是哪一个)在优化 MMX asm 方面表现不佳。老化的编译器支持是新项目避免使用 MMX 的另一个原因。)
SSE2何时推出in 2001 ,AMD64/x86-64还没有发布,并且几年内都不会得到Intel的支持。 (当时他们希望IA-64 / Itanium将成为 future 并取代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_epi32
( packssdw
) 或 _mm_unpackhi_epi16
(punpckhwd
)。 PMOVZX 需要这两个数字,因为有 _mm_cvtepu8_epi32
( pmovzxbd
), _mm_cvtepu8_epi64
( pmovzxbq
等
编译器当然支持 32 位模式下的 64 位整数,因此英特尔包含用于处理它们的内在函数是有意义的。但是 IIRC,在某些编译器中 64x
内在函数仅在编译 64 位代码时可用。 64x
仅与标量 64 位整数之间的转换相关,因此您不会找到 x
_mm_add_epi64
的版本或类似的东西。
对于_mm256_set1_epi64x
来说,这个仅在64位的东西可能仍然存在取决于编译器,但无论哪种方式,历史都解释了原因 64x
但不是32x
.
(抱歉,我很懒,没有在 Godbolt 上进行实验来检查当前编译器的 -m32
。看看从 int64_t
到 __m64
得到什么样的汇编可能会很有趣。并在 32 位代码中使用 _mm_set
内在函数。)
关于x86 - 后缀 "x"在像 "_mm256_set1_epi64x"这样的内在函数中的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44989391/