使用 SIMD 右移 32 位压缩负数

Using SIMD to right shift 32 bit packed negative number

我正在编写一些 SSE/AVX 代码,并且有一个任务是将打包的有符号 32 位整数除以 2 的补码。当值为正时,此移位工作正常,但是由于移动了符号位,它会为负值产生错误的结果。
是否有任何 SIMD 操作可以让我移动并保留符号位的位置?谢谢

SSE2/AVX2 可以选择算术 1 与 16 位和 32 位元素大小的逻辑右移。 (对于 64 位元素,在 AVX512 之前只有逻辑可用)。

使用_mm_srai_epi32 (psrad) instead of _mm_srli_epi32 (psrld).

参见Intel's intrinsics guide, and other links in the SSE tag wiki https://whosebug.com/tags/sse/info。 (如果你愿意,可以过滤它以排除 AVX512,因为这些天它非常混乱,所有 3 种尺寸的所有屏蔽版本......)

或者只查看 asm 指令集参考,其中包括具有内在指令的指令。在 http://felixcloutier.com/x86/index.html 中搜索 "arithmetic" 可找到您想要的班次。

请注意 a=arithmetic 与 l=logical,而不是 epu32 无符号的通常的内在命名方案。 asm 助记符简单且一致(例如,Packed Shift Right Arithmetic Dword = psrad)。


算术右移也可用于 AVX2 变量移位(vpsravd,以及立即移位的一变量所有元素版本。


脚注 1:

算术右移符号位的副本,而不是零

这正确地实现了 2 的有符号补码除法,并向负无穷大舍入,这与从 C 有符号除法中得到的向零截断不同。查看 int foo(int a){return a/4;} 的 asm 输出,了解编译器如何根据移位实现有符号除法语义。