From: Richard Henderson Date: Fri, 20 Sep 2002 17:50:48 +0000 (-0700) Subject: real.c (real_hash): New. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=46b33600d57ae54591bccaa935d7d837b5318a19;p=platform%2Fupstream%2Fgcc.git 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 --- 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 + + * 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 * 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.