如何用最少AVX2/AVX-512指令实现寄存器打包字节的循环移位
能不能用少于5条AVX2/AVX-512指令完成字节位循环移位?
结论
- 仅使用原生AVX2/AVX-512指令,无法用少于5条指令实现无跨字节错误的8位字节粒度循环移位
- AVX-512原生
vprol/vpror循环移位指令最小仅支持16位WORD粒度,无法直接应用于8位BYTE场景
现有最优实现(5条指令,单周期处理64字节)
以下代码可正确实现64个字节同时循环左移3位(等价于循环右移5位):
# zmm0 已预加载64个独立字节值 # SL3:内存中连续64个字节为0xf8(左移结果掩码) # SR5:内存中连续64个字节为0x07(右移结果掩码) vpslld zmm1, zmm0, 3 ; 按DWORD粒度左移3位 vpandd zmm1, zmm1, SL3 ; 清除所有字节的低3位,消除跨字节溢出的无效位 vpsrld zmm2, zmm0, 5 ; 按DWORD粒度右移5位 vpandd zmm2, zmm2, SR5 ; 清除所有字节的高5位,消除跨字节溢出的无效位 vpord zmm1, zmm1, zmm2 ; 合并两次移位结果,得到最终循环移位值
指令数无法压缩的原因
由于AVX/AVX-512没有提供8位粒度的移位指令,所有移位操作最小按16位WORD或32位DWORD粒度执行,移位时会导致字节边界的位溢出到相邻字节,必须对两次移位的结果分别做掩码清除溢出位,加上最终合并操作,最少需要5条指令:
- 2条移位指令:分别完成左移n位、右移(8-n)位
- 2条掩码指令:分别清除两次移位后跨字节溢出的无效位
- 1条合并指令:用or/add/xor任意逻辑合并两个结果即可得到正确的循环移位值
补充说明:16位WORD粒度的循环移位可以做到仅3条指令,因为AVX-512原生支持WORD粒度移位,移位后不会跨WORD边界溢出,不需要额外掩码操作,仅需左移、右移、合并三步即可。
内容的提问来源于stack exchange,提问作者John J
相关产品推荐
相关产品推荐

