Test if any byte in an xmm register is 0

Viewed 1149

I am currently teaching myself SIMD and am writing a rather simple String processing subroutine. I am however restricted to SSE2, which makes me unable to utilize ptest to find the null terminal.

The way I am currently trying to find the null terminal makes my SIMD loop have >16 instructions, which kind of defeats the purpose of using SIMD - or atleast makes it not as worthwhile as it could be.

//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

I was wondering if there is any faster way to do this without ptest or whether this is the best it is gonna get and I'll have to just optimize the rest of the loop some more.

Note: I am ensuring that the String address for which the loop using SIMD is entered is 16B aligned to allow for aligned instructions.

1 Answers

You can use _mm_movemask_epi8 (pmovmskb instruction) to obtain a bit mask from the result of comparison (the resulting mask contains the most significant bits of each byte in the vector). Then, testing for whether any of the bytes are zero means testing if any of the 16 bits in the mask are non-zero.

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

After finding a vector with any matches, you can find the first match position with bsf eax,eax to get the bit-index in the bitmask, which is also the byte index in the 16-byte vector.

Alternatively, you can check for all bytes matching (e.g. like you'd do in memcmp / strcmp) with pcmpeqb / pmovmskb / cmp eax, 0xffff to check that all bits are set, instead of checking for at least 1 bit set.

Related