考虑到我们有这个:
....
pxor xmm1, xmm1
movdqu xmm0, [reax]
pcmpeqb xmm0, xmm1
pmovmskb eax, xmm0
test ax , ax
jz .zero
...
有没有办法不使用'pmovmskb'并直接从xmm0测试位掩码(以检查其是否为零)?此操作有任何SSE指令吗?
实际上,我正在搜索类似'ptest xmm0,xmm0'的动作,但是在SSE2中...而不是SSE4
使用ptest
:
ptest
[ptest xmm0, xmm0
jz .zero
如果ptest a, b
is a
为零,则设置ZF;如果b
∧¬a
为零,则设置CF。
但是请注意,b
必须存在SSE 4.1。
否则,我想您的方法是ptest
。
通常不值得在as good as it gets结果上使用SSE4.1 ptest xmm0,xmm0
,尤其是在分支的情况下尤其如此。>
pcmpeqb
是1个uop,并且pmovmskb
或cmp
可以与test
宏融合到Intel和AMD CPU上的另一个单个uop中。在pcmpeqb结果上总共分支了2微码。
但是jnz
是2 uops,它的第二个uop cant
当您无需使用ptest
即可直接使用ptest
时,收支平衡。测试整个向量中的任何/所有位(或使用掩码,一些位)。如果将其用于cmov或setcc而不是分支,则实际上是一个胜利。即使代码数量相同,这也是代码大小的胜利。
您可以分摊对多个向量的检查。
例如pcmp
将某些向量组合在一起,然后检查所有字节为零。或将por
一些向量放在一起,然后检查any零。 (诸如strlen和strchr之类的glibc字符串函数使用此技巧来并行检查整个向量的高速缓存行,然后在离开循环后找出其来源。)您可以合并pcmpeq结果而不是原始输入,例如对于memchr。在这种情况下,可以使用pminub
代替pand
在any
pminub
上运行的端口要多于pand
,因此对向量ALU的竞争较少。