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

Reply via email to