diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-09-20 15:12:54 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-09-20 15:12:54 +0000 |
commit | 15d769aab42c4ea8a8863b8b37dee46c77155be0 (patch) | |
tree | 9f82325d87e923ce9de88e1e1f44c7643f7d9c53 /gcc/fold-const.c | |
parent | 41f4d177c8884f82b1a6f3cf74af02cfd7e1c15c (diff) | |
download | gcc-15d769aab42c4ea8a8863b8b37dee46c77155be0.tar.gz |
* fold-const.c (hashtab.h): Include.
(int_const_binop): Remove FORSIZE arg and compute from type; all
callers changed.
Call size_int_type_wide for all single-word constants.
(size_htab_hash, size_htab_eq): New functions.
(size_int_type_wide): Rework to use hash table.
* ggc-common.c (hashtab.h): Include.
(struct d_htab_root): New struct.
(d_htab_roots): New variable.
(ggc_add_deletable_htab, ggc_htab_delete): New functions
(ggc_mark_roots): Handle deletable htabs.
* ggc-page.c (ggc_marked_p): New function.
* ggc-simple.c (ggc_marked_p): Likewise.
* ggc.h: Reformatting throughout.
(ggc_marked_p, ggc_add_deletable_htab): New declarations.
* tree.c (init_obstacks): Make type_hash_table a deletable root.
(type_hash_add): Allocate struct type_hash from GC memory.
(mark_hash_entry, mark_type_hash): Deleted.
(type_hash_marked_p, type_hash_mark): New functions.
* Makefile.in (ggc-common.o, fold-const.o): Include hashtab.h.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45710 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 128 |
1 files changed, 85 insertions, 43 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7cefaeaef0e..b4c60a489bb 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -51,6 +51,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm_p.h" #include "toplev.h" #include "ggc.h" +#include "hashtab.h" static void encode PARAMS ((HOST_WIDE_INT *, unsigned HOST_WIDE_INT, @@ -65,9 +66,11 @@ static tree negate_expr PARAMS ((tree)); static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *, int)); static tree associate_trees PARAMS ((tree, tree, enum tree_code, tree)); -static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int, int)); +static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int)); static void const_binop_1 PARAMS ((PTR)); static tree const_binop PARAMS ((enum tree_code, tree, tree, int)); +static hashval_t size_htab_hash PARAMS ((const void *)); +static int size_htab_eq PARAMS ((const void *, const void *)); static void fold_convert_1 PARAMS ((PTR)); static tree fold_convert PARAMS ((tree, tree)); static enum tree_code invert_tree_comparison PARAMS ((enum tree_code)); @@ -1478,14 +1481,13 @@ associate_trees (t1, t2, code, type) /* Combine two integer constants ARG1 and ARG2 under operation CODE to produce a new constant. - If NOTRUNC is nonzero, do not truncate the result to fit the data type. - If FORSIZE is nonzero, compute overflow for unsigned types. */ + If NOTRUNC is nonzero, do not truncate the result to fit the data type. */ static tree -int_const_binop (code, arg1, arg2, notrunc, forsize) +int_const_binop (code, arg1, arg2, notrunc) enum tree_code code; register tree arg1, arg2; - int notrunc, forsize; + int notrunc; { unsigned HOST_WIDE_INT int1l, int2l; HOST_WIDE_INT int1h, int2h; @@ -1494,7 +1496,10 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) unsigned HOST_WIDE_INT garbagel; HOST_WIDE_INT garbageh; register tree t; - int uns = TREE_UNSIGNED (TREE_TYPE (arg1)); + tree type = TREE_TYPE (arg1); + int uns = TREE_UNSIGNED (type); + int is_sizetype + = (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type)); int overflow = 0; int no_overflow = 0; @@ -1527,7 +1532,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) /* It's unclear from the C standard whether shifts can overflow. The following code ignores overflow; perhaps a C standard interpretation ruling is needed. */ - lshift_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)), + lshift_double (int1l, int1h, int2l, TYPE_PRECISION (type), &low, &hi, !uns); no_overflow = 1; break; @@ -1535,7 +1540,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) case RROTATE_EXPR: int2l = - int2l; case LROTATE_EXPR: - lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (TREE_TYPE (arg1)), + lrotate_double (int1l, int1h, int2l, TYPE_PRECISION (type), &low, &hi); break; @@ -1583,8 +1588,7 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) low = 1, hi = 0; break; } - overflow = div_and_round_double (code, uns, - int1l, int1h, int2l, int2h, + overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h, &low, &hi, &garbagel, &garbageh); break; @@ -1632,9 +1636,14 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) abort (); } - if (forsize && hi == 0 && low < 10000 + /* If this is for a sizetype, can be represented as one (signed) + HOST_WIDE_INT word, and doesn't overflow, use size_int since it caches + constants. */ + if (is_sizetype + && ((hi == 0 && (HOST_WIDE_INT) low >= 0) + || (hi == -1 && (HOST_WIDE_INT) low < 0)) && overflow == 0 && ! TREE_OVERFLOW (arg1) && ! TREE_OVERFLOW (arg2)) - return size_int_type_wide (low, TREE_TYPE (arg1)); + return size_int_type_wide (low, type); else { t = build_int_2 (low, hi); @@ -1642,14 +1651,16 @@ int_const_binop (code, arg1, arg2, notrunc, forsize) } TREE_OVERFLOW (t) - = ((notrunc ? (!uns || forsize) && overflow - : force_fit_type (t, (!uns || forsize) && overflow) && ! no_overflow) + = ((notrunc + ? (!uns || is_sizetype) && overflow + : (force_fit_type (t, (!uns || is_sizetype) && overflow) + && ! no_overflow)) | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)); /* If we're doing a size calculation, unsigned arithmetic does overflow. So check if force_fit_type truncated the value. */ - if (forsize + if (is_sizetype && ! TREE_OVERFLOW (t) && (TREE_INT_CST_HIGH (t) != hi || TREE_INT_CST_LOW (t) != low)) @@ -1740,7 +1751,7 @@ const_binop (code, arg1, arg2, notrunc) STRIP_NOPS (arg2); if (TREE_CODE (arg1) == INTEGER_CST) - return int_const_binop (code, arg1, arg2, notrunc, 0); + return int_const_binop (code, arg1, arg2, notrunc); #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) if (TREE_CODE (arg1) == REAL_CST) @@ -1865,6 +1876,39 @@ const_binop (code, arg1, arg2, notrunc) } return 0; } + +/* These are the hash table functions for the hash table of INTEGER_CST + nodes of a sizetype. */ + +/* Return the hash code code X, an INTEGER_CST. */ + +static hashval_t +size_htab_hash (x) + const void *x; +{ + tree t = (tree) x; + + return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t) + ^ (hashval_t) ((long) TREE_TYPE (t) >> 3) + ^ (TREE_OVERFLOW (t) << 20)); +} + +/* Return non-zero if the value represented by *X (an INTEGER_CST tree node) + is the same as that given by *Y, which is the same. */ + +static int +size_htab_eq (x, y) + const void *x; + const void *y; +{ + tree xt = (tree) x; + tree yt = (tree) y; + + return (TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt) + && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt) + && TREE_TYPE (xt) == TREE_TYPE (yt) + && TREE_OVERFLOW (xt) == TREE_OVERFLOW (yt)); +} /* Return an INTEGER_CST with value whose low-order HOST_BITS_PER_WIDE_INT bits are given by NUMBER and of the sizetype represented by KIND. */ @@ -1884,40 +1928,38 @@ size_int_type_wide (number, type) HOST_WIDE_INT number; tree type; { - /* Type-size nodes already made for small sizes. */ - static tree size_table[2048 + 1]; - static int init_p = 0; - tree t; + static htab_t size_htab = 0; + static tree new_const = 0; + PTR *slot; - if (! init_p) + if (size_htab == 0) { - ggc_add_tree_root ((tree *) size_table, - sizeof size_table / sizeof (tree)); - init_p = 1; + size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL); + ggc_add_deletable_htab (size_htab, NULL, NULL); + new_const = make_node (INTEGER_CST); + ggc_add_tree_root (&new_const, 1); } - /* If this is a positive number that fits in the table we use to hold - cached entries, see if it is already in the table and put it there - if not. */ - if (number >= 0 && number < (int) ARRAY_SIZE (size_table)) + /* Adjust NEW_CONST to be the constant we want. If it's already in the + hash table, we return the value from the hash table. Otherwise, we + place that in the hash table and make a new node for the next time. */ + TREE_INT_CST_LOW (new_const) = number; + TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0; + TREE_TYPE (new_const) = type; + TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const) + = force_fit_type (new_const, 0); + + slot = htab_find_slot (size_htab, new_const, INSERT); + if (*slot == 0) { - if (size_table[number] != 0) - for (t = size_table[number]; t != 0; t = TREE_CHAIN (t)) - if (TREE_TYPE (t) == type) - return t; - - t = build_int_2 (number, 0); - TREE_TYPE (t) = type; - TREE_CHAIN (t) = size_table[number]; - size_table[number] = t; + tree t = new_const; + *slot = (PTR) new_const; + new_const = make_node (INTEGER_CST); return t; } - - t = build_int_2 (number, number < 0 ? -1 : 0); - TREE_TYPE (t) = type; - TREE_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (t) = force_fit_type (t, 0); - return t; + else + return (tree) *slot; } /* Combine operands OP1 and OP2 with arithmetic operation CODE. CODE @@ -1949,7 +1991,7 @@ size_binop (code, arg0, arg1) return arg1; /* Handle general case of two integer constants. */ - return int_const_binop (code, arg0, arg1, 0, 1); + return int_const_binop (code, arg0, arg1, 0); } if (arg0 == error_mark_node || arg1 == error_mark_node) |