real.c (real_hash): New.
authorRichard Henderson <rth@redhat.com>
Fri, 20 Sep 2002 17:50:48 +0000 (10:50 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 20 Sep 2002 17:50:48 +0000 (10:50 -0700)
        * real.c (real_hash): New.
        * real.h: Declare it.
        * cse.c (canon_hash): Use it.
        * cselib.c (hash_rtx): Likewise.
        * emit-rtl.c (const_double_htab_hash): Likewise.
        * rtl.h (CONST_DOUBLE_REAL_VALUE): New.
        * varasm.c (struct rtx_const): Reduce vector size; separate
        integer and fp vectors.
        (HASHBITS): Remove.
        (const_hash_1): Rename from const_hash.  Use real_hash.  Do not
        take modulus MAX_HASH_TABLE.
        (const_hash): New.  Do take modulus MAX_HASH_TABLE.
        (output_constant_def): Do not take modulus MAX_HASH_TABLE.
        (SYMHASH): Don't use HASHBITS.
        (decode_rtx_const): Copy only active bits from REAL_VALUE_TYPE.
        Fix CONST_VECTOR thinko wrt fp vectors.  Fix kind comparison.
        (simplify_subtraction): Fix kind comparison.
        (const_hash_rtx): Return unsigned int.  Don't use HASHBITS.
        Use a union to pun integer array.
        * config/rs6000/rs6000.c (rs6000_hash_constant): Use real_hash;
        only hash two words of integral CONST_DOUBLE.

From-SVN: r57356

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/cse.c
gcc/cselib.c
gcc/emit-rtl.c
gcc/real.c
gcc/real.h
gcc/rtl.h
gcc/varasm.c

index 6e0e49b867a92e5e857c446ba6f0127323099042..53e5000c0d1b2af4513186c55790783594c54f79 100644 (file)
@@ -1,3 +1,27 @@
+2002-09-20  Richard Henderson  <rth@redhat.com>
+
+       * real.c (real_hash): New.
+       * real.h: Declare it.
+       * cse.c (canon_hash): Use it.
+       * cselib.c (hash_rtx): Likewise.
+       * emit-rtl.c (const_double_htab_hash): Likewise.
+       * rtl.h (CONST_DOUBLE_REAL_VALUE): New.
+       * varasm.c (struct rtx_const): Reduce vector size; separate
+       integer and fp vectors.
+       (HASHBITS): Remove.
+       (const_hash_1): Rename from const_hash.  Use real_hash.  Do not
+       take modulus MAX_HASH_TABLE.
+       (const_hash): New.  Do take modulus MAX_HASH_TABLE.
+       (output_constant_def): Do not take modulus MAX_HASH_TABLE.
+       (SYMHASH): Don't use HASHBITS.
+       (decode_rtx_const): Copy only active bits from REAL_VALUE_TYPE.
+       Fix CONST_VECTOR thinko wrt fp vectors.  Fix kind comparison.
+       (simplify_subtraction): Fix kind comparison.
+       (const_hash_rtx): Return unsigned int.  Don't use HASHBITS.
+       Use a union to pun integer array.
+       * config/rs6000/rs6000.c (rs6000_hash_constant): Use real_hash;
+       only hash two words of integral CONST_DOUBLE.
+
 2002-09-20  Steve Ellcey  <sje@cup.hp.com>
 
        * config/ia64/hpux.h (STARTFILE_SPEC): Modify.
index fa9fb0548f247439cb8940246df15c733407095b..ba0249cba7e40e0fe042e3eb68fc60c59f183335 100644 (file)
@@ -11412,18 +11412,34 @@ static unsigned
 rs6000_hash_constant (k)
      rtx k;
 {
-  unsigned result = (GET_CODE (k) << 3) ^ GET_MODE (k);
-  const char *format = GET_RTX_FORMAT (GET_CODE (k));
-  int flen = strlen (format);
-  int fidx;
+  enum rtx_code code = GET_CODE (k);
+  enum machine_mode mode = GET_MODE (k);
+  unsigned result = (code << 3) ^ mode;
+  const char *format;
+  int flen, fidx;
   
-  if (GET_CODE (k) == LABEL_REF)
-    return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
+  format = GET_RTX_FORMAT (code);
+  flen = strlen (format);
+  fidx = 0;
 
-  if (GET_CODE (k) == CODE_LABEL)
-    fidx = 3;
-  else
-    fidx = 0;
+  switch (code)
+    {
+    case LABEL_REF:
+      return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
+
+    case CONST_DOUBLE:
+      if (mode != VOIDmode)
+       return real_hash (CONST_DOUBLE_REAL_VALUE (k)) * result;
+      flen = 2;
+      break;
+
+    case CODE_LABEL:
+      fidx = 3;
+      break;
+
+    default:
+      break;
+    }
 
   for (; fidx < flen; fidx++)
     switch (format[fidx])
@@ -11460,6 +11476,7 @@ rs6000_hash_constant (k)
       default:
        abort ();
       }
+
   return result;
 }
 
