我需要为压缩单体构建某种屏蔽系统,因为我需要对包含少于4个元素的向量使用压缩操作。
例如,我需要这样做:

section .data

align 16
a:      dd      1.5, 2.3, 5.0
align 16
x:      dd      1.0, -3.0, 5.0

global  main

main:   start

     movaps     xmm0, [x]
     movaps     xmm1, [a]
     addps      xmm0, xmm1
     haddps     xmm0, xmm0
     haddps     xmm0, xmm0

这将导致inxmm0
11.8、11.8、11.8、11.8
这样我就可以把其中一个拿到手术结果。
这是必需的,因为代码应该处理用户的输入,其中可能不包含4个元素的倍数,并且,与其编写一个特殊的案例来处理它,我希望重用已经拥有的代码,只做一些细微的更改。
据我所知,在这种情况下,将a移动到xmm0将导致inxmm0
1.5、2.3、5.0、0.0
所以不应该有任何问题,因为添加0不会改变任何东西。
但是如果a是从float*程序传递过来的呢?据我所知,我很有可能将一个不同于C的值作为0.0中复制的第四个元素,因为我是从内存复制而不是处理定义的常量。
当然,这会扰乱我的所有计算,导致不想要的结果,所以我的想法是:我可以根据我有多少元素来“屏蔽”xmm0的内容吗?
这意味着,在这种情况下,我只需要手动将xmm0的第四个元素设置为0,因为需要前三个元素。
这是我写的代码:
section .data

align 16
a:      dd      1.5, 2.3, 5.0, 7.0
align 16
x:      dd      1.0, -3.0, 5.0, 7.0
align 16
mask:   dd      0x00, 0x00, 0x00, 0xFF

section .bss

section .text

global  main

main:   start

        movaps      xmm0, [x]
        movaps      xmm1, [a]
        movaps      xmm2, [mask]    ; move the mask to a support registry

        cmpnltps    xmm3, xmm2      ; this compare should put -NaN where xmm2 has 0xFF
        andps       xmm0, xmm3      ; mask x vector
        andps       xmm1, xmm3      ; mask a vector

        ; let's make the needed operations to compute the result
        addps       xmm0, xmm1
        haddps      xmm0, xmm0
        haddps      xmm0, xmm0

        ; yay! there's 11.8, 11.8, 11.8, 11.8 in xmm0!

        stop

我已经尝试了一些例子,它可以很好地工作,因为我需要,即使我改变了屏蔽排除一些其他值(xmm0将只工作在前2个元素等)。
现在,考虑到我几天前开始与0x00, 0x00, 0xFF, 0xFF合作,我不确定这是否是正确的方法,我也不能用一些例子来证明这是行不通的,所以这里有一个问题:有没有更好的/官方的方法来实现我的需要,如果没有,我的代码是做这项工作呢,还是仅仅因为我使用了一个“幸运”的例子就起作用了?

最佳答案

对于这个带有gcc向量扩展的C代码,

typedef float v4sf __attribute__((vector_size(16)));

v4sf foo(float const *restrict a, float const *restrict b)
{
  float const *restrict aa = __builtin_assume_aligned(a, 16);
  float const *restrict ba = __builtin_assume_aligned(b, 16);
  v4sf av = *(v4sf*)aa;
  v4sf bv = *(v4sf*)ba;
  v4sf sv = av+bv;
  float temp = sv[0]+sv[1]+sv[2];
  v4sf ret = {temp,temp,temp,temp};
  return ret;
}

gcc -Ofast -S生成以下程序集(AT&T语法):
foo:
    movaps  (%rsi), %xmm1       #load 1 of the vectors
    addps   (%rdi), %xmm1       #load the 2.nd vector, add to 1.st
    movaps  %xmm1, %xmm0        #make a copy of the sum
    movaps  %xmm1, %xmm2        #make a second copy
    shufps  $85, %xmm1, %xmm0   #shuffle [3][2][1][0] to [1][1][1][1]
    unpckhps    %xmm1, %xmm1    #unpack [3][2][1][0] to [3][3][2][2]
    addss   %xmm2, %xmm0        #add [3][2][1][0] to [1][1][1][1]
    addss   %xmm1, %xmm0        #add [3][3][2][2] to [3+1][2+1][1+1][0+1]
    shufps  $0, %xmm0, %xmm0    #shuffle [0+1+2] to all positions
    ret

避免从内存中加载常量掩码。

关于c - SSE中的打包 mask ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29985766/

10-11 04:36