c++simdavxavx2mmx

How to create a 8 bit mask from lsb of __m64 value?


I have a use case, where I have array of bits each bit is represented as 8 bit integer for example uint8_t data[] = {0,1,0,1,0,1,0,1}; I want to create a single integer by extracting only lsb of each value. I know that using int _mm_movemask_pi8 (__m64 a) function I can create a mask but this intrinsic only takes a msb of a byte not lsb. Is there a similar intrinsic or efficient method to extract lsb to create single 8 bit integer?


Solution

  • There is no direct way to do it, but obviously you can simply shift the lsb into the msb and then extract it:

    _mm_movemask_pi8(_mm_slli_si64(x, 7))
    

    Using MMX these days is strange and should probably be avoided.

    Here is an SSE2 version, still reading only 8 bytes:

    int lsb_mask8(uint8_t* bits) {
        __m128i x = _mm_loadl_epi64((__m128i*)bits);
        return _mm_movemask_epi8(_mm_slli_epi64(x, 7));
    }
    

    Using SSE2 instead of MMX avoids the needs for EMMS