summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2001-09-20 15:12:54 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2001-09-20 15:12:54 +0000
commit15d769aab42c4ea8a8863b8b37dee46c77155be0 (patch)
tree9f82325d87e923ce9de88e1e1f44c7643f7d9c53 /gcc/fold-const.c
parent41f4d177c8884f82b1a6f3cf74af02cfd7e1c15c (diff)
downloadgcc-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.c128
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)