assembly 优化arm64的simd指令(mov),将交替字节打包成连续字节(十六进制到uint64_t)

mi7gmzs6  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(58)

我有这个V6.16b寄存器:0a,0b,0c,0d,0e,0f,07,08,0a,0b,0c,0d,0e,0f,07,08
目标是:ab,cd,ef,78,ab,cd,ef,78
我是这样做的:

movi v7.8h,   0x04            // 04,00,04,00,04,00,04,00,04,00,04,00,04,00,04,00
ushl v6.16b,  v6.16b,  v7.16b // a0,0b,c0,0d,e0,0f,70,08,a0,0b,c0,0d,e0,0f,70,08
movi v8.8h,   0xf8            // f8,00,f8,00,f8,00,f8,00,f8,00,f8,00,f8,00,f8,00
ushl v10.8h,  v6.8h,   v8.8h  // 0b,00,0d,00,0f,00,08,00,0b,00,0d,00,0f,00,08,00
orr  v10.16b, v10.16b, v6.16b // ab,0b,cd,0d,ef,0f,78,08,ab,0b,cd,0d,ef,0f,78,08

mov v10.b[1], v10.b[2]
mov v10.b[2], v10.b[4]
mov v10.b[3], v10.b[6]
mov v10.b[4], v10.b[8]
mov v10.b[5], v10.b[10]
mov v10.b[6], v10.b[12]
mov v10.b[7], v10.b[14] // ab,cd,ef,78,ab,cd,ef,78,ab,0b,cd,0d,ef,0f,78,08

字符串
它工作,但有没有一种方法可以用更少的指令来完成它?(特别是mov)

b4qexyjb

b4qexyjb1#

所以你有零扩展的半字节解压缩在big-endian顺序打包成字节?
就像strtol for hex -> integer,经过一些初始处理,将ASCII十六进制数字Map到它们表示的整数数字。
对于您想要从偶数位置打包字节的原始设置,UZP1,但您也可以优化shift/orr步骤。
而不是2x ushl + orr的第一个块,也许是shl v10.8h, v6.8h, #12/orr来获得奇数元素中想要的字节,垃圾(未修改)偶数元素。(从0开始计数,0a元素,因为我认为您正在以最低有效位优先顺序编写向量,其中较宽的左移位将数据向右移动跨越字节边界)。sli v6.8h, v6.8h, #12**(Shift-Left and Insert,其中位在左移创建零的位置保持其原始值。)

对于打包步骤,UZP2应该将奇数向量元素(从1开始)打包到低8个字节中。(如果使用相同的向量作为两个源操作数,则在高8个字节中重复。)

// produces the same result as all your code
//  in the bottom 8 bytes of v10
 sli   v6.8h, v6.8h, #12       //a0,ab,c0,cd,e0,ef,70,78, a0,ab,c0,cd,e0,0f,70,78
 uzp2  v10.16b, v6.16b, v6.16b //ab,cd,ef,78,ab,cd,0f,78, ab,cd,ef,78,ab,cd,0f,78

// rev64 v10.8b, v10.8b         // if you want a uint64_t in proper order

字符串
(我注意到你有一个e0字节。(0xe0 as u16) << 12移出位变成0,如果这不是0x0e的错别字的话)
如果这是跨半字节对的顺序,则这会使数据保持big-endian字节顺序。**在打包时,您可能需要使用字节混洗tbluzp2**将顺序反转为uint64_t。或者如果您一次只对一个数字执行此操作(所以加载一个shuffle-control常量需要另一条不能从循环中提升出来的指令)可能是uzp2之后的rev64 v10.8b, v10.8b。或者是rev64v10.16b在向量的两半中做两个u64整数。
对于字节对的打包,右移和usra乘以#4的累加也可以在一条指令中完成(移位和累加),因为当设置位不重叠时,ORR、ADD和插入是等效的。但它会给你给予0xba而不是0xab,将第二个字节向下移位以成为U8.rev16 + usra的高半部分将起作用,但是shl + orr也是2个指令并且可能更便宜,可能至少在一些CPU上运行更多的执行单元。sli甚至更好,谢谢@fuz。
没有usla。乘法累加可以与2的幂乘法器一起使用,但在某些CPU上可能比shl + orr慢,并且需要一个向量常数。当然比sli更糟糕。

相关问题