index adaf20d32b4f0574bae72b685881f4e741130267..3571cc7c730a4f447a260f295c20088680efca1d 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2320,11 +2320,7 @@ canon_hash (x, mode)
         the integers representing the constant.  */
       hash += (unsigned) code + (unsigned) GET_MODE (x);
       if (GET_MODE (x) != VOIDmode)
-       for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
-         {
-           unsigned HOST_WIDE_INT tem = XWINT (x, i);
-           hash += tem;
-         }
+       hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
       else
        hash += ((unsigned) CONST_DOUBLE_LOW (x)
                 + (unsigned) CONST_DOUBLE_HIGH (x));
index 18e3a4adb740ce2372566c328bd70ae3e88f9824..9c54015f1e84d4d56db48f7da25639d20157e5e7 100644 (file)
@@ -581,8 +581,7 @@ hash_rtx (x, mode, create)
         the integers representing the constant.  */
       hash += (unsigned) code + (unsigned) GET_MODE (x);
       if (GET_MODE (x) != VOIDmode)
-       for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
-         hash += XWINT (x, i);
+       hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
       else
        hash += ((unsigned) CONST_DOUBLE_LOW (x)
                 + (unsigned) CONST_DOUBLE_HIGH (x));
index 4a8b9e36ea3ccd4e70ac458b970ee727bbbb19b5..bfcc289cca420c5e53d3f6ee09b8f66bebd0d037 100644 (file)
@@ -221,12 +221,13 @@ static hashval_t
 const_double_htab_hash (x)
      const void *x;
 {
-  hashval_t h = 0;
-  size_t i;
   rtx value = (rtx) x;
+  hashval_t h;
 
-  for (i = 0; i < sizeof(CONST_DOUBLE_FORMAT)-1; i++)
-    h ^= XWINT (value, i);
+  if (GET_MODE (value) == VOIDmode)
+    h = CONST_DOUBLE_LOW (value) ^ CONST_DOUBLE_HIGH (value);
+  else
+    h = real_hash (CONST_DOUBLE_REAL_VALUE (value));
   return h;
 }
 
index 2c28135c17138d469a07179517937977fa7acd68..d746ab61223a77d2ceefc2dd951506637072710a 100644 (file)
@@ -2311,6 +2311,47 @@ significand_size (mode)
 
   return fmt->p * fmt->log2_b;
 }
+
+/* Return a hash value for the given real value.  */
+/* ??? The "unsigned int" return value is intended to be hashval_t,
+   but I didn't want to pull hashtab.h into real.h.  */
+
+unsigned int
+real_hash (r)
+     const REAL_VALUE_TYPE *r;
+{
+  unsigned int h;
+  size_t i;
+
+  h = r->class | (r->sign << 2);
+  switch (r->class)
+    {
+    case rvc_zero:
+    case rvc_inf:
+      break;
+
+    case rvc_normal:
+      h |= r->exp << 3;
+      /* FALLTHRU */
+
+    case rvc_nan:
+      if (sizeof(unsigned long) > sizeof(unsigned int))
+       for (i = 0; i < SIGSZ; ++i)
+         {
+           unsigned long s = r->sig[i];
+           h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
+         }
+      else
+       for (i = 0; i < SIGSZ; ++i)
+         h ^= r->sig[i];
+      break;
+
+    default:
+      abort ();
+    }
+
+  return h;
+}
 \f
 /* IEEE single-precision format.  */
 
