x86 - 后缀 "x"在像 "_mm256_set1_epi64x"这样的内在函数中的含义

标签 x86 vectorization x86-64 simd intrinsics

在某些内在函数中,它们使用后缀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/

相关文章:

c - 函数指针局部变量的意外值

numpy - 包含 nan 的数组行的平均值直到 25%

assembly - 加载数字流时避免缓存污染

assembly - 编程语言可以有自己的调用约定吗?

x86 - 原子操作是如何在硬件层面实现的?

gcc - 在 GCC 中编译 SSE 内在函数会出错

assembly - NASM 是否在 32 位 x86 中生成的机器指令中包含段寄存器?

matlab - 向量化特征归一化的适当零方差处理?

python - 基于数组的向量化矩阵选择

x86-64 - 是否可以用编译后的二进制文件中的虚拟对象替换特定函数的每个实例?