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

时间:2017-07-08 18:17:36

标签: x86 vectorization x86-64 simd intrinsics

在某些内在函数中,他们使用后缀x,如_mm256_set1_epi64x。它的含义是什么?作为参考,_mm256_set1_epi32没有此后缀。

1 个答案:

答案 0 :(得分:4)

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)。根据内在发现者的说法,movq mm0, rax仍然没有任何内在因素。我认为你可以/应该将int64_t投射到__m64。 (虽然上次我在去年左右进行了实验,gcc或clang(我忘记了)在优化MMX asm方面表现不佳。老化编译器支持是避免MMX用于新项目的另一个原因。)

当SSE2被引入in 2001时,AMD64 / x86-64仍未发布,并且几年内英特尔不会支持它。 (当时他们希望IA-64 / Itanium成为未来并取代x86)。我没有检查过旧的手册,但我想是的 __m128i _mm_set1_epi64 (__m64 a)当时可用,并且 __m128i _mm_set1_epi64x (__int64 a)可能不是。 (请注意,__int64不是来自int64_t的{​​{1}}。但它是64位整数类型,无需担心。)

<stdint.h>代表扩展(?)Packed Integer。 epi代替epi告诉您它是SSE内在的,而不是MMX内在的。对于从一个元素宽度转换为另一个元素宽度的内部函数,如果明确地识别操作(至少对于我所看到的那些),内在函数使用源宽度。例如pi_mm_packs_epi32)或packssdw_mm_unpackhi_epi16)。 PMOVZX需要两个数字,因为有punpckhwd_mm_cvtepu8_epi32),pmovzxbd_mm_cvtepu8_epi64等等。

编译器当然支持32位模式下的64位整数,因此英特尔包含用于处理它们的内在函数是有意义的。但是IIRC,在某些编译器中pmovzxbq内在函数仅在编译64位代码时可用64x仅与转换为标量64位整数/从标量64位整数相关,因此您无法找到64xx或类似内容。

根据编译器的不同,_mm_add_epi64可能仍然存在这个仅64位的内容,但历史记录解释了为什么_mm256_set1_epi64x而不是64x

(抱歉,我很懒,并没有在Godbolt上组合实验来检查当前编译器32x。看看你从铸造-m32获得什么样的asm可能会很有趣到int64_t并在32位代码中使用__m64内在函数。)