测试 xmm 寄存器中的任何字节是否为 0



我目前正在自学 SIMD,并正在编写一个相当简单的字符串处理子例程。但是,我仅限于SSE2,这使我无法使用ptest来查找空终端。

我目前试图找到空终端的方式使我的 SIMD 循环具有>16 条指令,这有点违背了使用 SIMD 的目的 - 或者至少使它没有应有的价值。

//Check for null byte
pxor xmm4, xmm4
pcmpeqb xmm4, [rdi]                                   //Generate bitmask
movq rax, xmm4
test rax, 0xffffffffffffffff                          //Test low qword
jnz .Lepilogue
movhlps xmm4, xmm4                                    //Move high into low qword
movq rax, xmm4
test rax, 0xffffffffffffffff                          //Test high qword
jz .LsimdLoop                                         //No terminal was found, keep looping

我想知道是否有任何更快的方法可以在没有 ptest 的情况下做到这一点,或者这是否是最好的,我将不得不进一步优化循环的其余部分。

注意:我确保输入使用 SIMD 循环的字符串地址为 16B,以允许对齐指令。

您可以使用_mm_movemask_epi8(pmovmskb指令(从比较结果中获取位掩码(生成的掩码包含向量中每个字节的最高有效位(。然后,测试是否有任何字节为零意味着测试掩码中的 16 位中的任何一个是否不为零。

pxor xmm4, xmm4
pcmpeqb xmm4, [rdi]
pmovmskb eax, xmm4
test eax, eax          ; ZF=0 if there are any set bits = any matches
jnz .found_a_zero

找到具有任何匹配项的向量后,您可以找到第一个带有bsf eax,eax的匹配位置,以获取位掩码中的位索引,这也是 16 字节向量中的字节索引。

或者,您可以检查所有字节匹配(例如,就像您在 memcmp/strcmp 中所做的那样(与pcmpeqb/pmovmskb/cmp eax, 0xffff以检查是否设置了所有位,而不是检查至少 1 位设置。

最新更新