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]); } };