typedef __SIZE_TYPE__ size_t; static int mymemcmp1 (unsigned long int, unsigned long int) __attribute__ ((__nothrow__));
__inline static int mymemcmp1 (unsigned long int a, unsigned long int b) { long int srcp1 = (long int) &a; long int srcp2 = (long int) &b; unsigned long int a0, b0; do { a0 = ((unsigned char *) srcp1)[0]; b0 = ((unsigned char *) srcp2)[0]; srcp1 += 1; srcp2 += 1; } while (a0 == b0); return a0 - b0; } static int mymemcmp2 (long, long, size_t) __attribute__ ((__nothrow__)); static int mymemcmp2 (long int srcp1, long int srcp2, size_t len) { unsigned long int a0, a1; unsigned long int b0, b1; switch (len % 4) { default: case 2: a0 = ((unsigned long int *) srcp1)[0]; b0 = ((unsigned long int *) srcp2)[0]; srcp1 -= 2 * (sizeof (unsigned long int)); srcp2 -= 2 * (sizeof (unsigned long int)); len += 2; goto do1; case 3: a1 = ((unsigned long int *) srcp1)[0]; b1 = ((unsigned long int *) srcp2)[0]; srcp1 -= (sizeof (unsigned long int)); srcp2 -= (sizeof (unsigned long int)); len += 1; goto do2; case 0: if (16 <= 3 * (sizeof (unsigned long int)) && len == 0) return 0; a0 = ((unsigned long int *) srcp1)[0]; b0 = ((unsigned long int *) srcp2)[0]; goto do3; case 1: a1 = ((unsigned long int *) srcp1)[0]; b1 = ((unsigned long int *) srcp2)[0]; srcp1 += (sizeof (unsigned long int)); srcp2 += (sizeof (unsigned long int)); len -= 1; if (16 <= 3 * (sizeof (unsigned long int)) && len == 0) goto do0; } do { a0 = ((unsigned long int *) srcp1)[0]; b0 = ((unsigned long int *) srcp2)[0]; if (a1 != b1) return mymemcmp1 ((a1), (b1)); do3: a1 = ((unsigned long int *) srcp1)[1]; b1 = ((unsigned long int *) srcp2)[1]; if (a0 != b0) return mymemcmp1 ((a0), (b0)); do2: a0 = ((unsigned long int *) srcp1)[2]; b0 = ((unsigned long int *) srcp2)[2]; if (a1 != b1) return mymemcmp1 ((a1), (b1)); do1: a1 = ((unsigned long int *) srcp1)[3]; b1 = ((unsigned long int *) srcp2)[3]; if (a0 != b0) return mymemcmp1 ((a0), (b0)); srcp1 += 4 * (sizeof (unsigned long int)); srcp2 += 4 * (sizeof (unsigned long int)); len -= 4; } while (len != 0); do0: if (a1 != b1) return mymemcmp1 ((a1), (b1)); return 0; } static int mymemcmp3 (long, long, size_t) __attribute__ ((__nothrow__)); static int mymemcmp3 (long int srcp1, long int srcp2, size_t len) { unsigned long int a0, a1, a2, a3; unsigned long int b0, b1, b2, b3; unsigned long int x; int shl, shr; shl = 8 * (srcp1 % (sizeof (unsigned long int))); shr = 8 * (sizeof (unsigned long int)) - shl; srcp1 &= -(sizeof (unsigned long int)); switch (len % 4) { default: case 2: a1 = ((unsigned long int *) srcp1)[0]; a2 = ((unsigned long int *) srcp1)[1]; b2 = ((unsigned long int *) srcp2)[0]; srcp1 -= 1 * (sizeof (unsigned long int)); srcp2 -= 2 * (sizeof (unsigned long int)); len += 2; goto do1; case 3: a0 = ((unsigned long int *) srcp1)[0]; a1 = ((unsigned long int *) srcp1)[1]; b1 = ((unsigned long int *) srcp2)[0]; srcp2 -= 1 * (sizeof (unsigned long int)); len += 1; goto do2; case 0: if (16 <= 3 * (sizeof (unsigned long int)) && len == 0) return 0; a3 = ((unsigned long int *) srcp1)[0]; a0 = ((unsigned long int *) srcp1)[1]; b0 = ((unsigned long int *) srcp2)[0]; srcp1 += 1 * (sizeof (unsigned long int)); goto do3; case 1: a2 = ((unsigned long int *) srcp1)[0]; a3 = ((unsigned long int *) srcp1)[1]; b3 = ((unsigned long int *) srcp2)[0]; srcp1 += 2 * (sizeof (unsigned long int)); srcp2 += 1 * (sizeof (unsigned long int)); len -= 1; if (16 <= 3 * (sizeof (unsigned long int)) && len == 0) goto do0; } do { a0 = ((unsigned long int *) srcp1)[0]; b0 = ((unsigned long int *) srcp2)[0]; x = (((a2) >> (shl)) | ((a3) << (shr))); if (x != b3) return mymemcmp1 ((x), (b3)); do3: a1 = ((unsigned long int *) srcp1)[1]; b1 = ((unsigned long int *) srcp2)[1]; x = (((a3) >> (shl)) | ((a0) << (shr))); if (x != b0) return mymemcmp1 ((x), (b0)); do2: a2 = ((unsigned long int *) srcp1)[2]; b2 = ((unsigned long int *) srcp2)[2]; x = (((a0) >> (shl)) | ((a1) << (shr))); if (x != b1) return mymemcmp1 ((x), (b1)); do1: a3 = ((unsigned long int *) srcp1)[3]; b3 = ((unsigned long int *) srcp2)[3]; x = (((a1) >> (shl)) | ((a2) << (shr))); if (x != b2) return mymemcmp1 ((x), (b2)); srcp1 += 4 * (sizeof (unsigned long int)); srcp2 += 4 * (sizeof (unsigned long int)); len -= 4; } while (len != 0); do0: x = (((a2) >> (shl)) | ((a3) << (shr))); if (x != b3) return mymemcmp1 ((x), (b3)); return 0; } __attribute__ ((noinline)) int mymemcmp (const void *s1, const void *s2, size_t len) { unsigned long int a0; unsigned long int b0; long int srcp1 = (long int) s1; long int srcp2 = (long int) s2; if (srcp1 % (sizeof (unsigned long int)) == 0) return mymemcmp2 (srcp1, srcp2, len / (sizeof (unsigned long int))); else return mymemcmp3 (srcp1, srcp2, len / (sizeof (unsigned long int))); } char buf[256] __attribute__((aligned (16))); char buf2[256] __attribute__((aligned (16))); int main (void) { __builtin_memcpy (buf + 9, "\x1\x37\x82\xa7\x55\x49\x9d\xbf\xf8\x44\xb6\x55\x17\x8e\xf9", 15); __builtin_memcpy (buf2 + 24, "\x1\x37\x82\xa7\x55\x49\xd0\xf3\xb7\x2a\x6d\x23\x71\x49\x6a", 15); if (mymemcmp (buf + 9, buf2 + 24, 33) != -51) __builtin_abort (); return 0; } is miscompiled at -O2 or -O2 -fno-strict-aliasing, doesn't return the expected -51, but something that depends on the stack content etc. (e.g. prints different value when run from gdb's inferior and in the program). Note mymemcmp has a couple of lines that weren't affecting the result removed. -- Summary: [4.4 Regression] Miscompilation of glibc's memcmp Product: gcc Version: 4.4.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jakub at gcc dot gnu dot org GCC target triplet: x86_64-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38051