Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly XMM寄存器的位求反_Assembly_X86_Bit Manipulation_Sse_Bitwise Not - Fatal编程技术网

Assembly XMM寄存器的位求反

Assembly XMM寄存器的位求反,assembly,x86,bit-manipulation,sse,bitwise-not,Assembly,X86,Bit Manipulation,Sse,Bitwise Not,如何在XMM寄存器中获得值的位求反?据我所知,没有这样的指示。唯一带否定的指令是pandn,但要使用它简单地对一个XMM寄存器中的值进行否定,我必须用1填充另一个XMM寄存器 是否有另一种方法对XMM寄存器中的位求反?或者有没有一种聪明的方法可以在不访问内存的情况下用1填充XMM寄存器?要加载一个包含所有1的寄存器,请使用 pcmpeqd xmm0, xmm0 在这之后,您可以简单地从xmm0中减去xmmX,得到~xmmX,或者使用pandn 您还可以轻松地将其他常量加载到xmm寄存器 pcm

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


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

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

pcmpeqd xmm0, xmm0
在这之后,您可以简单地从
xmm0
中减去
xmmX
,得到
~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的优化指南,

要加载所有1的寄存器,请使用

pcmpeqd xmm0, xmm0
在这之后,您可以简单地从
xmm0
中减去
xmmX
,得到
~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的优化指南,

使用
pxor
和“全一”寄存器。

pandn
也可用,但没有任何优势。在任何情况下,
pandn
使用“全一”常量都可以执行
pxor
无法执行的操作

psubd
也可用(2的补码标识),但比
pandn
更糟糕,因为它在某些CPU上的吞吐量更低(执行端口更少)


PXOR很好,因为它是可交换的。使用AVX,您可以加载一个微型熔断uop,而不是:

vpxor    xmm0, xmm1, [rdi]
VPANDN不能这样做,因为可以是内存或寄存器的操作数是非反转操作数。(但是,如果没有AVX,只需加载
movdqa
dqu
然后加载
pxor
加载结果。一个reg拷贝和一个微融合加载+pxor是3个未使用的域UOP,而不是2个)


或者在没有AVX的情况下,如果要销毁all ones常量而不是正在反转的数据,
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+和推土机系列/Ryzen具有零延迟
movdqa
),或者如果您每次都在目标寄存器中使用
pcmpeqd
对所有延迟进行重物质化(可能是因为寄存器压力,或者因为您没有在循环中执行此操作),这将是另一种情况,您需要
pxor
而不是
pandn


使用
pcmpeqb/w/d
生成一个全一常量是一种特殊情况,它不会对旧值产生错误依赖(Silvermont除外),但仍然需要一个执行单元(与Sandybridge系列上的xor归零不同)。尽管如此,它还是很便宜,而且它是编译器用于
\u mm\u set1\u epi32(-1)

在IvyBridge和更高版本上,以及在推土机系列和Ryzen上,每次需要时重新创建常量而不是从另一个寄存器中复制,情况稍差
mov
-消除XMM拷贝可避免占用向量执行单元/端口,以防向量ALU执行端口成为瓶颈


但在Intel P6系列(Core2/Nehalem)上稍好一些:在问题组中读取太多“冷”寄存器时,寄存器读取暂停可能是一个问题。(参见Agner Fog的Microach pdf)。P6系列已过时,但仍在一些旧机器中使用。如果有一个AVX版本运行在带有AVX的CPU上,您可能希望在非AVX版本的代码中对其进行调优。(但是Haswell/Skylake“pentium”/“celeron”仍然是一个东西,而且他们没有AVX,所以没有AVX并不意味着旧CPU。)

使用
pxor
和“全一”寄存器。

pandn
也可用,但没有任何优势。在任何情况下,
pandn
使用“全一”常量都可以执行
pxor
无法执行的操作

psubd
也可用(2的补码标识),但比
pandn
更糟糕,因为它在某些CPU上的吞吐量更低(执行端口更少)


PXOR很好,因为它是可交换的。使用AVX,您可以加载一个微型熔断uop,而不是:

vpxor    xmm0, xmm1, [rdi]
VPANDN不能这样做,因为可以是内存或寄存器的操作数是非反转操作数。(但是,如果没有AVX,只需加载
movdqa
dqu
然后加载
pxor
加载结果。一个reg拷贝和一个微融合加载+pxor是3个未使用的域UOP,而不是2个)


或者在没有AVX的情况下,如果要销毁all ones常量而不是正在反转的数据,
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+和推土机系列/Ryzen具有零延迟
movdqa
),或者如果您每次都在目标寄存器中使用
pcmpeqd
对所有延迟进行重物质化(可能是因为寄存器压力,或者因为您没有在循环中执行此操作),这将是另一种情况,您需要
pxor
而不是
pandn


使用
pcmpeqb/w/d
生成一个全一常量是一种特殊情况,它不会对旧值产生错误依赖(Silvermont除外),但仍然需要一个执行单元(与Sandybridge系列上的xor归零不同)。尽管如此,它还是很便宜,而且它是编译器用于
\u mm\u set1\u epi32(-1)

在IvyBridge和更高版本上,以及在推土机系列和Ryzen上,每次需要时重新创建常量而不是从另一个寄存器中复制,情况稍差
mov
-消除XMM拷贝可避免占用向量执行单元/端口,以防向量ALU执行端口成为瓶颈

但在英特尔P6上稍好一些