使用SIMD右移32位打包负数

Iss*_*sso 1 c sse avx mmx

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

Pet*_*des 5

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

使用_mm_srai_epi32(psrad)代替_mm_srli_epi32(psrld).

请参阅英特尔的内在指南以及SSE标记wiki中的其他链接https://stackoverflow.com/tags/sse/info.(如果你愿意的话,过滤它以排除AVX512,因为这些天所有3种尺寸的所有蒙版版本都很混乱...)

或者只是查看asm指令集引用,其中包含具有它们的指令的内在函数.在http://felixcloutier.com/x86/index.html中搜索"算术"会找到您想要的变化.

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


算术右移也可用于AVX2变量换档(vpsravd以及即时换档的单变量换全元素版本).


脚注1:

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

这正确地实现了2的补码有符号除以2的幂,向着负无穷大舍入,而不像从C有符号除法那样截断到零.查看asm输出,int foo(int a){return a/4;}了解编译器如何根据移位实现有符号划分语义.