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

fuz*_*fuz 2 x86 assembly sse x86-64 vectorization

我有一个8位无符号8位数的向量,范围为0 .. 12 in xmm0.我想对e向量中的每个元素执行以下转换:

if (e != 12)
    e = 11 - e;
Run Code Online (Sandbox Code Playgroud)

也就是说,数字0,1,...,11被改变为11,10,...,0而12保持不变.其他值不会发生,我不在乎它们会发生什么.

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

har*_*old 6

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

e = (e ^ mask) + (12 & mask)
Run Code Online (Sandbox Code Playgroud)

对于真正的面具而言~e + 12 = -e + -1 + 12 = 11 - e,对于假面具而言,这显然是身份.

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

movdqa xmm1, [vec12]
pcmpgtb xmm1, xmm0
pxor xmm0, xmm1
pand xmm1, [vec12]
paddb xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)

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

movdqa xmm1, [table]
pshufb xmm1, xmm0
Run Code Online (Sandbox Code Playgroud)

表格看起来像(未经测试)

.db 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 12, "yolo"
Run Code Online (Sandbox Code Playgroud)

  • 哦哇,我完全忘记了pshufb!对于第一个,我想做(((12-v)+ 243) - 243)其中加法是饱和加法,它将结果移动到正确的位置.但是对于所有掩模负载,您的方法可能更快. (2认同)