OSDN Git Service

* reload1.c (reload_cse_noop_set_p): Return false if mode of
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Apr 2003 01:07:12 +0000 (01:07 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Apr 2003 01:07:12 +0000 (01:07 +0000)
SET_DEST is not the same as that returned by...
* cselib.h (cselib_reg_set_mode): ... new function.
* cselib.c (cselib_reg_set_mode): Define it.
(REG_VALUES): Document semantics of first element as set mode.
(cselib_subst_to_values): Skip first element if ELT is NULL.
(cselib_lookup): Likewise.  Insert past the first element.
(cselib_invalidate_regno): NULLify first element.
(cselib_record_set): Set first element.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65713 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cselib.c
gcc/cselib.h
gcc/reload1.c

index 19fdf5a..a34da40 100644 (file)
@@ -1,3 +1,15 @@
+2003-04-16  Alexandre Oliva  <aoliva@redhat.com>
+
+       * reload1.c (reload_cse_noop_set_p): Return false if mode of
+       SET_DEST is not the same as that returned by...
+       * cselib.h (cselib_reg_set_mode): ... new function.
+       * cselib.c (cselib_reg_set_mode): Define it.
+       (REG_VALUES): Document semantics of first element as set mode.
+       (cselib_subst_to_values): Skip first element if ELT is NULL.
+       (cselib_lookup): Likewise.  Insert past the first element.
+       (cselib_invalidate_regno): NULLify first element.
+       (cselib_record_set): Set first element.
+
 2003-04-16  Olivier Hainque <hainque@act-europe.fr>
 
         * tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions.
index 3aac058..cf3394f 100644 (file)
@@ -1,6 +1,6 @@
 /* Common subexpression elimination library for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -99,9 +99,13 @@ static int n_useless_values;
 /* Number of useless values before we remove them from the hash table.  */
 #define MAX_USELESS_VALUES 32
 
-/* This table maps from register number to values.  It does not contain
-   pointers to cselib_val structures, but rather elt_lists.  The purpose is
-   to be able to refer to the same register in different modes.  */
+/* This table maps from register number to values.  It does not
+   contain pointers to cselib_val structures, but rather elt_lists.
+   The purpose is to be able to refer to the same register in
+   different modes.  The first element of the list defines the mode in
+   which the register was set; if the mode is unknown or the value is
+   no longer valid in that mode, ELT will be NULL for the first
+   element.  */
 static GTY(()) varray_type reg_values;
 static GTY((deletable (""))) varray_type reg_values_old;
 #define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I))
@@ -402,6 +406,25 @@ remove_useless_values ()
     abort ();
 }
 
+/* Return the mode in which a register was last set.  If X is not a
+   register, return its mode.  If the mode in which the register was
+   set is not known, or the value was already clobbered, return
+   VOIDmode.  */
+
+enum machine_mode
+cselib_reg_set_mode (x)
+     rtx x;
+{
+  if (GET_CODE (x) != REG)
+    return GET_MODE (x);
+
+  if (REG_VALUES (REGNO (x)) == NULL
+      || REG_VALUES (REGNO (x))->elt == NULL)
+    return VOIDmode;
+
+  return GET_MODE (REG_VALUES (REGNO (x))->elt->u.val_rtx);
+}
+
 /* Return nonzero if we can prove that X and Y contain the same value, taking
    our gathered information into account.  */
 
