是否可以使用SSE对非字节对齐的数据进行位操作?例如,我想使用SSE实现这一点:
const char buf[8];
assert(n <= 8);
long rv = 0;
for (int i = 0; i < n; i++)
rv = (rv << 6) | (buf[i] & 0x3f);
相反,我想将buf加载到xmm寄存器中并使用SSE指令来避免循环。不幸的是,移位操作(例如PSLLW)将每个打包整数移位相同的量,所以我不能在这里使用它。使用乘法(PMULLW)模拟移位似乎也不正确......
查看SSE文档,似乎通常不支持位操作。这是真的?或者使用SSE有很好的位操作示例吗?
答案 0 :(得分:4)
我不确定SSE指令是否有助于减少实现代码执行所需的操作数量;如果有人知道,我也很好奇。让我们稍微分解一下代码。
代码是递归移位/或序列,意味着你取最低6位,将它们向左移6位,或接下来6位,再移位,依此类推。
因此,您将8位值的数组转换为6位值的打包数组,将数据从64位缩小到48位。像:
|76543210|76543210|76543210|76543210|76543210|76543210|76543210|76543210| |-----------------|54321054|32105432|10543210|54321054|32105432|10543210|
因此,你可以解开循环并按如下方式编写它:
/*
* (buf[x] << 58)
* moves lowest six bits of a 64bit long into the highest bits, clears others
*
* >> (6 * x + 16)
* shifts the bits into the expected final position
*/
#define L(x) (((long)buf[x] << 58) >> (6 * x + 16))
long rv = L(0) | L(1) | L(2) | L(3) | L(4) | L(5) | L(6) | L(7);
如上所述,我不知道SSE指令有助于这种打包(SSE包做四对一,字到短,短到字节)。
您可以在SSE寄存器中执行操作,但是根据我的意见,不能减少获得最终结果所需的指令数。
答案 1 :(得分:0)
您可以在SSE中执行相当多的按位操作。你可以使用_mm_and_si128,_mm_or_si128并且有一大堆移位操作。 Google _mm_slli_si128查找完整列表。这些说明已添加到SSE2中,因此它们可以广泛使用。