re PR tree-optimization/38051 (Miscompilation of glibc's memcmp)
authorRichard Guenther <rguenther@suse.de>
Sat, 15 Nov 2008 15:37:57 +0000 (15:37 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 15 Nov 2008 15:37:57 +0000 (15:37 +0000)
2008-11-15  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/38051
* tree-ssa-alias.c (update_alias_info_1): Manually find
written variables.

* gcc.c-torture/execute/pr38051.c: New testcase.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r141887

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr38051.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index a4e4609..2e34022 100644 (file)
@@ -1,3 +1,9 @@
+2008-11-15  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/38051
+       * tree-ssa-alias.c (update_alias_info_1): Manually find
+       written variables.
+
 2008-11-15  Joshua Kinard  <kumba@gentoo.org>
 
        * doc/invoke.texi (-mfix-r10000): Document.
index 1a4a0d2..dac4651 100644 (file)
@@ -1,3 +1,9 @@
+2008-11-15  Richard Guenther  <rguenther@suse.de>
+       Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/38051
+       * gcc.c-torture/execute/pr38051.c: New testcase.
+
 2008-11-15  Joshua Kinard  <kumba@gentoo.org>
            Richard Sandiford  <rdsandiford@goolemail.com>
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr38051.c b/gcc/testsuite/gcc.c-torture/execute/pr38051.c
new file mode 100644 (file)
index 0000000..3437f73
--- /dev/null
@@ -0,0 +1,205 @@
+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;
+}
+
index 655056b..83800ed 100644 (file)
@@ -2667,6 +2667,17 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
 
       mem_ref_stats->num_mem_stmts++;
 
+      /* Add all decls written to to the list of written variables.  */
+      if (gimple_has_lhs (stmt)
+         && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME)
+       {
+         tree lhs = gimple_get_lhs (stmt);
+         while (handled_component_p (lhs))
+           lhs = TREE_OPERAND (lhs, 0);
+         if (DECL_P (lhs))
+           pointer_set_insert (ai->written_vars, lhs);
+       }
+
       /* Notice that we only update memory reference stats for symbols
         loaded and stored by the statement if the statement does not
         contain pointer dereferences and it is not a call/asm site.
@@ -2689,25 +2700,19 @@ update_alias_info_1 (gimple stmt, struct alias_info *ai)
         dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
         memory symbols in its argument list, but these cases do not
         occur so frequently as to constitute a serious problem.  */
-      if (gimple_stored_syms (stmt))
-       EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
-         {
-           tree sym = referenced_var (i);
-           pointer_set_insert (ai->written_vars, sym);
-           if (!stmt_dereferences_ptr_p
-               && stmt_escape_type != ESCAPE_TO_CALL
-               && stmt_escape_type != ESCAPE_TO_PURE_CONST
-               && stmt_escape_type != ESCAPE_TO_ASM)
-             update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
-         }
-
       if (!stmt_dereferences_ptr_p
-         && gimple_loaded_syms (stmt)
          && stmt_escape_type != ESCAPE_TO_CALL
          && stmt_escape_type != ESCAPE_TO_PURE_CONST
          && stmt_escape_type != ESCAPE_TO_ASM)
-       EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
-         update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
+       {
+         if (gimple_stored_syms (stmt))
+           EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
+             update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 0, 1);
+
+         if (gimple_loaded_syms (stmt))
+           EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
+             update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
+       }
     }
 }