我需要为压缩单体构建某种屏蔽系统,因为我需要对包含少于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
这将导致in
xmm0
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/