aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-09-20 10:50:48 -0700
committerRichard Henderson <rth@gcc.gnu.org>2002-09-20 10:50:48 -0700
commit46b33600d57ae54591bccaa935d7d837b5318a19 (patch)
tree89d914be5aa639096dbd44d7f9d3e884503d85a0 /gcc
parent40ad65d05ee933ba6d04684e9ddaa6e841c5e4a6 (diff)
downloadgcc-46b33600d57ae54591bccaa935d7d837b5318a19.zip
gcc-46b33600d57ae54591bccaa935d7d837b5318a19.tar.gz
gcc-46b33600d57ae54591bccaa935d7d837b5318a19.tar.bz2
real.c (real_hash): New.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/rs6000/rs6000.c37
-rw-r--r--gcc/cse.c6
-rw-r--r--gcc/cselib.c3
-rw-r--r--gcc/emit-rtl.c9
-rw-r--r--gcc/real.c41
-rw-r--r--gcc/real.h2
-rw-r--r--gcc/rtl.h11
-rw-r--r--gcc/varasm.c174
9 files changed, 216 insertions, 91 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6e0e49b..53e5000 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index fa9fb05..ba0249c 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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;
}
diff --git a/gcc/cse.c b/gcc/cse.c
index adaf20d..3571cc7 100644
--- 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));
diff --git a/gcc/cselib.c b/gcc/cselib.c
index 18e3a4a..9c54015 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -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));
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 4a8b9e3..bfcc289 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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;
}
diff --git a/gcc/real.c b/gcc/real.c
index 2c28135..d746ab6 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -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;
+}
/* IEEE single-precision format. */
diff --git a/gcc/real.h b/gcc/real.h
index 6b9cc35..d59e520 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -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. */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 0fd7e67..249233c 100644
--- 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)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index edd0262..702cf82 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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)
/* 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.