XMM寄存器的按位否定

时间:2016-01-19 16:34:46

标签: assembly x86 bit-manipulation sse bitwise-not

如何在XMM寄存器中对值进行逐位否定?据我所知,没有这样的指示。唯一带有否定的指令是pandn,但是要用它来简单地否定一个XMM寄存器中的值,我必须让另一个填充了1的XMM寄存器填充。

是否有另一种方法来否定XMM寄存器中的位?或者是否有一种聪明的方法可以在不访问内存的情况下用1填充XMM寄存器?

2 个答案:

答案 0 :(得分:5)

要加载一个包含全1的寄存器,请使用

pcmpeqd xmm0, xmm0

之后,您只需从xmmX中扣除xmm0即可获得~xmmX,或使用pandn

您还可以轻松地将其他常量加载到xmm寄存器

pcmpeqd xmm0, xmm0
psrld   xmm0, 30   ; 3 (32-bit)

pcmpeqd xmm0, xmm0 ; -1

pcmpeqw xmm0, xmm0 ; 1.5f
pslld   xmm0, 24
psrld   xmm0, 2

pcmpeqw xmm0, xmm0 ; -2.0f
pslld   xmm0, 30

阅读Agner Fog的优化指南13.4 Generating constants - Making constants for integer vectors in XMM registers

答案 1 :(得分:5)

pxor与所有人注册一起使用。

pandn也可以使用,但优势为零。在所有情况下,pandn都可以使用全常量来进行pxor做不到的事情。

psubd也是可用的(2的补码身份),但比pandn更糟糕,因为它在某些CPU上具有较低的吞吐量(较少的执行端口)。


pcmpedq  xmm1, xmm1      ; create the all-ones.  No false dependency.

pxor     xmm0, xmm1      ; flip all the bits in XMM0. Doesn't destroy XMM1
;pandn    xmm0, xmm1      ; equivalent but no advantage.  (~xmm0) & xmm1

PXOR很好,因为它是可交换的。使用AVX,您可以使用一个微融合的uop加载和不加载:

vpxor    xmm0, xmm1, [rdi]

您不能使用VPANDN进行此操作,因为可以是内存或寄存器的操作数是未取反的操作数。 (不过,在没有AVX的情况下,仅加载movdqadqu,然后加载pxor。reg复制和微融合的load + pxor是3个未融合域的总和。2)


或者在没有AVX的情况下,如果要破坏全常量而不是要反转的数据,则pxor会再次获胜:

movdqa  xmm2, xmm1      ; copy the all-ones constant.  Off the critical path for latency
pxor    xmm2, xmm0

movdqa / movdqa xmm2, xmm0相比,您可以从关键路径上撤消pandn xmm2,xmm1。 (只有IvyBridge +和Bulldozer-family / Ryzen对向量寄存器使用零延迟movdqa。)或者如果您每次在目标寄存器中使用pcmpeqd重新实现全一(也许是由于寄存器压力)或因为您没有循环执行),那是您想要pxor而不是pandn的另一种情况。


使用pcmpeqb/w/d生成全常量是特殊情况,它不会对旧值有错误的依赖性(在Silvermont上除外),但是仍然需要一个执行单元(与异或归零不同)在桑迪布里奇家庭)。尽管如此,它还是便宜的,并且是编译器用于_mm_set1_epi32(-1)的功能。

在IvyBridge和更高版本以及Bulldozer系列和Ryzen上,每次需要它时都重新创建该常量,而不是从另一个寄存器中复制它会变得稍微mov消除XMM副本可以避免占用向量执行单元/端口,以防向量ALU执行端口成为您的瓶颈。

但是在Intel P6-family(Core2 / Nehalem)上要好一些:在问题组中读取过多的“冷”寄存器时,寄存器读取停顿可能是个问题。 (请参阅Agner Fog的microarch pdf https://agner.org/optimize/)。 P6系列已过时,但仍在某些旧机器中使用。如果您有在具有AVX的CPU上运行的AVX版本,则可能需要在代码的非AVX版本中进行调整。 (但是Haswell / Skylake的“ pentium” /“ celeron”还是一回事,它们没有AVX,所以没有AVX并不意味着旧的CPU。)