Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/*@@ This file should be rewritten to use an arbitrary precision
@@ representation for "struct tree_int_cst" and "struct tree_real_cst".
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "flags.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "toplev.h"
#include "ggc.h"
+#include "hashtab.h"
static void encode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT,
static void decode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT *,
HOST_WIDE_INT *));
+#ifndef REAL_ARITHMETIC
+static void exact_real_inverse_1 PARAMS ((PTR));
+#endif
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));
HOST_WIDE_INT arg1[4];
HOST_WIDE_INT arg2[4];
HOST_WIDE_INT prod[4 * 2];
- register unsigned HOST_WIDE_INT carry;
- register int i, j, k;
+ unsigned HOST_WIDE_INT carry;
+ int i, j, k;
unsigned HOST_WIDE_INT toplow, neglow;
HOST_WIDE_INT tophigh, neghigh;
CODE is a tree code for a kind of division, one of
TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
or EXACT_DIV_EXPR
- It controls how the quotient is rounded to a integer.
+ It controls how the quotient is rounded to an integer.
Return nonzero if the operation overflows.
UNS nonzero says do unsigned division. */
int quo_neg = 0;
HOST_WIDE_INT num[4 + 1]; /* extra element for scaling. */
HOST_WIDE_INT den[4], quo[4];
- register int i, j;
+ int i, j;
unsigned HOST_WIDE_INT work;
unsigned HOST_WIDE_INT carry = 0;
unsigned HOST_WIDE_INT lnum = lnum_orig;
else
quo_est = BASE - 1;
- /* Refine quo_est so it's usually correct, and at most one high. */
+ /* Refine quo_est so it's usually correct, and at most one high. */
tmp = work - quo_est * den[den_hi_sig];
if (tmp < BASE
&& (den[den_hi_sig - 1] * quo_est
unsigned sign : 1;
unsigned exponent : 11;
unsigned mantissa1 : 20;
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
} little_endian;
struct {
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
unsigned sign : 1;
unsigned exponent : 11;
unsigned mantissa1 : 20;
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
} little_endian;
struct {
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
unsigned sign : 1;
unsigned exponent : 11;
unsigned mantissa1 : 20;
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
} little_endian;
struct {
- unsigned mantissa2;
+ unsigned mantissa2 : 32;
unsigned mantissa1 : 20;
unsigned exponent : 11;
unsigned sign : 1;
/* Try to change R into its exact multiplicative inverse in machine mode
MODE. Return nonzero function value if successful. */
+struct exact_real_inverse_args
+{
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ int success;
+};
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
- REAL_VALUE_TYPE *r;
+static void
+exact_real_inverse_1 (p)
+ PTR p;
{
- jmp_buf float_error;
+ struct exact_real_inverse_args *args =
+ (struct exact_real_inverse_args *) p;
+
+ enum machine_mode mode = args->mode;
+ REAL_VALUE_TYPE *r = args->r;
+
union
- {
- double d;
- unsigned short i[4];
- }x, t, y;
+ {
+ double d;
+ unsigned short i[4];
+ }
+ x, t, y;
#ifdef CHECK_FLOAT_VALUE
int i;
#endif
- /* Usually disable if bounds checks are not reliable. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
- return 0;
-
/* Set array index to the less significant bits in the unions, depending
- on the endian-ness of the host doubles.
- Disable if insufficient information on the data structure. */
-#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
- return 0;
-#else
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define K 2
-#else
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define K 2
+ on the endian-ness of the host doubles. */
+#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT \
+ || HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
+# define K 2
#else
-#define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
-#endif
-#endif
+# define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
#endif
- if (setjmp (float_error))
- {
- /* Don't do the optimization if there was an arithmetic error. */
-fail:
- set_float_handler (NULL);
- return 0;
- }
- set_float_handler (float_error);
-
/* Domain check the argument. */
x.d = *r;
if (x.d == 0.0)
#endif
/* Output the reciprocal and return success flag. */
- set_float_handler (NULL);
*r = y.d;
- return 1;
+ args->success = 1;
+ return;
+
+ fail:
+ args->success = 0;
+ return;
+
+#undef K
+}
+
+
+int
+exact_real_inverse (mode, r)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *r;
+{
+ struct exact_real_inverse_args args;
+
+ /* Disable if insufficient information on the data structure. */
+#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
+ return 0;
+#endif
+
+ /* Usually disable if bounds checks are not reliable. */
+ if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
+ return 0;
+
+ args.mode = mode;
+ args.r = r;
+
+ if (do_float_handler (exact_real_inverse_1, (PTR) &args))
+ return args.success;
+ return 0;
}
/* Convert C99 hexadecimal floating point string constant S. Return
shcount = 0;
while ((c = *p) != '\0')
{
- if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
- || (c >= 'a' && c <= 'f'))
+ if (ISXDIGIT (c))
{
k = c & CHARMASK;
if (k >= 'a' && k <= 'f')
/* 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;
+ tree arg1, arg2;
+ int notrunc;
{
unsigned HOST_WIDE_INT int1l, int2l;
HOST_WIDE_INT int1h, int2h;
HOST_WIDE_INT hi;
unsigned HOST_WIDE_INT garbagel;
HOST_WIDE_INT garbageh;
- register tree t;
- int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
+ tree t;
+ 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;
/* 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;
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;
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;
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);
}
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))
static tree
const_binop (code, arg1, arg2, notrunc)
enum tree_code code;
- register tree arg1, arg2;
+ tree arg1, arg2;
int notrunc;
{
STRIP_NOPS (arg1);
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)
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
if (TREE_CODE (arg1) == COMPLEX_CST)
{
- register tree type = TREE_TYPE (arg1);
- register tree r1 = TREE_REALPART (arg1);
- register tree i1 = TREE_IMAGPART (arg1);
- register tree r2 = TREE_REALPART (arg2);
- register tree i2 = TREE_IMAGPART (arg2);
- register tree t;
+ tree type = TREE_TYPE (arg1);
+ tree r1 = TREE_REALPART (arg1);
+ tree i1 = TREE_IMAGPART (arg1);
+ tree r2 = TREE_REALPART (arg2);
+ tree i2 = TREE_IMAGPART (arg2);
+ tree t;
switch (code)
{
case RDIV_EXPR:
{
- register tree magsquared
+ tree magsquared
= const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r2, r2, notrunc),
const_binop (MULT_EXPR, i2, i2, 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));
+}
\f
/* 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. */
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
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)
static tree
fold_convert (t, arg1)
- register tree t;
- register tree arg1;
+ tree t;
+ tree arg1;
{
- register tree type = TREE_TYPE (t);
+ tree type = TREE_TYPE (t);
int overflow = 0;
if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
if (!const_p)
{
/* If this is not a constant, we can only do something if bit positions,
- sizes, and signedness are the same. */
+ sizes, and signedness are the same. */
rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
&runsignedp, &rvolatilep, &alignment);
{
if (code == CEIL_DIV_EXPR)
code = FLOOR_DIV_EXPR;
- else if (code == CEIL_MOD_EXPR)
- code = FLOOR_MOD_EXPR;
else if (code == FLOOR_DIV_EXPR)
code = CEIL_DIV_EXPR;
- else if (code == FLOOR_MOD_EXPR)
- code = CEIL_MOD_EXPR;
- else if (code != MULT_EXPR)
+ else if (code != MULT_EXPR
+ && code != CEIL_MOD_EXPR && code != FLOOR_MOD_EXPR)
break;
}
fold (expr)
tree expr;
{
- register tree t = expr;
+ tree t = expr;
tree t1 = NULL_TREE;
tree tem;
tree type = TREE_TYPE (expr);
- register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
- register enum tree_code code = TREE_CODE (t);
- register int kind = TREE_CODE_CLASS (code);
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (t);
+ int kind = TREE_CODE_CLASS (code);
int invert;
/* WINS will be nonzero when the switch is done
if all operands are constant. */
}
else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
{
- register int len = first_rtl_op (code);
- register int i;
+ int len = first_rtl_op (code);
+ int i;
for (i = 0; i < len; i++)
{
tree op = TREE_OPERAND (t, i);
/* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
is a rotate of A by B bits. */
{
- register enum tree_code code0, code1;
+ enum tree_code code0, code1;
code0 = TREE_CODE (arg0);
code1 = TREE_CODE (arg1);
if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
TREE_OPERAND (arg1, 0), 0)
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
- register tree tree01, tree11;
- register enum tree_code code01, code11;
+ tree tree01, tree11;
+ enum tree_code code01, code11;
tree01 = TREE_OPERAND (arg0, 1);
tree11 = TREE_OPERAND (arg1, 1);
return 1;
case INTEGER_CST:
return tree_int_cst_sgn (t) >= 0;
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case TRUNC_MOD_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case COND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
&& tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case BIND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ case SAVE_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ case NON_LVALUE_EXPR:
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case RTL_EXPR:
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));