index 6b9cc35a321c740fd3d8860526572cdc78c75c30..d59e5202a1f87b928aa572b2de0325315d011953 100644 (file)
@@ -169,6 +169,8 @@ extern bool real_nan                PARAMS ((REAL_VALUE_TYPE *, const char *,
 
 extern void real_2expN         PARAMS ((REAL_VALUE_TYPE *, int));
 
+extern unsigned int real_hash  PARAMS ((const REAL_VALUE_TYPE *));
+
 /* ====================================================================== */
 /* Crap.  */
 
index 0fd7e6775b9a3923aa595155ccc6717b4e05f7a3..249233cb161c43d80ba642cd4bdd0f56fdb9e60f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1010,14 +1010,13 @@ enum label_kind
 #define INTVAL(RTX) XCWINT(RTX, 0, CONST_INT)
 
 /* For a CONST_DOUBLE:
-   The usual two ints that hold the value.
-   For a DImode, that is all there are;
-    and CONST_DOUBLE_LOW is the low-order word and ..._HIGH the high-order.
-   For a float, the number of ints varies,
-    and CONST_DOUBLE_LOW is the one that should come first *in memory*.
-    So use &CONST_DOUBLE_LOW(r) as the address of an array of ints.  */
+   For a DImode, there are two integers CONST_DOUBLE_LOW is the
+     low-order word and ..._HIGH the high-order.
+   For a float, there is a REAL_VALUE_TYPE structure, and 
+     CONST_DOUBLE_REAL_VALUE(r) is a pointer to it.  */
 #define CONST_DOUBLE_LOW(r) XCWINT (r, 0, CONST_DOUBLE)
 #define CONST_DOUBLE_HIGH(r) XCWINT (r, 1, CONST_DOUBLE)
+#define CONST_DOUBLE_REAL_VALUE(r) ((struct real_value *)&CONST_DOUBLE_LOW(r))
 
 /* For a CONST_VECTOR, return element #n.  */
 #define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
index edd02622b09a6759882ed7580054f4f4cdc65b43..702cf82446d794c5246d61ca0f9432170fce7f60 100644 (file)
@@ -136,13 +136,14 @@ static HOST_WIDE_INT const_alias_set;
 static const char *strip_reg_name      PARAMS ((const char *));
 static int contains_pointers_p         PARAMS ((tree));
 static void decode_addr_const          PARAMS ((tree, struct addr_const *));
-static int const_hash                  PARAMS ((tree));
+static unsigned int const_hash         PARAMS ((tree));
+static unsigned int const_hash_1       PARAMS ((tree));
 static int compare_constant            PARAMS ((tree, tree));
 static tree copy_constant              PARAMS ((tree));
 static void output_constant_def_contents  PARAMS ((tree, int, int));
 static void decode_rtx_const           PARAMS ((enum machine_mode, rtx,
                                               struct rtx_const *));
-static int const_hash_rtx              PARAMS ((enum machine_mode, rtx));
+static unsigned int const_hash_rtx     PARAMS ((enum machine_mode, rtx));
 static int compare_constant_rtx
   PARAMS ((enum machine_mode, rtx, struct constant_descriptor_rtx *));
 static struct constant_descriptor_rtx * record_constant_rtx
@@ -2166,11 +2167,15 @@ struct rtx_const GTY(())
       HOST_WIDE_INT low;
     } GTY ((tag ("0"))) di;
 
-    /* The max vector size we have is 8 wide.  This should be enough.  */
-    struct rtx_const_vec {
-      HOST_WIDE_INT veclo;
-      HOST_WIDE_INT vechi; 
-    } GTY ((tag ("2"))) vec[16];
+    /* The max vector size we have is 8 wide; two variants for
+       integral and floating point vectors.  */
+    struct rtx_const_int_vec {
+      HOST_WIDE_INT high;
+      HOST_WIDE_INT low;
+    } GTY ((tag ("2"))) int_vec[8];
+
+    REAL_VALUE_TYPE GTY ((tag ("3"))) fp_vec[8];
+
   } GTY ((desc ("%1.kind >= RTX_INT"), descbits ("1"))) un;
 };
 
@@ -2193,7 +2198,6 @@ struct constant_descriptor_tree GTY(())
   tree value;
 };
 
-#define HASHBITS 30
 #define MAX_HASH_TABLE 1009
 static GTY(()) struct constant_descriptor_tree *
   const_hash_table[MAX_HASH_TABLE];
@@ -2238,12 +2242,20 @@ const_str_htab_eq (x, y)
 
 /* Compute a hash code for a constant expression.  */
 
-static int
+static unsigned int
 const_hash (exp)
      tree exp;
