title: AVX2, How to Efficiently Load Four Integers to Even Indices of a 256 Bit Register and Copy to Odd Indices?
body: <p>I have an aligned array of integers in memory containing indices I0, I1, I2, I3. My goal is to get them into a __m256i register containing I0, I0 + 1, I1, I1 + 1, I2, I2 + 1, I3, I3 + 1. The hard part is getting them into the 256 bit register as I0, I0, I1, I1, I2, I2, I3, I3, after which I can just add a register containing 0, 1, 0, 1, 0, 1, 0, 1. </p>
  
  <p>I found the intrinsic, _mm256_castsi128_si256, which lets me load the 4 integers into the lower 128 bits of the 256 bit register, but I'm struggling to find the best intrinsics to use from there. </p>
  
  <p>Any help would be appreciated. I have access to all SSE versions, AVX, and AVX2 and would like to do this using intrinsics only.</p>
  
  <p>Edit:</p>
  
  <p>I think this works, but I'm not how efficient it is...in the process of testing it.</p>
  
  <pre><code>// _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);
  </code></pre>
  
  <p>Edit2: The above code does not work because _mm256_unpacklo_epi32 does not behave the way I thought. The code above will result in I0, I0+1, I1, I1+1, I0,I0+1, I1, I1+1.</p>
  
  <p>Edit3: The following code works, though again I'm not sure if it's the most efficient:</p>
  
  <pre><code>__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);
  </code></pre>