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);
  • 2
    \$\begingroup\$ Explain the downvote. \$\endgroup\$
    – IamIC
    Apr 17, 2020 at 14:16
  • \$\begingroup\$ If this is off-topic, it's because of the missing review context category. You should explain what the wider program is doing (or attempting to do), and show more contextual code. \$\endgroup\$
    – Reinderien
    Apr 17, 2020 at 14:28
  • \$\begingroup\$ Is AVX2 available? Your code looks as if you carefully avoided AVX2 and used only AVX1 instructions. \$\endgroup\$
    – harold
    Apr 17, 2020 at 14:32
  • 1
    \$\begingroup\$ You don't seem to be asking for a code review, which makes this more of a how to question. This is definitely off-topic for this site. \$\endgroup\$
    – pacmaninbw
    Apr 17, 2020 at 17:17
  • 1
    \$\begingroup\$ Is it me or this question was closed because several people did not know what it is about? \$\endgroup\$ Apr 19, 2020 at 5:04

1 Answer 1


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).

  • \$\begingroup\$ Ah, perfect! Thank you! \$\endgroup\$
    – IamIC
    Apr 17, 2020 at 15:01
  • \$\begingroup\$ Is the AVX1 version as efficient as it can be? My code has dual paths. In this case, I didn't know how to use AVX2. \$\endgroup\$
    – IamIC
    Apr 17, 2020 at 15:23
  • 1
    \$\begingroup\$ @IamIC I've added a better AVX1 version \$\endgroup\$
    – harold
    Apr 17, 2020 at 16:10
  • \$\begingroup\$ Nicely done, sir! \$\endgroup\$
    – IamIC
    Apr 17, 2020 at 18:06
  • \$\begingroup\$ This answer does not appear to review the code in question. Please avoid off-topic questions in the future. See rolfl's answer to How to prevent people from answering off-topic questions? for more information. \$\endgroup\$
    – L. F.
    Apr 18, 2020 at 2:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.