X86 仅使用SSE3更换_mm_cvtepi16_epi32

X86 仅使用SSE3更换_mm_cvtepi16_epi32,x86,sse,intrinsics,X86,Sse,Intrinsics,\u mm\u cvtepi16\u epi32(pmovsxwd)需要SSE4.1 如何仅使用SSE3或SSE2对扩展向量元素进行签名 SSSE3的答案可能也很有趣。使用解包复制每个16位元素(从下半部分开始),然后使用算术右移在每个32b元素的上半部分保留符号位的副本 __m128i v16 = ...; v32 = _mm_unpacklo_epi16(v16, v16); // [ a a b b c c d d ] v32 = _mm_srai_epi32(v32, 16); 这只

\u mm\u cvtepi16\u epi32
pmovsxwd
)需要SSE4.1

如何仅使用SSE3或SSE2对扩展向量元素进行签名


SSSE3的答案可能也很有趣。

使用解包复制每个16位元素(从下半部分开始),然后使用算术右移在每个32b元素的上半部分保留符号位的副本

__m128i v16 = ...;
v32 = _mm_unpacklo_epi16(v16, v16);  // [ a a b b c c d d ]
v32 = _mm_srai_epi32(v32, 16);
这只是SSE2。这是两个快速指令,所以我不认为从SSE3或SSSE3中可以获得任何东西,也想不到任何东西。唯一比这更好的方法是以非破坏性方式进行编译(因此,如果我们仍然需要它,编译器不必复制
v16

如果您已经可以在一条指令中完成此操作,则可能没有引入
pmovsxwd
。(尽管它可能与其他
pmovsx
表单保持一致。当从字节到dword,或从字节到qword时,
pmovsx
真正引人注目。此外,它的加载形式很好,尽管内部函数使它很难用作加载。)

对于其他元素大小,有一个
psraw
,因此8->16也是有效的,但是没有
psraq
(对于64位元素只有逻辑左/右移位)
pmovsxdq
更难模拟
pblendw
也是SSE4.1。我在想也许用零解包,然后算术右移。然后你可以用另一种方法,用零来解包向量

这样做的好处是可以使用
\u mm_unpachi
来获取上半部分,而
pmovsz
/
pmovzx
不幸的是,上半部分无法获得。在我找到答案之前,我找不到那个副本,所以我可以在谷歌上搜索。它没有出现在“没有sse4.1的cvtepi16\U epi32”中,所以这是一个不错的问题。这是一个复制品,但不是一个我希望OP自己发现的。