summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/builtins.c10
-rw-r--r--gcc/fold-const.c116
-rw-r--r--gcc/tree.c67
-rw-r--r--gcc/tree.h2
5 files changed, 100 insertions, 105 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index df844328b80..319ed868045 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2007-01-08 Richard Guenther <rguenther@suse.de>
+
+ * builtins.c (fold_builtin_int_roundingfn): Use fit_double_type.
+ * tree.c (build_int_cst_type): Likewise.
+ (size_in_bytes): Don't call force_fit_type on the result.
+ (int_fits_type_p): Use fit_double_type.
+ * fold-const.c (fit_double_type): New function.
+ (force_fit_type): Use it.
+ * tree.h (fit_double_type): Export.
+
2007-01-08 Jan Hubicka <jh@suse.cz>
* tree-vectorizer.c (gate_increase_alignment): Fix return type.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e97e3bb57cb..a39a4c16241 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -7576,7 +7576,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
{
tree itype = TREE_TYPE (TREE_TYPE (fndecl));
- tree ftype = TREE_TYPE (arg), result;
+ tree ftype = TREE_TYPE (arg);
+ unsigned HOST_WIDE_INT lo2;
HOST_WIDE_INT hi, lo;
REAL_VALUE_TYPE r;
@@ -7602,11 +7603,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
}
REAL_VALUE_TO_INT (&lo, &hi, r);
- result = build_int_cst_wide (itype, lo, hi);
- result = force_fit_type (result, 0, false, false);
- if (TREE_INT_CST_LOW (result) == lo
- && TREE_INT_CST_HIGH (result) == hi)
- return result;
+ if (!fit_double_type (lo, hi, &lo2, &hi, itype))
+ return build_int_cst_wide (itype, lo2, hi);
}
}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 559acf018ad..d082ed34088 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -192,58 +192,44 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
*hi = words[2] + words[3] * BASE;
}
-/* T is an INT_CST node. OVERFLOWABLE indicates if we are interested
- in overflow of the value, when >0 we are only interested in signed
- overflow, for <0 we are interested in any overflow. OVERFLOWED
- indicates whether overflow has already occurred. CONST_OVERFLOWED
- indicates whether constant overflow has already occurred. We force
- T's value to be within range of T's type (by setting to 0 or 1 all
- the bits outside the type's range). We set TREE_OVERFLOWED if,
- OVERFLOWED is nonzero,
- or OVERFLOWABLE is >0 and signed overflow occurs
- or OVERFLOWABLE is <0 and any overflow occurs
- We set TREE_CONSTANT_OVERFLOWED if,
- CONST_OVERFLOWED is nonzero
- or we set TREE_OVERFLOWED.
- We return either the original T, or a copy. */
+/* Force the double-word integer L1, H1 to be within the range of the
+ integer type TYPE. Stores the properly truncated and sign-extended
+ double-word integer in *LV, *HV. Returns true if the operation
+ overflows, that is, argument and result are different. */
-tree
-force_fit_type (tree t, int overflowable,
- bool overflowed, bool overflowed_const)
+int
+fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
+ unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, tree type)
{
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
+ unsigned HOST_WIDE_INT low0 = l1;
+ HOST_WIDE_INT high0 = h1;
unsigned int prec;
int sign_extended_type;
- gcc_assert (TREE_CODE (t) == INTEGER_CST);
-
- low = TREE_INT_CST_LOW (t);
- high = TREE_INT_CST_HIGH (t);
-
- if (POINTER_TYPE_P (TREE_TYPE (t))
- || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == OFFSET_TYPE)
prec = POINTER_SIZE;
else
- prec = TYPE_PRECISION (TREE_TYPE (t));
+ prec = TYPE_PRECISION (type);
+
/* Size types *are* sign extended. */
- sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
- || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
+ sign_extended_type = (!TYPE_UNSIGNED (type)
+ || (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)));
/* First clear all bits that are beyond the type's precision. */
-
if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
;
else if (prec > HOST_BITS_PER_WIDE_INT)
- high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+ h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
else
{
- high = 0;
+ h1 = 0;
if (prec < HOST_BITS_PER_WIDE_INT)
- low &= ~((HOST_WIDE_INT) (-1) << prec);
+ l1 &= ~((HOST_WIDE_INT) (-1) << prec);
}
+ /* Then do sign extension if necessary. */
if (!sign_extended_type)
/* No sign extension */;
else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
@@ -251,28 +237,70 @@ force_fit_type (tree t, int overflowable,
else if (prec > HOST_BITS_PER_WIDE_INT)
{
/* Sign extend top half? */
- if (high & ((unsigned HOST_WIDE_INT)1
- << (prec - HOST_BITS_PER_WIDE_INT - 1)))
- high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
+ if (h1 & ((unsigned HOST_WIDE_INT)1
+ << (prec - HOST_BITS_PER_WIDE_INT - 1)))
+ h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
}
else if (prec == HOST_BITS_PER_WIDE_INT)
{
- if ((HOST_WIDE_INT)low < 0)
- high = -1;
+ if ((HOST_WIDE_INT)l1 < 0)
+ h1 = -1;
}
else
{
/* Sign extend bottom half? */
- if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
+ if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
{
- high = -1;
- low |= (HOST_WIDE_INT)(-1) << prec;
+ h1 = -1;
+ l1 |= (HOST_WIDE_INT)(-1) << prec;
}
}
+ *lv = l1;
+ *hv = h1;
+
+ /* If the value didn't fit, signal overflow. */
+ return l1 != low0 || h1 != high0;
+}
+
+/* T is an INT_CST node. OVERFLOWABLE indicates if we are interested
+ in overflow of the value, when >0 we are only interested in signed
+ overflow, for <0 we are interested in any overflow. OVERFLOWED
+ indicates whether overflow has already occurred. CONST_OVERFLOWED
+ indicates whether constant overflow has already occurred. We force
+ T's value to be within range of T's type (by setting to 0 or 1 all
+ the bits outside the type's range). We set TREE_OVERFLOWED if,
+ OVERFLOWED is nonzero,
+ or OVERFLOWABLE is >0 and signed overflow occurs
+ or OVERFLOWABLE is <0 and any overflow occurs
+ We set TREE_CONSTANT_OVERFLOWED if,
+ CONST_OVERFLOWED is nonzero
+ or we set TREE_OVERFLOWED.
+ We return either the original T, or a copy. */
+
+tree
+force_fit_type (tree t, int overflowable,
+ bool overflowed, bool overflowed_const)
+{
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int sign_extended_type;
+ bool overflow;
+
+ gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+ /* Size types *are* sign extended. */
+ sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t))
+ || (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (t))));
+
+ low = TREE_INT_CST_LOW (t);
+ high = TREE_INT_CST_HIGH (t);
+
+ overflow = fit_double_type (low, high, &low, &high, TREE_TYPE (t));
+
/* If the value changed, return a new node. */
- if (overflowed || overflowed_const
- || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
+ if (overflowed || overflowed_const || overflow)
{
t = build_int_cst_wide (TREE_TYPE (t), low, high);
diff --git a/gcc/tree.c b/gcc/tree.c
index e3eb4be8b05..348d288f50f 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -779,53 +779,14 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
tree
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
- unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
- unsigned HOST_WIDE_INT hi, mask;
- unsigned bits;
- bool signed_p;
- bool negative;
+ unsigned HOST_WIDE_INT low1;
+ HOST_WIDE_INT hi;
- if (!type)
- type = integer_type_node;
-
- bits = TYPE_PRECISION (type);
- signed_p = !TYPE_UNSIGNED (type);
-
- if (bits >= HOST_BITS_PER_WIDE_INT)
- negative = (low < 0);
- else
- {
- /* If the sign bit is inside precision of LOW, use it to determine
- the sign of the constant. */
- negative = ((val >> (bits - 1)) & 1) != 0;
-
- /* Mask out the bits outside of the precision of the constant. */
- mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
-
- if (signed_p && negative)
- val |= ~mask;
- else
- val &= mask;
- }
-
- /* Determine the high bits. */
- hi = (negative ? ~(unsigned HOST_WIDE_INT) 0 : 0);
+ gcc_assert (type);
- /* For unsigned type we need to mask out the bits outside of the type
- precision. */
- if (!signed_p)
- {
- if (bits <= HOST_BITS_PER_WIDE_INT)
- hi = 0;
- else
- {
- bits -= HOST_BITS_PER_WIDE_INT;
- mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
- hi &= mask;
- }
- }
+ fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, type);
- return build_int_cst_wide (type, val, hi);
+ return build_int_cst_wide (type, low1, hi);
}
/* These are the hash table functions for the hash table of INTEGER_CST
@@ -1818,9 +1779,6 @@ size_in_bytes (tree type)
return size_zero_node;
}
- if (TREE_CODE (t) == INTEGER_CST)
- t = force_fit_type (t, 0, false, false);
-
return t;
}
@@ -6009,12 +5967,13 @@ int_fits_type_p (tree c, tree type)
tree type_low_bound = TYPE_MIN_VALUE (type);
tree type_high_bound = TYPE_MAX_VALUE (type);
bool ok_for_low_bound, ok_for_high_bound;
- tree tmp;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
/* If at least one bound of the type is a constant integer, we can check
ourselves and maybe make a decision. If no such decision is possible, but
this type is a subtype, try checking against that. Otherwise, use
- force_fit_type, which checks against the precision.
+ fit_double_type, which checks against the precision.
Compute the status for each possibly constant bound, and return if we see
one does not match. Use ok_for_xxx_bound for this purpose, assigning -1
@@ -6069,12 +6028,10 @@ int_fits_type_p (tree c, tree type)
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type)))
return int_fits_type_p (c, TREE_TYPE (type));
- /* Or to force_fit_type, if nothing else. */
- tmp = copy_node (c);
- TREE_TYPE (tmp) = type;
- tmp = force_fit_type (tmp, -1, false, false);
- return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c)
- && TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c);
+ /* Or to fit_double_type, if nothing else. */
+ low = TREE_INT_CST_LOW (c);
+ high = TREE_INT_CST_HIGH (c);
+ return !fit_double_type (low, high, &low, &high, type);
}
/* Subprogram of following function. Called by walk_tree.
diff --git a/gcc/tree.h b/gcc/tree.h
index 9f2d7076c45..fd9e14a585a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4321,6 +4321,8 @@ extern tree fold_indirect_ref_1 (tree, tree);
extern tree force_fit_type (tree, int, bool, bool);
+extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, tree);
extern int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
unsigned HOST_WIDE_INT, HOST_WIDE_INT,
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
OpenPOWER on IntegriCloud