代码之家  ›  专栏  ›  技术社区  ›  Rames

XMM寄存器的位取反

  •  1
  • Rames  · 技术社区  · 9 年前

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

    有没有另一种方法可以对XMM寄存器中的位取反?或者有没有一种聪明的方法来填充XMM寄存器 1. 不访问内存?

    2 回复  |  直到 6 年前
        1
  •  6
  •   phuclv    9 年前

    要加载所有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

        2
  •  5
  •   Peter Cordes    6 年前

    使用 pxor 所有1寄存器。

    pandn 也可用,但没有任何优势。不存在以下情况 潘德恩 使用all ones常量可以让你做任何你做不到的事情 像素 .

    psubd 也可用(2的补码身份),但比 潘德恩 因为它在一些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 加载,然后 像素 负载结果。一个reg拷贝和一个微融合加载+pxor总共是3个未融合域uops,而2)


    或者没有AVX,如果你想破坏所有1常量而不是你正在反转的数据, 像素 再次获胜:

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

    你可以坐一辆 移动dqa 偏离关键路径与。 movdqa xmm2, xmm0 / pandn xmm2,xmm1 。(只有IvyBridge+和推土机系列/Ryzen具有零延迟 移动dqa 用于向量调节器)或者,如果你每次都用 pcmpeqd 在目标寄存器中(可能是因为寄存器压力或不是在循环中执行),这将是另一种情况 像素 而不是 潘德恩 .


    使用 pcmpeqb/w/d 特殊情况下,不会对旧值有错误依赖(除了在Silvermont上有),但仍然需要执行单元(与Sandybridge系列上的xor归零不同)。尽管如此,它还是很便宜,而且它是编译器用来做的 _mm_set1_epi32(-1) .

    每次需要时重新创建常量,而不是从另一个寄存器复制 轻微地 在常春藤桥和后来,推土机家族和Ryzen的情况更糟。 mov -消除XMM拷贝可以避免占用矢量执行单元/端口,以防矢量ALU执行端口成为您的瓶颈。

    但它在Intel P6系列(Core2/Nehalem)上略胜一筹:当读取问题组中过多的“冷”寄存器时,寄存器读取暂停可能是一个问题。(参见Agner Fog的微阵列pdf https://agner.org/optimize/ ). P6系列已经过时,但仍在一些旧机器中使用。如果您有一个在带有AVX的CPU上运行的AVX版本,您可能需要在代码的非AVX版本中调整它。(但哈斯韦尔/天湖“pentium”/“celeron”仍然是一个东西,他们没有AVX,所以没有AVX并不意味着旧CPU。)