如何获得 XMM 寄存器中值的按位否定?据我所知,没有这样的指示。唯一带有否定的指令是pandn
,但要使用它来简单地否定一个 XMM 寄存器中的值,我必须让另一个 XMM 寄存器填充1
.
是否有另一种方法来否定 XMM 寄存器中的位?1
或者有没有一种聪明的方法可以在不访问内存的情况下填充 XMM 寄存器?
如何获得 XMM 寄存器中值的按位否定?据我所知,没有这样的指示。唯一带有否定的指令是pandn
,但要使用它来简单地否定一个 XMM 寄存器中的值,我必须让另一个 XMM 寄存器填充1
.
是否有另一种方法来否定 XMM 寄存器中的位?1
或者有没有一种聪明的方法可以在不访问内存的情况下填充 XMM 寄存器?
要加载一个全为 1 的寄存器,请使用
pcmpeqd xmm0, xmm0
之后,您可以简单地xmmX
从xmm0
get中减去~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 生成常量 - 在 XMM 寄存器中为整数向量制作常量
pxor
与全为寄存器一起使用。
pandn
也可以使用,但是优势为零。没有任何情况下,pandn
使用全1 常量可以让你做任何你不能用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,只需加载movdqa
或dqu
加载,然后pxor
加载结果。reg-copy 和 micro-fused load+pxor 是 3 个未融合域 uops 与 2 个)
或者没有 AVX,如果你想破坏全为常数而不是你正在反转的数据,pxor
再次获胜:
movdqa xmm2, xmm1 ; copy the all-ones constant. Off the critical path for latency
pxor xmm2, xmm0
您可以movdqa
从关键路径 vs. movdqa xmm2, xmm0
/中取出pandn xmm2,xmm1
。(只有 IvyBridge+ 和 Bulldozer-family/Ryzen 对矢量寄存器具有零延迟movdqa
。)或者,如果您每次都pcmpeqd
在目标寄存器中重新实现全1(可能是因为寄存器压力或因为您没有在循环),那将是您想要pxor
而不是pandn
.
生成一个全为常量pcmpeqb/w/d
的特殊情况是不会对旧值产生错误的依赖(在 Silvermont 上除外),但仍然需要一个执行单元(与 Sandybridge 系列上的异或归零不同)。不过,它很便宜,而且它是编译器用于_mm_set1_epi32(-1)
.
在 IvyBridge 及更高版本以及 Bulldozer-family 和 Ryzen 上, 每次需要时重新创建常量而不是从另一个寄存器中复制会稍微差一些。mov
-XMM 副本的消除避免了占用向量执行单元/端口,以防向量 ALU 执行端口是您的瓶颈。
但它在 Intel P6 系列(Core2/Nehalem)上稍好一些:当在一个问题组中读取太多“冷”寄存器时,寄存器读取停顿可能是一个问题。(参见 Agner Fog 的 microarch pdf https://agner.org/optimize/)。P6 系列已过时,但仍在一些旧机器中使用。如果您有在带有 AVX 的 CPU 上运行的 AVX 版本,您可能希望在代码的非 AVX 版本中对其进行调整。(但 Haswell/Skylake “pentium”/“celeron”仍然是一个东西,而且他们没有 AVX,所以没有 AVX 并不意味着旧 CPU。)