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
This commit is contained in:
parent
61fcaeefb2
commit
2b60792f2b
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
124
gcc/fold-const.c
124
gcc/fold-const.c
@ -192,6 +192,77 @@ decode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT *low,
|
||||
*hi = words[2] + words[3] * BASE;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
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 low0 = l1;
|
||||
HOST_WIDE_INT high0 = h1;
|
||||
unsigned int prec;
|
||||
int sign_extended_type;
|
||||
|
||||
if (POINTER_TYPE_P (type)
|
||||
|| TREE_CODE (type) == OFFSET_TYPE)
|
||||
prec = POINTER_SIZE;
|
||||
else
|
||||
prec = TYPE_PRECISION (type);
|
||||
|
||||
/* Size types *are* sign extended. */
|
||||
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)
|
||||
h1 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
|
||||
else
|
||||
{
|
||||
h1 = 0;
|
||||
if (prec < HOST_BITS_PER_WIDE_INT)
|
||||
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)
|
||||
/* Correct width already. */;
|
||||
else if (prec > HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
/* Sign extend top half? */
|
||||
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)l1 < 0)
|
||||
h1 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sign extend bottom half? */
|
||||
if (l1 & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
|
||||
{
|
||||
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
|
||||
@ -213,66 +284,23 @@ force_fit_type (tree t, int overflowable,
|
||||
{
|
||||
unsigned HOST_WIDE_INT low;
|
||||
HOST_WIDE_INT high;
|
||||
unsigned int prec;
|
||||
int sign_extended_type;
|
||||
bool overflow;
|
||||
|
||||
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)
|
||||
prec = POINTER_SIZE;
|
||||
else
|
||||
prec = TYPE_PRECISION (TREE_TYPE (t));
|
||||
/* 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))));
|
||||
|
||||
/* First clear all bits that are beyond the type's precision. */
|
||||
low = TREE_INT_CST_LOW (t);
|
||||
high = TREE_INT_CST_HIGH (t);
|
||||
|
||||
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));
|
||||
else
|
||||
{
|
||||
high = 0;
|
||||
if (prec < HOST_BITS_PER_WIDE_INT)
|
||||
low &= ~((HOST_WIDE_INT) (-1) << prec);
|
||||
}
|
||||
|
||||
if (!sign_extended_type)
|
||||
/* No sign extension */;
|
||||
else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
|
||||
/* Correct width already. */;
|
||||
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);
|
||||
}
|
||||
else if (prec == HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
if ((HOST_WIDE_INT)low < 0)
|
||||
high = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sign extend bottom half? */
|
||||
if (low & ((unsigned HOST_WIDE_INT)1 << (prec - 1)))
|
||||
{
|
||||
high = -1;
|
||||
low |= (HOST_WIDE_INT)(-1) << prec;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
|
67
gcc/tree.c
67
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;
|
||||
gcc_assert (type);
|
||||
|
||||
bits = TYPE_PRECISION (type);
|
||||
signed_p = !TYPE_UNSIGNED (type);
|
||||
fit_double_type (low, low < 0 ? -1 : 0, &low1, &hi, 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
|
||||
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
|
||||
@ -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.
|
||||
|
@ -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 *,
|
||||
|
Loading…
x
Reference in New Issue
Block a user