+{
+  return const_hash_1 (exp) % MAX_HASH_TABLE;
+}
+
+static unsigned int
+const_hash_1 (exp)
+     tree exp;
 {
   const char *p;
-  int len, hi, i;
+  unsigned int hi;
+  int len, i;
   enum tree_code code = TREE_CODE (exp);
 
   /* Either set P and LEN to the address and len of something to hash and
@@ -2257,9 +2269,7 @@ const_hash (exp)
       break;
 
     case REAL_CST:
-      p = (char *) &TREE_REAL_CST (exp);
-      len = sizeof TREE_REAL_CST (exp);
-      break;
+      return real_hash (TREE_REAL_CST_PTR (exp));
 
     case STRING_CST:
       p = TREE_STRING_POINTER (exp);
@@ -2267,8 +2277,8 @@ const_hash (exp)
       break;
 
     case COMPLEX_CST:
-      return (const_hash (TREE_REALPART (exp)) * 5
-             + const_hash (TREE_IMAGPART (exp)));
+      return (const_hash_1 (TREE_REALPART (exp)) * 5
+             + const_hash_1 (TREE_IMAGPART (exp)));
 
     case CONSTRUCTOR:
       if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
@@ -2285,23 +2295,11 @@ const_hash (exp)
        {
          tree link;
 
-         /* For record type, include the type in the hashing.
-            We do not do so for array types
-            because (1) the sizes of the elements are sufficient
-            and (2) distinct array types can have the same constructor.
-            Instead, we include the array size because the constructor could
-            be shorter.  */
-         if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-           hi = ((unsigned long) TREE_TYPE (exp) & ((1 << HASHBITS) - 1))
-             % MAX_HASH_TABLE;
-         else
-           hi = ((5 + int_size_in_bytes (TREE_TYPE (exp)))
-                 & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
+         hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
 
          for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
            if (TREE_VALUE (link))
-             hi
-               = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
+             hi = hi * 603 + const_hash_1 (TREE_VALUE (link));
 
          return hi;
        }
@@ -2325,25 +2323,22 @@ const_hash (exp)
          hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
        else
          abort ();
-
-       hi &= (1 << HASHBITS) - 1;
-       hi %= MAX_HASH_TABLE;
       }
       return hi;
 
     case PLUS_EXPR:
     case MINUS_EXPR:
-      return (const_hash (TREE_OPERAND (exp, 0)) * 9
-             + const_hash (TREE_OPERAND (exp, 1)));
+      return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
+             + const_hash_1 (TREE_OPERAND (exp, 1)));
 
     case NOP_EXPR:
     case CONVERT_EXPR:
     case NON_LVALUE_EXPR:
-      return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
+      return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
 
     default:
       /* A language specific constant. Just hash the code.  */
-      return (int) code % MAX_HASH_TABLE;
+      return code;
     }
 
   /* Compute hashing function */
@@ -2351,8 +2346,6 @@ const_hash (exp)
   for (i = 0; i < len; i++)
     hi = ((hi * 613) + (unsigned) (p[i]));
 
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_HASH_TABLE;
   return hi;
 }
 
@@ -2691,7 +2684,7 @@ output_constant_def (exp, defer)
      to see if any of them describes EXP.  If yes, the descriptor records
      the label number already assigned.  */
 
-  hash = const_hash (exp) % MAX_HASH_TABLE;
+  hash = const_hash (exp);
 
   for (desc = const_hash_table[hash]; desc; desc = desc->next)
     if (compare_constant (exp, desc->value))
@@ -2910,8 +2903,7 @@ struct pool_constant GTY(())
 /* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
    The argument is XSTR (... , 0)  */
 
-#define SYMHASH(LABEL) \
-  ((((unsigned long) (LABEL)) & ((1 << HASHBITS) - 1))  % MAX_RTX_HASH_TABLE)
+#define SYMHASH(LABEL) (((unsigned long) (LABEL)) % MAX_RTX_HASH_TABLE)
 \f
 /* Initialize constant pool hashing for a new function.  */
 
