Search code examples
assemblyx86ssesimd

How to compare two vectors using SIMD and get a single boolean result?


I have two vectors of 4 integers each and I'd like to use a SIMD command to compare them (say generate a result vector where each entry is 0 or 1 according to the result of the comparison).

Then, I'd like to compare the result vector to a vector of 4 zeros and only if they're equal do something.

Do you know what SIMD commands I can use to do it?


Solution

  • To compare two SIMD vectors:

    #include <stdint.h>
    #include <xmmintrin.h>
    
    int32_t __attribute__ ((aligned(16))) vector1[4] = { 1, 2, 3, 4 };
    int32_t __attribute__ ((aligned(16))) vector2[4] = { 1, 2, 2, 2 };
    int32_t __attribute__ ((aligned(16))) result[4];
    
    __m128i v1 = _mm_load_si128((__m128i *)vector1);
    __m128i v2 = _mm_load_si128((__m128i *)vector2);
    __m128i vcmp = _mm_cmpeq_epi32(v1, v2);
    _mm_store_si128((__m128i *)result, vcmp);
    

    Notes:

    • data is assumed to be 32 bit integers
    • vector1, vector2, result all need to be 16 byte aligned
    • result will be -1 for equal, 0 for not equal ({ -1, -1, 0, 0 } for above code example)

    UPDATE

    If you just want a single Boolean result for the case where all 4 elements match then you can do it like this:

    #include <stdint.h>
    #include <xmmintrin.h>
    
    int32_t __attribute__ ((aligned(16))) vector1[4] = { 1, 2, 3, 4 };
    int32_t __attribute__ ((aligned(16))) vector2[4] = { 1, 2, 2, 2 };
    
    __m128i v1 = _mm_load_si128((__m128i *)vector1);
    __m128i v2 = _mm_load_si128((__m128i *)vector2);
    __m128i vcmp = _mm_cmpeq_epi32(v1, v2);
    uint16_t mask = _mm_movemask_epi8(vcmp);
    int result = (mask == 0xffff);