[Bug target/87853] New: _mm_cmpgt_epi8 broken with -funsigned-char

derek.mauro at gmail dot com gcc-bugzilla@gcc.gnu.org
Thu Nov 1 15:08:00 GMT 2018


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853

            Bug ID: 87853
           Summary: _mm_cmpgt_epi8 broken with -funsigned-char
           Product: gcc
           Version: 7.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: derek.mauro at gmail dot com
  Target Milestone: ---

_mm_cmpgt_epi8 (and probably some related methods) are broken with
-funsigned-char

https://software.intel.com/en-us/node/524239 says specifically that it
"compares the 16 *signed* 8-bit integers in a and the 16 *signed* 8-bit
integers in b for greater than."

GCC's implementation of _mm_cmpgt_epi8:
https://github.com/gcc-mirror/gcc/blob/913b81c4d40ca6e1b157ea5785376d8de58b42fc/gcc/config/i386/emmintrin.h#L1331-L1335

and __v16qi:
https://github.com/gcc-mirror/gcc/blob/913b81c4d40ca6e1b157ea5785376d8de58b42fc/gcc/config/i386/emmintrin.h#L47

So I think a type with "signed char" instead of just "char" is needed to
implement _mm_cmpgt_epi8 correctly

Clang seems to get this right:
https://github.com/llvm-mirror/clang/blob/5fd1ab66bf97297c2b71ce3ec2bb33d579bca06e/lib/Headers/emmintrin.h#L3247-L3253

Here is a small repro program that you can compile with and without
-funsigned-char to see the difference:

#include <stdio.h>
#include <x86intrin.h>

int main() {
  int i;
  signed char a[16] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1};
  signed char b[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  __m128i c = _mm_cmpgt_epi8(_mm_load_si128((const __m128i*)a),
                             _mm_load_si128((const __m128i*)b));
  for (i = 0; i < 16; ++i) {
    unsigned char* result = (unsigned char*)&c;
    printf("result[%d]=%d\n", i, (int)result[i]);
  }
};


More information about the Gcc-bugs mailing list