@@ -812,7 +835,10 @@ cselib_subst_to_values (x)
   switch (code)
     {
     case REG:
-      for (l = REG_VALUES (REGNO (x)); l; l = l->next)
+      l = REG_VALUES (REGNO (x));
+      if (l && l->elt == NULL)
+       l = l->next;
+      for (; l; l = l->next)
        if (GET_MODE (l->elt->u.val_rtx) == GET_MODE (x))
          return l->elt->u.val_rtx;
 
@@ -909,7 +935,10 @@ cselib_lookup (x, mode, create)
       struct elt_list *l;
       unsigned int i = REGNO (x);
 
-      for (l = REG_VALUES (i); l; l = l->next)
+      l = REG_VALUES (i);
+      if (l && l->elt == NULL)
+       l = l->next;
+      for (; l; l = l->next)
        if (mode == GET_MODE (l->elt->u.val_rtx))
          return l->elt;
 
@@ -927,8 +956,14 @@ cselib_lookup (x, mode, create)
       e = new_cselib_val (++next_unknown_value, GET_MODE (x));
       e->locs = new_elt_loc_list (e->locs, x);
       if (REG_VALUES (i) == 0)
-        VARRAY_PUSH_UINT (used_regs, i);
-      REG_VALUES (i) = new_elt_list (REG_VALUES (i), e);
+       {
+         /* Maintain the invariant that the first entry of
+            REG_VALUES, if present, must be the value used to set the
+            register, or NULL.  */
+         VARRAY_PUSH_UINT (used_regs, i);
+         REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL);
+       }
+      REG_VALUES (i)->next = new_elt_list (REG_VALUES (i)->next, e);
       slot = htab_find_slot_with_hash (hash_table, x, e->value, INSERT);
       *slot = e;
       return e;
@@ -1011,17 +1046,28 @@ cselib_invalidate_regno (regno, mode)
          struct elt_loc_list **p;
          unsigned int this_last = i;
 
-         if (i < FIRST_PSEUDO_REGISTER)
+         if (i < FIRST_PSEUDO_REGISTER && v != NULL)
            this_last += HARD_REGNO_NREGS (i, GET_MODE (v->u.val_rtx)) - 1;
 
-         if (this_last < regno)
+         if (this_last < regno || v == NULL)
            {
              l = &(*l)->next;
              continue;
            }
 
          /* We have an overlap.  */
-         unchain_one_elt_list (l);
+         if (*l == REG_VALUES (i))
+           {
+             /* Maintain the invariant that the first entry of
+                REG_VALUES, if present, must be the value used to set
+                the register, or NULL.  This is also nice because
+                then we won't push the same regno onto user_regs
+                multiple times.  */
+             (*l)->elt = NULL;
+             l = &(*l)->next;
+           }
+         else
+           unchain_one_elt_list (l);
 
          /* Now, we clear the mapping from value to reg.  It must exist, so
             this code will crash intentionally if it doesn't.  */
@@ -1213,9 +1259,6 @@ cselib_record_set (dest, src_elt, dest_addr_elt)
 
   if (dreg >= 0)
     {
-      if (REG_VALUES (dreg) == 0)
-        VARRAY_PUSH_UINT (used_regs, dreg);
-
       if (dreg < FIRST_PSEUDO_REGISTER)
        {
          unsigned int n = HARD_REGNO_NREGS (dreg, GET_MODE (dest));
@@ -1224,7 +1267,20 @@ cselib_record_set (dest, src_elt, dest_addr_elt)
            max_value_regs = n;
        }
 
-      REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
+      if (REG_VALUES (dreg) == 0)
+       {
+         VARRAY_PUSH_UINT (used_regs, dreg);
+         REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
+       }
+      else
+       {
+         if (REG_VALUES (dreg)->elt == 0)
+           REG_VALUES (dreg)->elt = src_elt;
+         else
+           /* The register should have been invalidated.  */
+           abort ();
+       }
+
       if (src_elt->locs == 0)
        n_useless_values--;
       src_elt->locs = new_elt_loc_list (src_elt->locs, dest);
index 9cceddb..073384d 100644 (file)
@@ -1,6 +1,6 @@
 /* Common subexpression elimination for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999 Free Software Foundation, Inc.
+   1999, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -67,6 +67,7 @@ extern void cselib_update_varray_sizes        PARAMS ((void));
 extern void cselib_init                        PARAMS ((void));
 extern void cselib_finish              PARAMS ((void));
 extern void cselib_process_insn                PARAMS ((rtx));
+extern enum machine_mode cselib_reg_set_mode PARAMS ((rtx));
 extern int rtx_equal_for_cselib_p      PARAMS ((rtx, rtx));
 extern int references_value_p          PARAMS ((rtx, int));
 extern rtx cselib_subst_to_values      PARAMS ((rtx));
index a6e41dd..54d163e 100644 (file)
@@ -8025,6 +8025,9 @@ static int
 reload_cse_noop_set_p (set)
      rtx set;
 {
+  if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set)))
+    return 0;
+
   return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
 }