仅使用 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的寻址范围为____到____

王爽汇编习题 : 给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为 ___ 到 ____。

新加坡100M带宽,国内延迟70ms,仅800元

新加坡100M带宽,国内延迟70ms,仅800元