AVX2, ¿Cómo cargar eficientemente cuatro enteros en índices pares de un registro de 256 bits y copiar en índices impares?

Tengo una matriz alineada de enteros en la memoria que contiene los índices I0, I1, I2, I3. Mi objetivo es llevarlos a un registro __m256i que contenga I0, I0 + 1, I1, I1 + 1, I2, I2 + 1, I3, I3 + 1. La parte difícil es llevarlos al registro de 256 bits como I0, I0 , I1, I1, I2, I2, I3, I3, después de lo cual puedo agregar un registro que contiene 0, 1, 0, 1, 0, 1, 0, 1.

Encontré el intrínseco, _mm256_castsi128_si256, que me permite cargar los 4 enteros en los 128 bits inferiores del registro de 256 bits, pero estoy luchando por encontrar los mejores intrínsecos para usar desde allí.

Cualquier ayuda sería apreciada. Tengo acceso a todas las versiones SSE, AVX y AVX2 y me gustaría hacer esto usando solo intrínsecos.

Editar:

Creo que esto funciona, pero no sé cuán eficiente es ... en el proceso de probarlo.

// _mm128_load_si128: Loads 4 integer values into a temporary 128bit register.
// _mm256_broadcastsi128_si256: Copies 4 integer values in the 128 bit register to the low and high 128 bits of the 256 bit register.
__m256i tmpStuff = _mm256_broadcastsi128_si256 ((_mm_load_si128((__m128i*) indicesArray)));

// _mm256_unpacklo_epi32: Interleaves the integer values of source0 and source1.
__m256i indices = _mm256_unpacklo_epi32(tmpStuff, tmpStuff);

__m256i regToAdd = _mm256_set_epi32 (0, 1, 0, 1, 0, 1, 0, 1);
indices = _mm256_add_epi32(indices, regToAdd);

Edit2: el código anterior no funciona porque _mm256_unpacklo_epi32 no se comporta de la manera que pensaba. El código anterior dará como resultado I0, I0 + 1, I1, I1 + 1, I0, I0 + 1, I1, I1 + 1.

Edit3: el siguiente código funciona, aunque nuevamente no estoy seguro de si es el más eficiente:

__m256i tmpStuff = _mm256_castsi128_si256(_mm_loadu_si128((__m128i*) indicesArray));
__m256i mask = _mm256_set_epi32 (3, 3, 2, 2, 1, 1, 0, 0);
__m256i indices= _mm256_permutevar8x32_epi32(tmpStuff, mask);
__m256i regToAdd = _mm256_set_epi32 (1, 0, 1, 0, 1, 0, 1, 0); // Set in reverse order.
indices= _mm256_add_epi32(indices, regToAdd);

Respuestas a la pregunta(1)

Su respuesta a la pregunta