[llvm-bugs] [Bug 27320] New: [AVX2] vpermd + vpshufb intrinsics merged into wrong code at -O1 and higher

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Apr 11 20:10:44 PDT 2016


            Bug ID: 27320
           Summary: [AVX2] vpermd + vpshufb intrinsics merged into wrong
                    code at -O1 and higher
           Product: new-bugs
           Version: 3.8
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: peter at cordes.ca
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

clang 3.8 (but not clang 3.7.1) mis-compiles a sequence of two shuffles.  


__m256i doubleshuff(__m256i in) {
  const __m256i byteshuf =  ...;
  const __m256i lane_adjust_shuf = ...;

  in = _mm256_permutevar8x32_epi32(in, lane_adjust_shuf);
  return _mm256_shuffle_epi8(in, byteshuf);

clang 3.8.1-svn265380-1~exp1 (from llvm repo for Ubuntu 15.10) compiles that to
  (with -O3 -march=haswell):

        vmovdqa ymm0, ymmword ptr [rip + .LCPI3_0] # ymm0 = [0,1,2,2,3,4,5,5]
        vpshufb ymm0, ymm0, ymmword ptr [rip + .LCPI3_1] # ymm0 =

which is obviously wrong because it doesn't depend on the input.  It's
shuffling the vpermd shuffle mask instead of shuffling the input.

gcc 5.2 emits:

        vmovdqa ymm1, YMMWORD PTR .LC7[rip]
        vpermd  ymm0, ymm1, ymm0
        vpshufb ymm0, ymm0, YMMWORD PTR .LC8[rip]

I created a test-case that exits with true or false status, suitable for
testing with git bisect.  (I don't have a checkout of the clang tree myself, or
a fast machine).


#include <immintrin.h>
#include <assert.h>
#include <string.h>

__m256i doubleshuff(__m256i in) {
  const __m256i byteshuf =  _mm256_setr_epi8(0,1,1,2, 3,4,4,5, 6,7,7,8,
                         0,1,1,2, 3,4,4,5, 6,7,7,8, 9,10,10,11);
// or broadcast128

  const __m256i lane_adjust_shuf = _mm256_setr_epi32(0,1,2,2, 3,4,5,5);
//  const __m256i lane_adjust_shuf =
_mm256_cvtepu8_epi32(_mm_setr_epi8(0,1,2,2, 3,4,5,5,
//               /* unused padding that isn't optimized away :( */     
0,0,0,0, 0,0,0,0));

  in = _mm256_permutevar8x32_epi32(in, lane_adjust_shuf);
  return _mm256_shuffle_epi8(in, byteshuf);

static unsigned char dst[33];
static const unsigned char src[33] =

static const unsigned char good_output[33] =

// return false if result doesn't match
int shuffle_test(void) {
    __m256i srcv = _mm256_loadu_si256((const __m256i*)src);
    __m256i expanded = doubleshuff(srcv);
    _mm256_storeu_si256((__m256i*)dst, expanded);
    return !memcmp(dst, good_output, 32);

int main(int argc, char**argv) {
    int test_passed = shuffle_test();
//    assert(test_passed);
    return !test_passed;

See also this code and a bigger loop using it on godbolt:

You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160412/e55d5b46/attachment.html>

More information about the llvm-bugs mailing list