re PR target/27363 (ARM gcc 4.1 optimization bug)
authorPaul Brook <paul@codesourcery.com>
Thu, 20 Jul 2006 13:57:31 +0000 (13:57 +0000)
committerPaul Brook <pbrook@gcc.gnu.org>
Thu, 20 Jul 2006 13:57:31 +0000 (13:57 +0000)
2006-07-20  Paul Brook  <paul@codesourcery.com>

PR 27363
gcc/
* cse.c (cse_insn): Add destination addresses to hash table. Check if
they are invalidated by this instruction.

gcc/testsuite/
* gcc.dg/pr27363.c: New test.

From-SVN: r115614

gcc/ChangeLog
gcc/cse.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr27363.c [new file with mode: 0644]

index 213f3d817f1ab69b2cf3dbc24a7a5282298630fa..5d9e52ecac155282842b8a29035f3a67f2ef2fcd 100644 (file)
@@ -1,3 +1,9 @@
+2006-07-20  Paul Brook  <paul@codesourcery.com>
+
+       PR 27363
+       * cse.c (cse_insn): Add destination addresses to hash table. Check if
+       they are invalidated by this instruction.
+
 2006-07-21  Danny Smith  <dannysmith@users.sourceforge.net>
 
        PR target/28427
index 65a4a0ab172723cc3fbfab4e956ea511c8200477..9e6fec091da8b057a85c1b6921696a9a2b5e8481 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4739,6 +4739,8 @@ struct set
   unsigned src_const_hash;
   /* Table entry for constant equivalent for SET_SRC, if any.  */
   struct table_elt *src_const_elt;
+  /* Table entry for the destination address.  */
+  struct table_elt *dest_addr_elt;
 };
 
 static void
@@ -5970,6 +5972,40 @@ cse_insn (rtx insn, rtx libcall_insn)
         so that the destination goes into that class.  */
       sets[i].src_elt = src_eqv_elt;
 
+  /* Record destination addresses in the hash table.  This allows us to
+     check if they are invalidated by other sets.  */
+  for (i = 0; i < n_sets; i++)
+    {
+      if (sets[i].rtl)
+       {
+         rtx x = sets[i].inner_dest;
+         struct table_elt *elt;
+         enum machine_mode mode;
+         unsigned hash;
+
+         if (MEM_P (x))
+           {
+             x = XEXP (x, 0);
+             mode = GET_MODE (x);
+             hash = HASH (x, mode);
+             elt = lookup (x, hash, mode);
+             if (!elt)
+               {
+                 if (insert_regs (x, NULL, 0))
+                   {
+                     rehash_using_reg (x);
+                     hash = HASH (x, mode);
+                   }
+                 elt = insert (x, NULL, hash, mode);
+               }
+
+             sets[i].dest_addr_elt = elt;
+           }
+         else
+           sets[i].dest_addr_elt = NULL;
+       }
+    }
+
   invalidate_from_clobbers (x);
 
   /* Some registers are invalidated by subroutine calls.  Memory is
@@ -6062,12 +6098,20 @@ cse_insn (rtx insn, rtx libcall_insn)
     }
 
   /* We may have just removed some of the src_elt's from the hash table.
-     So replace each one with the current head of the same class.  */
+     So replace each one with the current head of the same class.
+     Also check if destination addresses have been removed.  */
 
   for (i = 0; i < n_sets; i++)
     if (sets[i].rtl)
       {
-       if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0)
+       if (sets[i].dest_addr_elt
+           && sets[i].dest_addr_elt->first_same_value == 0)
+         {
+           /* The elt was removed, which means this destination s not
+              valid after this instruction.  */
+           sets[i].rtl = NULL_RTX;
+         }
+       else if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0)
          /* If elt was removed, find current head of same class,
             or 0 if nothing remains of that class.  */
          {
index f6ca4c799aed73f85b1f5586d6ca6bed3ec8b75d..414d3143d99759b7a5da48eaf402ed688f1378e7 100644 (file)
@@ -1,3 +1,8 @@
+2006-07-20  Paul Brook  <paul@codesourcery.com>
+
+       PR 27363
+       * gcc.dg/pr27363.c: New test.
+
 2006-07-19  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/28338
diff --git a/gcc/testsuite/gcc.dg/pr27363.c b/gcc/testsuite/gcc.dg/pr27363.c
new file mode 100644 (file)
index 0000000..40a3c6b
--- /dev/null
@@ -0,0 +1,39 @@
+/* PR27363.  CSE was breaking on the arm store multiple insn used for
+   structure copies.  */
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+extern void abort (void);
+
+struct snd_mask {
+    unsigned int bits[6];
+};
+
+static int __attribute__((noinline))
+snd_mask_refine(struct snd_mask *mask)
+{
+  struct snd_mask old;
+
+  old = *mask;
+  if (mask->bits[0]==0 && mask->bits[1]==0)
+    return 1;
+
+  return old.bits[0] != mask->bits[0];
+}
+
+int main(int argc, char *argv[])
+{
+  struct snd_mask mask;
+
+
+  mask.bits[0] = 23;
+  mask.bits[1] = 42;
+  mask.bits[2] = 0;
+  mask.bits[3] = 0;
+  mask.bits[4] = 0; 
+  mask.bits[5] = 0;
+
+
+  if (snd_mask_refine(&mask))
+    abort();
+  return 0;
+}