如何在保持一个值不变的情况下翻转 SSE 中的范围?

How do I flip a range in SSE while keeping one value unchanged?

我在 xmm0 中有一个由 0 .. 12 范围内的八个无符号 8 位数字组成的向量。我想对向量中的每个元素 e 执行以下翻译:

if (e != 12)
    e = 11 - e;

即数字0, 1, ..., 11 改为11, 10, ..., 0 而12 保持不变。其他值不会出现,我不在乎它们会发生什么。

如何使用 SSE4 指令集高效地实现此操作?

对于 SSE2(你没有问,但是..),我提出以下建议,重新使用比较中的掩码来做有趣的否定:

e = (e ^ mask) + (12 & mask)

对于真正的面具变成 ~e + 12 = -e + -1 + 12 = 11 - e 而对于错误的面具,它显然是身份。

或者在向量中,(未测试)

movdqa xmm1, [vec12]
pcmpgtb xmm1, xmm0
pxor xmm0, xmm1
pand xmm1, [vec12]
paddb xmm0, xmm1

对于 SSSE3 及更高版本,您可以使用我们的老朋友 pshufb,因为使用这个值范围可以进行 16 项 table 查找:(未测试)

movdqa xmm1, [table]
pshufb xmm1, xmm0

table 的样子(未测试)

.db 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 12, "yolo"