Commit 2b60792f by Richard Guenther Committed by Richard Biener

builtins.c (fold_builtin_int_roundingfn): Use fit_double_type.

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.

From-SVN: r120593
parent 61fcaeef
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> 2007-01-08 Jan Hubicka <jh@suse.cz>
* tree-vectorizer.c (gate_increase_alignment): Fix return type. * tree-vectorizer.c (gate_increase_alignment): Fix return type.
......
...@@ -7576,7 +7576,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist) ...@@ -7576,7 +7576,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x)) if (! REAL_VALUE_ISNAN (x) && ! REAL_VALUE_ISINF (x))
{ {
tree itype = TREE_TYPE (TREE_TYPE (fndecl)); 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; HOST_WIDE_INT hi, lo;
REAL_VALUE_TYPE r; REAL_VALUE_TYPE r;
...@@ -7602,11 +7603,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist) ...@@ -7602,11 +7603,8 @@ fold_builtin_int_roundingfn (tree fndecl, tree arglist)
} }
REAL_VALUE_TO_INT (&lo, &hi, r); REAL_VALUE_TO_INT (&lo, &hi, r);
result = build_int_cst_wide (itype, lo, hi); if (!fit_double_type (lo, hi, &lo2, &hi, itype))
result = force_fit_type (result, 0, false, false); return build_int_cst_wide (itype, lo2, hi);
if (TREE_INT_CST_LOW (result) == lo
&& TREE_INT_CST_HIGH (result) == hi)
return result;
} }
} }
......
...@@ -192,58 +192,44 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low, ...@@ -192,58 +192,44 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
*hi = words[2] + words[3] * BASE; *hi = words[2] + words[3] * BASE;
} }
/* T is an INT_CST node. OVERFLOWABLE indicates if we are interested /* Force the double-word integer L1, H1 to be within the range of the
in overflow of the value, when >0 we are only interested in signed integer type TYPE. Stores the properly truncated and sign-extended
overflow, for <0 we are interested in any overflow. OVERFLOWED double-word integer in *LV, *HV. Returns true if the operation
indicates whether overflow has already occurred. CONST_OVERFLOWED overflows, that is, argument and result are different. */
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 int
force_fit_type (tree t, int overflowable, fit_double_type (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
bool overflowed, bool overflowed_const) unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, tree type)
{ {
unsigned HOST_WIDE_INT low; unsigned HOST_WIDE_INT low0 = l1;
HOST_WIDE_INT high; HOST_WIDE_INT high0 = h1;
unsigned int prec; unsigned int prec;
int sign_extended_type; int sign_extended_type;
gcc_assert (TREE_CODE (t) == INTEGER_CST); if (POINTER_TYPE_P (type)
|| TREE_CODE (type) == OFFSET_TYPE)
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)
prec = POINTER_SIZE; prec = POINTER_SIZE;
else else
prec = TYPE_PRECISION (TREE_TYPE (t)); prec = TYPE_PRECISION (type);
/* Size types *are* sign extended. */ /* Size types *are* sign extended. */
sign_extended_type = (!TYPE_UNSIGNED (TREE_TYPE (t)) sign_extended_type = (!TYPE_UNSIGNED (type)
|| (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE || (TREE_CODE (type) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (t)))); && TYPE_IS_SIZETYPE (type)));
/* First clear all bits that are beyond the type's precision. */ /* First clear all bits that are beyond the type's precision. */
if (prec >= 2 * HOST_BITS_PER_WIDE_INT) if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
; ;
else if (prec > 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 else
{ {
high = 0; h1 = 0;
if (prec < HOST_BITS_PER_WIDE_INT) 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) if (!sign_extended_type)
/* No sign extension */; /* No sign extension */;
else if (prec >= 2 * HOST_BITS_PER_WIDE_INT) else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
...@@ -251,28 +237,70 @@ force_fit_type (tree t, int overflowable, ...@@ -251,28 +237,70 @@ force_fit_type (tree t, int overflowable,
else if (prec > HOST_BITS_PER_WIDE_INT) else if (prec > HOST_BITS_PER_WIDE_INT)
{ {
/* Sign extend top half? */ /* Sign extend top half? */
if (high & ((unsigned HOST_WIDE_INT)1 if (h1 & ((unsigned HOST_WIDE_INT)1
<< (prec - HOST_BITS_PER_WIDE_INT - 1))) << (prec - HOST_BITS_PER_WIDE_INT - 1)))
high |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT); h1 |= (HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT);
} }
else if (prec == HOST_BITS_PER_WIDE_INT) else if (prec == HOST_BITS_PER_WIDE_INT)
{ {
if ((HOST_WIDE_INT)low < 0) if ((HOST_WIDE_INT)l1 < 0)
high = -1; h1 = -1;
} }
else else
{ {
/* Sign extend bottom half? */ /* Sign extend bottom half? */
if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1))) if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
{ {
high = -1; h1 = -1;
low |= (HOST_WIDE_INT)(-1) << prec; 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 the value changed, return a new node. */
if (overflowed || overflowed_const if (overflowed || overflowed_const || overflow)
|| low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
{ {
t = build_int_cst_wide (TREE_TYPE (t), low, high); t = build_int_cst_wide (TREE_TYPE (t), low, high);
......
...@@ -779,53 +779,14 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low) ...@@ -779,53 +779,14 @@ build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
tree tree
build_int_cst_type (tree type, HOST_WIDE_INT low) build_int_cst_type (tree type, HOST_WIDE_INT low)
{ {
unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low; unsigned HOST_WIDE_INT low1;
unsigned HOST_WIDE_INT hi, mask; HOST_WIDE_INT hi;
unsigned bits;
bool signed_p;
bool negative;
if (!type) gcc_assert (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);
/* For unsigned type we need to mask out the bits outside of the type fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, 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;
}
}
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 /* These are the hash table functions for the hash table of INTEGER_CST
...@@ -1818,9 +1779,6 @@ size_in_bytes (tree type) ...@@ -1818,9 +1779,6 @@ size_in_bytes (tree type)
return size_zero_node; return size_zero_node;
} }
if (TREE_CODE (t) == INTEGER_CST)
t = force_fit_type (t, 0, false, false);
return t; return t;
} }
...@@ -6009,12 +5967,13 @@ int_fits_type_p (tree c, tree type) ...@@ -6009,12 +5967,13 @@ int_fits_type_p (tree c, tree type)
tree type_low_bound = TYPE_MIN_VALUE (type); tree type_low_bound = TYPE_MIN_VALUE (type);
tree type_high_bound = TYPE_MAX_VALUE (type); tree type_high_bound = TYPE_MAX_VALUE (type);
bool ok_for_low_bound, ok_for_high_bound; 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 /* 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 ourselves and maybe make a decision. If no such decision is possible, but
this type is a subtype, try checking against that. Otherwise, use 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 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 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) ...@@ -6069,12 +6028,10 @@ int_fits_type_p (tree c, tree type)
&& TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type))) && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (type)))
return int_fits_type_p (c, TREE_TYPE (type)); return int_fits_type_p (c, TREE_TYPE (type));
/* Or to force_fit_type, if nothing else. */ /* Or to fit_double_type, if nothing else. */
tmp = copy_node (c); low = TREE_INT_CST_LOW (c);
TREE_TYPE (tmp) = type; high = TREE_INT_CST_HIGH (c);
tmp = force_fit_type (tmp, -1, false, false); return !fit_double_type (low, high, &low, &high, type);
return TREE_INT_CST_HIGH (tmp) == TREE_INT_CST_HIGH (c)
&& TREE_INT_CST_LOW (tmp) == TREE_INT_CST_LOW (c);
} }
/* Subprogram of following function. Called by walk_tree. /* Subprogram of following function. Called by walk_tree.
......
...@@ -4321,6 +4321,8 @@ extern tree fold_indirect_ref_1 (tree, tree); ...@@ -4321,6 +4321,8 @@ extern tree fold_indirect_ref_1 (tree, tree);
extern tree force_fit_type (tree, int, bool, bool); 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, 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,
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment