仅使用 SSE3 替换 _mm_cvtepi16_epi32
Posted
技术标签:
【中文标题】仅使用 SSE3 替换 _mm_cvtepi16_epi32【英文标题】:replace _mm_cvtepi16_epi32 using only SSE3 【发布时间】:2016-02-25 14:18:54 【问题描述】:_mm_cvtepi16_epi32
(pmovsxwd
) 需要 SSE4.1
我们如何仅使用 SSE3 或 SSE2 对向量元素进行符号扩展?
SSSE3 的答案也可能很有趣。
【问题讨论】:
"Extend" data type size in SSE register 的可能重复项。在我找到答案之前我找不到那个副本,所以我可以在 _mm_unpacklo_epi16 _mm_srai_epi32 上搜索。 “_mm_cvtepi16_epi32 without sse4.1”没有出现,所以这不是一个坏问题。这是一个副本,但不是我希望 OP 自己找到的。 【参考方案1】:使用解包复制每个 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
形式保持一致。pmovsx
真正闪耀的地方是从字节到 dword,或从字节到 qword。此外,它的加载形式很好,即使内在函数做到了真的很难用作负载。)
对于其他元素大小,有一个psraw
,所以 8->16 也是有效的,但没有psraq
(对于 64 位元素只有逻辑左/右移位)。 pmovsxdq
更难模仿。 pblendw
也是 SSE4.1。我在想也许用零解包,然后算术右移。然后你可以用另一种方式对一个用零解包的向量进行 OR 运算。
这样做的好处是可以使用_mm_unpackhi
获得上半部分,而pmovsz
/pmovzx
很遗憾没有这样做。
【讨论】:
以上是关于仅使用 SSE3 替换 _mm_cvtepi16_epi32的主要内容,如果未能解决你的问题,请参考以下文章
PHP Regex 仅允许 a-z A-Z 1-9 并用下划线替换空格
给定地址段为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为____到____