OSDN Git Service

Fix typo
[pf3gnuchains/gcc-fork.git] / gcc / cselib.c
index 351d22d..13fc532 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cselib.h"
 #include "params.h"
 #include "alloc-pool.h"
+#include "target.h"
 
 static bool cselib_record_memory;
 static int entry_and_rtx_equal_p (const void *, const void *);
@@ -50,12 +51,11 @@ static struct elt_loc_list *new_elt_loc_list (struct elt_loc_list *, rtx);
 static void unchain_one_value (cselib_val *);
 static void unchain_one_elt_list (struct elt_list **);
 static void unchain_one_elt_loc_list (struct elt_loc_list **);
-static void clear_table (void);
 static int discard_useless_locs (void **, void *);
 static int discard_useless_values (void **, void *);
 static void remove_useless_values (void);
 static rtx wrap_constant (enum machine_mode, rtx);
-static unsigned int cselib_hash_rtx (rtx, enum machine_mode, int);
+static unsigned int cselib_hash_rtx (rtx, int);
 static cselib_val *new_cselib_val (unsigned int, enum machine_mode);
 static void add_mem_for_addr (cselib_val *, cselib_val *, rtx);
 static cselib_val *cselib_lookup_mem (rtx, int);
@@ -106,11 +106,11 @@ static unsigned int reg_values_size;
 #define REG_VALUES(i) reg_values[i]
 
 /* The largest number of hard regs used by any entry added to the
-   REG_VALUES table.  Cleared on each clear_table() invocation.  */
+   REG_VALUES table.  Cleared on each cselib_clear_table() invocation.  */
 static unsigned int max_value_regs;
 
 /* Here the set of indices I with REG_VALUES(I) != 0 is saved.  This is used
-   in clear_table() for fast emptying.  */
+   in cselib_clear_table() for fast emptying.  */
 static unsigned int *used_regs;
 static unsigned int n_used_regs;
 
@@ -200,8 +200,8 @@ unchain_one_value (cselib_val *v)
    initialization.  If CLEAR_ALL isn't set, then only clear the entries
    which are known to have been used.  */
 
-static void
-clear_table (void)
+void
+cselib_clear_table (void)
 {
   unsigned int i;
 
@@ -462,9 +462,18 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
   if (GET_CODE (x) != GET_CODE (y) || GET_MODE (x) != GET_MODE (y))
     return 0;
 
-  /* This won't be handled correctly by the code below.  */
-  if (GET_CODE (x) == LABEL_REF)
-    return XEXP (x, 0) == XEXP (y, 0);
+  /* These won't be handled correctly by the code below.  */
+  switch (GET_CODE (x))
+    {
+    case CONST_DOUBLE:
+      return 0;
+
+    case LABEL_REF:
+      return XEXP (x, 0) == XEXP (y, 0);
+
+    default:
+      break;
+    }
 
   code = GET_CODE (x);
   fmt = GET_RTX_FORMAT (code);
@@ -500,6 +509,11 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
          break;
 
        case 'e':
+         if (i == 1
+             && targetm.commutative_p (x, UNKNOWN)
+             && rtx_equal_for_cselib_p (XEXP (x, 1), XEXP (y, 0))
+             && rtx_equal_for_cselib_p (XEXP (x, 0), XEXP (y, 1)))
+           return 1;
          if (! rtx_equal_for_cselib_p (XEXP (x, i), XEXP (y, i)))
            return 0;
          break;
@@ -547,11 +561,22 @@ wrap_constant (enum machine_mode mode, rtx x)
    Possible reasons for return 0 are: the object is volatile, or we couldn't
    find a register or memory location in the table and CREATE is zero.  If
    CREATE is nonzero, table elts are created for regs and mem.
-   MODE is used in hashing for CONST_INTs only;
-   otherwise the mode of X is used.  */
+   N.B. this hash function returns the same hash value for RTXes that
+   differ only in the order of operands, thus it is suitable for comparisons
+   that take commutativity into account.
+   If we wanted to also support associative rules, we'd have to use a different
+   strategy to avoid returning spurious 0, e.g. return ~(~0U >> 1) .
+   We used to have a MODE argument for hashing for CONST_INTs, but that
+   didn't make sense, since it caused spurious hash differences between
+    (set (reg:SI 1) (const_int))
+    (plus:SI (reg:SI 2) (reg:SI 1))
+   and
+    (plus:SI (reg:SI 2) (const_int))
+   If the mode is important in any context, it must be checked specifically
+   in a comparison anyway, since relying on hash differences is unsafe.  */
 
 static unsigned int
-cselib_hash_rtx (rtx x, enum machine_mode mode, int create)
+cselib_hash_rtx (rtx x, int create)
 {
   cselib_val *e;
   int i, j;
@@ -573,7 +598,7 @@ cselib_hash_rtx (rtx x, enum machine_mode mode, int create)
       return e->value;
 
     case CONST_INT:
-      hash += ((unsigned) CONST_INT << 7) + (unsigned) mode + INTVAL (x);
+      hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
 
     case CONST_DOUBLE:
@@ -597,7 +622,7 @@ cselib_hash_rtx (rtx x, enum machine_mode mode, int create)
        for (i = 0; i < units; ++i)
          {
            elt = CONST_VECTOR_ELT (x, i);
-           hash += cselib_hash_rtx (elt, GET_MODE (elt), 0);
+           hash += cselib_hash_rtx (elt, 0);
          }
 
        return hash;
@@ -645,7 +670,7 @@ cselib_hash_rtx (rtx x, enum machine_mode mode, int create)
        case 'e':
          {
            rtx tem = XEXP (x, i);
-           unsigned int tem_hash = cselib_hash_rtx (tem, 0, create);
+           unsigned int tem_hash = cselib_hash_rtx (tem, create);
            
            if (tem_hash == 0)
              return 0;
@@ -657,7 +682,7 @@ cselib_hash_rtx (rtx x, enum machine_mode mode, int create)
          for (j = 0; j < XVECLEN (x, i); j++)
            {
              unsigned int tem_hash
-               = cselib_hash_rtx (XVECEXP (x, i, j), 0, create);
+               = cselib_hash_rtx (XVECEXP (x, i, j), create);
              
              if (tem_hash == 0)
                return 0;
@@ -937,7 +962,7 @@ cselib_lookup (rtx x, enum machine_mode mode, int create)
   if (MEM_P (x))
     return cselib_lookup_mem (x, create);
 
-  hashval = cselib_hash_rtx (x, mode, create);
+  hashval = cselib_hash_rtx (x, create);
   /* Can't even create if hashing is not possible.  */
   if (! hashval)
     return 0;
@@ -1362,7 +1387,7 @@ cselib_process_insn (rtx insn)
     {
       if (find_reg_note (insn, REG_RETVAL, NULL))
         cselib_current_insn_in_libcall = false;
-      clear_table ();
+      cselib_clear_table ();
       return;
     }
 
@@ -1464,7 +1489,7 @@ cselib_finish (void)
   free_alloc_pool (elt_loc_list_pool);
   free_alloc_pool (cselib_val_pool);
   free_alloc_pool (value_pool);
-  clear_table ();
+  cselib_clear_table ();
   htab_delete (hash_table);
   free (used_regs);
   used_regs = 0;