@@ -2958,8 +2950,29 @@ decode_rtx_const (mode, x, value)
       value->kind = RTX_DOUBLE;
       if (GET_MODE (x) != VOIDmode)
        {
+         const REAL_VALUE_TYPE *r = CONST_DOUBLE_REAL_VALUE (x);
+
          value->mode = GET_MODE (x);
-         REAL_VALUE_FROM_CONST_DOUBLE (value->un.du, x);
+
+         /* Copy the REAL_VALUE_TYPE by members so that we don't
+            copy garbage from the original structure into our
+            carefully cleaned hashing structure.  */
+         value->un.du.class = r->class;
+         value->un.du.sign = r->sign;
+         switch (r->class)
+           {
+           case rvc_zero:
+           case rvc_inf:
+             break;
+           case rvc_normal:
+             value->un.du.exp = r->exp;
+             /* FALLTHRU */
+           case rvc_nan:
+             memcpy (value->un.du.sig, r->sig, sizeof (r->sig));
+             break;
+           default:
+             abort ();
+           }
        }
       else
        {
@@ -2971,28 +2984,59 @@ decode_rtx_const (mode, x, value)
     case CONST_VECTOR:
       {
        int units, i;
-       rtx elt;
 
        units = CONST_VECTOR_NUNITS (x);
        value->kind = RTX_VECTOR;
        value->mode = mode;
 
-       for (i = 0; i < units; ++i)
+       if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
          {
-           elt = CONST_VECTOR_ELT (x, i);
-           if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+           for (i = 0; i < units; ++i)
              {
-               value->un.vec[i].veclo = (HOST_WIDE_INT) INTVAL (elt);
-               value->un.vec[i].vechi = 0;
+               rtx elt = CONST_VECTOR_ELT (x, i);
+               if (GET_CODE (elt) == CONST_INT)
+                 {
+                   value->un.int_vec[i].low = INTVAL (elt);
+                   value->un.int_vec[i].high = 0;
+                 }
+               else
+                 {
+                   value->un.int_vec[i].low = CONST_DOUBLE_LOW (elt);
+                   value->un.int_vec[i].high = CONST_DOUBLE_HIGH (elt);
+                 }
              }
-           else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+         }
+       else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+         {
+           for (i = 0; i < units; ++i)
              {
-               value->un.vec[i].veclo = (HOST_WIDE_INT) CONST_DOUBLE_LOW (elt);
-               value->un.vec[i].vechi = (HOST_WIDE_INT) CONST_DOUBLE_HIGH (elt);
+               const REAL_VALUE_TYPE *r
+                 = CONST_DOUBLE_REAL_VALUE (CONST_VECTOR_ELT (x, i));
+               REAL_VALUE_TYPE *d = &value->un.fp_vec[i];
+
+               /* Copy the REAL_VALUE_TYPE by members so that we don't
+                  copy garbage from the original structure into our
+                  carefully cleaned hashing structure.  */
+               d->class = r->class;
+               d->sign = r->sign;
+               switch (r->class)
+                 {
+                 case rvc_zero:
+                 case rvc_inf:
+                   break;
+                 case rvc_normal:
+                   d->exp = r->exp;
+                   /* FALLTHRU */
+                 case rvc_nan:
+                   memcpy (d->sig, r->sig, sizeof (r->sig));
+                   break;
+                 default:
+                   abort ();
+                 }
              }
-           else
-             abort ();
          }
+       else
+         abort ();
       }
       break;
 
@@ -3047,7 +3091,7 @@ decode_rtx_const (mode, x, value)
        }
     }
 
-  if (value->kind > RTX_VECTOR && value->un.addr.base != 0)
+  if (value->kind >= RTX_INT && value->un.addr.base != 0)
     switch (GET_CODE (value->un.addr.base))
       {
 #if 0
@@ -3079,7 +3123,7 @@ simplify_subtraction (x)
   decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0);
   decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1);
 
-  if (val0.kind > RTX_DOUBLE
+  if (val0.kind >= RTX_INT
       && val0.kind == val1.kind
       && val0.un.addr.base == val1.un.addr.base)
     return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
@@ -3089,25 +3133,27 @@ simplify_subtraction (x)
 
 /* Compute a hash code for a constant RTL expression.  */
 
-static int
+static unsigned int
 const_hash_rtx (mode, x)
      enum machine_mode mode;
      rtx x;
 {
-  int hi;
+  union {
+    struct rtx_const value;
+    unsigned int data[sizeof(struct rtx_const) / sizeof (unsigned int)];
+  } u;
+
+  unsigned int hi;
   size_t i;
 
-  struct rtx_const value;
-  decode_rtx_const (mode, x, &value);
+  decode_rtx_const (mode, x, &u.value);
 
   /* Compute hashing function */
   hi = 0;
-  for (i = 0; i < sizeof value / sizeof (int); i++)
-    hi += ((int *) &value)[i];
+  for (i = 0; i < ARRAY_SIZE (u.data); i++)
+    hi = hi * 613 + u.data[i];
 
-  hi &= (1 << HASHBITS) - 1;
-  hi %= MAX_RTX_HASH_TABLE;
-  return hi;
+  return hi % MAX_RTX_HASH_TABLE;
 }
 
 /* Compare a constant rtl object X with a constant-descriptor DESC.