Search code examples
c++x86ssesimdavx

Extracting ints and shorts from a struct using AVX?


I have a struct which contains a union between various data members and an AVX type to load all the bytes in one load. My code looks like:

#include <immintrin.h>

union S{
    struct{
        int32_t a;
        int32_t b;
        int16_t c;
        int16_t d;
    };

    __m128i x;
}

I'd like to use the AVX register to load the data all together and then separately extract the four members in to int32_t and int16_t local variables.

How would I go about doing this? I am unsure how I can separate the data members from each other when extracting from the AVX register?

EDIT: Was looking for answers in terms of GCC intrinsics.

EDIT2: Have updated the code to swap struct with union.


Solution

  • You can extract 16 bit elements from an __m128i using _mm_extract_epi16 (requires SSE2):

    int16_t v = _mm_extract_epi16 (v, 4);  // extract element 4
    

    For 32 bit elements use _mm_extract_epi32 (requires SSE4.1)

    int32_t v = _mm_extract_epi32 (v, 0);  // extract element 0
    

    See: Intel Intrinsics Guide


    Assuming your struct is declared as:

    union S{
        struct{
            int32_t a;
            int32_t b;
            int16_t c;
            int16_t d;
        };
    
        __m128i x;
    }
    

    then you would extract elements a, b, c, d as follows:

    S s = { { 1, 2, 3, 4 } };
    
    __m128i v = _mm_loadu_si128((__m128i *)&s);
    
    int32_t a = _mm_extract_epi32 (v, 0);
    int32_t b = _mm_extract_epi32 (v, 1);
    int16_t c = _mm_extract_epi16 (v, 4);
    int16_t d = _mm_extract_epi16 (v, 5);