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
This commit is contained in:
Richard Henderson 2002-09-20 10:50:48 -07:00 committed by Richard Henderson
parent 40ad65d05e
commit 46b33600d5
9 changed files with 218 additions and 93 deletions

View 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.

View 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;
}

View file

@ -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));

View 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));

View 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;
}

View 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;
}
/* IEEE single-precision format. */

View 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. */

View file

@ -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)

View 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)
/* 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)
{
value->un.vec[i].veclo = (HOST_WIDE_INT) CONST_DOUBLE_LOW (elt);
value->un.vec[i].vechi = (HOST_WIDE_INT) CONST_DOUBLE_HIGH (elt);
}
else
abort ();
}
else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
{
for (i = 0; i < units; ++i)
{
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 ();
}
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.