Efficiently shift elements right by one in an __mm256 vector The code below correctly shifts v256f_stats by one and puts the results into v256f_x3. This is then used to get the delta between n[1..7] and n[0..6]. The undefined element in the output is not an issue.

Is there a more efficient way of doing this?

// create a shift-by-1 copy
v256f_x1 = _mm256_permute2f128_ps(v256f_stats, v256f_stats, 0);
v256f_x2 = _mm256_permute2f128_ps(v256f_stats, v256f_stats, 0x11);
v256f_x1 = _mm256_permute_ps(v256f_x1, 0b10010011);
v256f_x2 = _mm256_permute_ps(v256f_x2, 0b10010011);
v256f_x3 = _mm256_blend_ps(v256f_x1, v256f_x2, 0b11100000);
With AVX2, it could be done with one vpermps aka _mm256_permutevar8x32_ps:

auto shifted = _mm256_permutevar8x32_ps(v256f_stats, _mm256_set_epi32(6, 5, 4, 3, 2, 1, 0, 0));


Clang rewrites the original shuffle into the same assembly.



Here is an alternative with just AVX1:

auto stats00 = _mm256_permute2f128_ps(v256f_stats, v256f_stats, 0);
stats00 = _mm256_blend_ps(stats00, v256f_stats, 0b01111111);
auto shifted = _mm256_permute_ps(stats00, _MM_SHUFFLE(2, 1, 0, 3));


Roughly the same idea as the original, but reworked so that the _mm256_permute_ps comes after the blend so it only needs to be done once.

This time Clang is too clever for its own good, it replaces the blend/shuffle with two shuffles, which is worse because the blend was cheaper (p015, while the shuffles are p5).