Message ID | 633567834.20100627193328@post.ru |
---|---|
State | New |
Headers | show |
2010/6/27 Anatoly Sokolov <aesok@post.ru>: > Hello. > > This patch move force_fit_type_double function from double-int.[ch] to > tree.[ch]. This should allow remove dependency double-int.[ch] from the > tree.h in future. > > Also, this patch change force_fit_type_double argument list. They receive > double int constant in double-int type, not as pair of HOST_WIDE_INT. > > Bootstrapped/regtested on x86_64-unknown-linux-gnu. > > OK for mainline? Ok. Thanks, Richard. > * double-int.h (force_fit_type_double): Remove declaration. > * double-int.c (force_fit_type_double): Move to tree.c. > * tree.h (force_fit_type_double): Declare. > * tree.h (force_fit_type_double): Moved from double-int.c. Use > double_int type for 'cst' argument. Use double_int_fits_to_tree_p and > double_int_to_tree instead of fit_double_type and build_int_cst_wide. > * convert.c (convert_to_pointer): Adjust call to > force_fit_type_double. > * tree-vrp.c (extract_range_from_assert, > extract_range_from_unary_expr): Adjust call to force_fit_type_double. > * fold-const.c: Update comment. > (int_const_binop, fold_convert_const_int_from_int, > fold_convert_const_int_from_real, fold_convert_const_int_from_fixed, > extract_muldiv_1, fold_div_compare, fold_sign_changed_comparison, > fold_unary_loc, fold_negate_const, fold_abs_const, fold_not_const, > round_up_loc): Adjust call to force_fit_type_double. > > /c-family > * c-common.c (shorten_compare): Adjust call to force_fit_type_double. > > > > Index: gcc/tree-vrp.c > =================================================================== > --- gcc/tree-vrp.c (revision 161254) > +++ gcc/tree-vrp.c (working copy) > @@ -1507,10 +1507,10 @@ > /* Make sure to not set TREE_OVERFLOW on the final type > conversion. We are willingly interpreting large positive > unsigned values as negative singed values here. */ > - min = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (min), > - TREE_INT_CST_HIGH (min), 0, false); > - max = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (max), > - TREE_INT_CST_HIGH (max), 0, false); > + min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min), > + 0, false); > + max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max), > + 0, false); > > /* We can transform a max, min range to an anti-range or > vice-versa. Use set_and_canonicalize_value_range which does > @@ -2783,11 +2783,11 @@ > { > tree new_min, new_max; > new_min = force_fit_type_double (outer_type, > - TREE_INT_CST_LOW (vr0.min), > - TREE_INT_CST_HIGH (vr0.min), 0, 0); > + tree_to_double_int (vr0.min), > + 0, false); > new_max = force_fit_type_double (outer_type, > - TREE_INT_CST_LOW (vr0.max), > - TREE_INT_CST_HIGH (vr0.max), 0, 0); > + tree_to_double_int (vr0.max), > + 0, false); > if (is_overflow_infinity (vr0.min)) > new_min = negative_overflow_infinity (outer_type); > if (is_overflow_infinity (vr0.max)) > Index: gcc/c-family/c-common.c > =================================================================== > --- gcc/c-family/c-common.c (revision 161254) > +++ gcc/c-family/c-common.c (working copy) > @@ -3361,9 +3361,8 @@ > /* Convert primop1 to target type, but do not introduce > additional overflow. We know primop1 is an int_cst. */ > primop1 = force_fit_type_double (*restype_ptr, > - TREE_INT_CST_LOW (primop1), > - TREE_INT_CST_HIGH (primop1), 0, > - TREE_OVERFLOW (primop1)); > + tree_to_double_int (primop1), > + 0, TREE_OVERFLOW (primop1)); > } > if (type != *restype_ptr) > { > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c (revision 161254) > +++ gcc/tree.c (working copy) > @@ -1092,6 +1092,52 @@ > return double_int_equal_p (cst, ext); > } > > +/* We force the double_int CST to the range of the type TYPE by sign or > + zero extending it. 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 return a new tree node for the extended double_int. The node > + is shared if no overflow flags are set. */ > + > + > +tree > +force_fit_type_double (tree type, double_int cst, int overflowable, > + bool overflowed) > +{ > + bool sign_extended_type; > + > + /* Size types *are* sign extended. */ > + sign_extended_type = (!TYPE_UNSIGNED (type) > + || (TREE_CODE (type) == INTEGER_TYPE > + && TYPE_IS_SIZETYPE (type))); > + > + /* If we need to set overflow flags, return a new unshared node. */ > + if (overflowed || !double_int_fits_to_tree_p(type, cst)) > + { > + if (overflowed > + || overflowable < 0 > + || (overflowable > 0 && sign_extended_type)) > + { > + tree t = make_node (INTEGER_CST); > + TREE_INT_CST (t) = double_int_ext (cst, TYPE_PRECISION (type), > + !sign_extended_type); > + TREE_TYPE (t) = type; > + TREE_OVERFLOW (t) = 1; > + return t; > + } > + } > + > + /* Else build a shared node. */ > + return double_int_to_tree (type, cst); > +} > + > /* These are the hash table functions for the hash table of INTEGER_CST > nodes of a sizetype. */ > > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h (revision 161254) > +++ gcc/tree.h (working copy) > @@ -4014,6 +4014,7 @@ > > extern tree double_int_to_tree (tree, double_int); > extern bool double_int_fits_to_tree_p (const_tree, double_int); > +extern tree force_fit_type_double (tree, double_int, int, bool); > > /* Create an INT_CST node with a CST value zero extended. */ > > Index: gcc/fold-const.c > =================================================================== > --- gcc/fold-const.c (revision 161254) > +++ gcc/fold-const.c (working copy) > @@ -27,8 +27,7 @@ > @@ This would also make life easier when this technology is used > @@ for cross-compilers. */ > > -/* The entry points in this file are fold, size_int_wide, size_binop > - and force_fit_type_double. > +/* The entry points in this file are fold, size_int_wide and size_binop. > > fold takes a tree as argument and returns a simplified tree. > > @@ -39,10 +38,6 @@ > size_int takes an integer value, and creates a tree constant > with type from `sizetype'. > > - force_fit_type_double takes a constant, an overflowable flag and a > - prior overflow indicator. It forces the value to fit the type and > - sets TREE_OVERFLOW. > - > Note: Since the folders get called on non-gimple code as well as > gimple code, we need to handle GIMPLE tuples as well as their > corresponding tree equivalents. */ > @@ -141,7 +136,7 @@ > static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree); > static bool reorder_operands_p (const_tree, const_tree); > static tree fold_negate_const (tree, tree); > -static tree fold_not_const (tree, tree); > +static tree fold_not_const (const_tree, tree); > static tree fold_relational_const (enum tree_code, tree, tree, tree); > static tree fold_convert_const (enum tree_code, tree, tree); > > @@ -1077,7 +1072,7 @@ > } > } > else > - t = force_fit_type_double (TREE_TYPE (arg1), res.low, res.high, 1, > + t = force_fit_type_double (TREE_TYPE (arg1), res, 1, > ((!uns || is_sizetype) && overflow) > | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)); > > @@ -1521,8 +1516,7 @@ > > /* Given an integer constant, make new constant with new type, > appropriately sign-extended or truncated. */ > - t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1), > - TREE_INT_CST_HIGH (arg1), > + t = force_fit_type_double (type, tree_to_double_int (arg1), > !POINTER_TYPE_P (TREE_TYPE (arg1)), > (TREE_INT_CST_HIGH (arg1) < 0 > && (TYPE_UNSIGNED (type) > @@ -1602,8 +1596,7 @@ > if (! overflow) > real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r); > > - t = force_fit_type_double (type, val.low, val.high, -1, > - overflow | TREE_OVERFLOW (arg1)); > + t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1)); > return t; > } > > @@ -1646,7 +1639,7 @@ > > /* Given a fixed-point constant, make new constant with new type, > appropriately sign-extended or truncated. */ > - t = force_fit_type_double (type, temp.low, temp.high, -1, > + t = force_fit_type_double (type, temp, -1, > (double_int_negative_p (temp) > && (TYPE_UNSIGNED (type) > < TYPE_UNSIGNED (TREE_TYPE (arg1)))) > @@ -5963,8 +5956,7 @@ > && 0 != (t1 = int_const_binop (MULT_EXPR, > fold_convert (ctype, op1), > fold_convert (ctype, c), 1)) > - && 0 != (t1 = force_fit_type_double (ctype, TREE_INT_CST_LOW (t1), > - TREE_INT_CST_HIGH (t1), > + && 0 != (t1 = force_fit_type_double (ctype, tree_to_double_int (t1), > (TYPE_UNSIGNED (ctype) > && tcode != MULT_EXPR) ? -1 : 1, > TREE_OVERFLOW (t1))) > @@ -6368,8 +6360,7 @@ > tree prod, tmp, hi, lo; > tree arg00 = TREE_OPERAND (arg0, 0); > tree arg01 = TREE_OPERAND (arg0, 1); > - unsigned HOST_WIDE_INT lpart; > - HOST_WIDE_INT hpart; > + double_int val; > bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0)); > bool neg_overflow; > int overflow; > @@ -6380,9 +6371,8 @@ > TREE_INT_CST_HIGH (arg01), > TREE_INT_CST_LOW (arg1), > TREE_INT_CST_HIGH (arg1), > - &lpart, &hpart, unsigned_p); > - prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart, > - -1, overflow); > + &val.low, &val.high, unsigned_p); > + prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow); > neg_overflow = false; > > if (unsigned_p) > @@ -6396,8 +6386,8 @@ > TREE_INT_CST_HIGH (prod), > TREE_INT_CST_LOW (tmp), > TREE_INT_CST_HIGH (tmp), > - &lpart, &hpart, unsigned_p); > - hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart, > + &val.low, &val.high, unsigned_p); > + hi = force_fit_type_double (TREE_TYPE (arg00), val, > -1, overflow | TREE_OVERFLOW (prod)); > } > else if (tree_int_cst_sgn (arg01) >= 0) > @@ -6850,9 +6840,8 @@ > return NULL_TREE; > > if (TREE_CODE (arg1) == INTEGER_CST) > - arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1), > - TREE_INT_CST_HIGH (arg1), 0, > - TREE_OVERFLOW (arg1)); > + arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1), > + 0, TREE_OVERFLOW (arg1)); > else > arg1 = fold_convert_loc (loc, inner_type, arg1); > > @@ -7957,9 +7946,8 @@ > } > if (change) > { > - tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1), > - TREE_INT_CST_HIGH (and1), 0, > - TREE_OVERFLOW (and1)); > + tem = force_fit_type_double (type, tree_to_double_int (and1), > + 0, TREE_OVERFLOW (and1)); > return fold_build2_loc (loc, BIT_AND_EXPR, type, > fold_convert_loc (loc, type, and0), tem); > } > @@ -15155,12 +15143,10 @@ > { > case INTEGER_CST: > { > - unsigned HOST_WIDE_INT low; > - HOST_WIDE_INT high; > - int overflow = neg_double (TREE_INT_CST_LOW (arg0), > - TREE_INT_CST_HIGH (arg0), > - &low, &high); > - t = force_fit_type_double (type, low, high, 1, > + double_int val = tree_to_double_int (arg0); > + int overflow = neg_double (val.low, val.high, &val.low, &val.high); > + > + t = force_fit_type_double (type, val, 1, > (overflow | TREE_OVERFLOW (arg0)) > && !TYPE_UNSIGNED (type)); > break; > @@ -15203,25 +15189,26 @@ > switch (TREE_CODE (arg0)) > { > case INTEGER_CST: > - /* If the value is unsigned, then the absolute value is > - the same as the ordinary value. */ > - if (TYPE_UNSIGNED (type)) > - t = arg0; > - /* Similarly, if the value is non-negative. */ > - else if (INT_CST_LT (integer_minus_one_node, arg0)) > - t = arg0; > - /* If the value is negative, then the absolute value is > - its negation. */ > - else > - { > - unsigned HOST_WIDE_INT low; > - HOST_WIDE_INT high; > - int overflow = neg_double (TREE_INT_CST_LOW (arg0), > - TREE_INT_CST_HIGH (arg0), > - &low, &high); > - t = force_fit_type_double (type, low, high, -1, > - overflow | TREE_OVERFLOW (arg0)); > - } > + { > + double_int val = tree_to_double_int (arg0); > + > + /* If the value is unsigned or non-negative, then the absolute value > + is the same as the ordinary value. */ > + if (TYPE_UNSIGNED (type) > + || !double_int_negative_p (val)) > + t = arg0; > + > + /* If the value is negative, then the absolute value is > + its negation. */ > + else > + { > + int overflow; > + > + overflow = neg_double (val.low, val.high, &val.low, &val.high); > + t = force_fit_type_double (type, val, -1, > + overflow | TREE_OVERFLOW (arg0)); > + } > + } > break; > > case REAL_CST: > @@ -15242,17 +15229,14 @@ > constant. TYPE is the type of the result. */ > > static tree > -fold_not_const (tree arg0, tree type) > +fold_not_const (const_tree arg0, tree type) > { > - tree t = NULL_TREE; > + double_int val; > > gcc_assert (TREE_CODE (arg0) == INTEGER_CST); > > - t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0), > - ~TREE_INT_CST_HIGH (arg0), 0, > - TREE_OVERFLOW (arg0)); > - > - return t; > + val = double_int_not (tree_to_double_int (arg0)); > + return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0)); > } > > /* Given CODE, a relational operator, the target type, TYPE and two > @@ -15650,25 +15634,23 @@ > { > if (TREE_CODE (value) == INTEGER_CST) > { > - unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (value); > - unsigned HOST_WIDE_INT high; > + double_int val = tree_to_double_int (value); > bool overflow_p; > > - if ((low & (divisor - 1)) == 0) > + if ((val.low & (divisor - 1)) == 0) > return value; > > overflow_p = TREE_OVERFLOW (value); > - high = TREE_INT_CST_HIGH (value); > - low &= ~(divisor - 1); > - low += divisor; > - if (low == 0) > + val.low &= ~(divisor - 1); > + val.low += divisor; > + if (val.low == 0) > { > - high++; > - if (high == 0) > + val.high++; > + if (val.high == 0) > overflow_p = true; > } > > - return force_fit_type_double (TREE_TYPE (value), low, high, > + return force_fit_type_double (TREE_TYPE (value), val, > -1, overflow_p); > } > else > Index: gcc/double-int.c > =================================================================== > --- gcc/double-int.c (revision 161254) > +++ gcc/double-int.c (working copy) > @@ -134,56 +134,6 @@ > return l1 != low0 || h1 != high0; > } > > -/* We force the double-int HIGH:LOW to the range of the type TYPE by > - sign or zero extending it. > - 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 return a new tree node for the extended double-int. The node > - is shared if no overflow flags are set. */ > - > -tree > -force_fit_type_double (tree type, unsigned HOST_WIDE_INT low, > - HOST_WIDE_INT high, int overflowable, > - bool overflowed) > -{ > - int sign_extended_type; > - bool overflow; > - > - /* Size types *are* sign extended. */ > - sign_extended_type = (!TYPE_UNSIGNED (type) > - || (TREE_CODE (type) == INTEGER_TYPE > - && TYPE_IS_SIZETYPE (type))); > - > - overflow = fit_double_type (low, high, &low, &high, type); > - > - /* If we need to set overflow flags, return a new unshared node. */ > - if (overflowed || overflow) > - { > - if (overflowed > - || overflowable < 0 > - || (overflowable > 0 && sign_extended_type)) > - { > - tree t = make_node (INTEGER_CST); > - TREE_INT_CST_LOW (t) = low; > - TREE_INT_CST_HIGH (t) = high; > - TREE_TYPE (t) = type; > - TREE_OVERFLOW (t) = 1; > - return t; > - } > - } > - > - /* Else build a shared node. */ > - return build_int_cst_wide (type, low, high); > -} > - > /* Add two doubleword integers with doubleword result. > Return nonzero if the operation overflows according to UNSIGNED_P. > Each argument is given as two `HOST_WIDE_INT' pieces. > Index: gcc/double-int.h > =================================================================== > --- gcc/double-int.h (revision 161254) > +++ gcc/double-int.h (working copy) > @@ -269,8 +269,6 @@ > > /* Legacy interface with decomposed high/low parts. */ > > -extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT, > - int, bool); > extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT, > unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, > const_tree); > Index: gcc/convert.c > =================================================================== > --- gcc/convert.c (revision 161254) > +++ gcc/convert.c (working copy) > @@ -46,7 +46,8 @@ > > /* Propagate overflow to the NULL pointer. */ > if (integer_zerop (expr)) > - return force_fit_type_double (type, 0, 0, 0, TREE_OVERFLOW (expr)); > + return force_fit_type_double (type, double_int_zero, 0, > + TREE_OVERFLOW (expr)); > > switch (TREE_CODE (TREE_TYPE (expr))) > { > > > Anatoly. > >
Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 161254) +++ gcc/tree-vrp.c (working copy) @@ -1507,10 +1507,10 @@ /* Make sure to not set TREE_OVERFLOW on the final type conversion. We are willingly interpreting large positive unsigned values as negative singed values here. */ - min = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (min), - TREE_INT_CST_HIGH (min), 0, false); - max = force_fit_type_double (TREE_TYPE (var), TREE_INT_CST_LOW (max), - TREE_INT_CST_HIGH (max), 0, false); + min = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (min), + 0, false); + max = force_fit_type_double (TREE_TYPE (var), tree_to_double_int (max), + 0, false); /* We can transform a max, min range to an anti-range or vice-versa. Use set_and_canonicalize_value_range which does @@ -2783,11 +2783,11 @@ { tree new_min, new_max; new_min = force_fit_type_double (outer_type, - TREE_INT_CST_LOW (vr0.min), - TREE_INT_CST_HIGH (vr0.min), 0, 0); + tree_to_double_int (vr0.min), + 0, false); new_max = force_fit_type_double (outer_type, - TREE_INT_CST_LOW (vr0.max), - TREE_INT_CST_HIGH (vr0.max), 0, 0); + tree_to_double_int (vr0.max), + 0, false); if (is_overflow_infinity (vr0.min)) new_min = negative_overflow_infinity (outer_type); if (is_overflow_infinity (vr0.max)) Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 161254) +++ gcc/c-family/c-common.c (working copy) @@ -3361,9 +3361,8 @@ /* Convert primop1 to target type, but do not introduce additional overflow. We know primop1 is an int_cst. */ primop1 = force_fit_type_double (*restype_ptr, - TREE_INT_CST_LOW (primop1), - TREE_INT_CST_HIGH (primop1), 0, - TREE_OVERFLOW (primop1)); + tree_to_double_int (primop1), + 0, TREE_OVERFLOW (primop1)); } if (type != *restype_ptr) { Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 161254) +++ gcc/tree.c (working copy) @@ -1092,6 +1092,52 @@ return double_int_equal_p (cst, ext); } +/* We force the double_int CST to the range of the type TYPE by sign or + zero extending it. 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 return a new tree node for the extended double_int. The node + is shared if no overflow flags are set. */ + + +tree +force_fit_type_double (tree type, double_int cst, int overflowable, + bool overflowed) +{ + bool sign_extended_type; + + /* Size types *are* sign extended. */ + sign_extended_type = (!TYPE_UNSIGNED (type) + || (TREE_CODE (type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (type))); + + /* If we need to set overflow flags, return a new unshared node. */ + if (overflowed || !double_int_fits_to_tree_p(type, cst)) + { + if (overflowed + || overflowable < 0 + || (overflowable > 0 && sign_extended_type)) + { + tree t = make_node (INTEGER_CST); + TREE_INT_CST (t) = double_int_ext (cst, TYPE_PRECISION (type), + !sign_extended_type); + TREE_TYPE (t) = type; + TREE_OVERFLOW (t) = 1; + return t; + } + } + + /* Else build a shared node. */ + return double_int_to_tree (type, cst); +} + /* These are the hash table functions for the hash table of INTEGER_CST nodes of a sizetype. */ Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 161254) +++ gcc/tree.h (working copy) @@ -4014,6 +4014,7 @@ extern tree double_int_to_tree (tree, double_int); extern bool double_int_fits_to_tree_p (const_tree, double_int); +extern tree force_fit_type_double (tree, double_int, int, bool); /* Create an INT_CST node with a CST value zero extended. */ Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 161254) +++ gcc/fold-const.c (working copy) @@ -27,8 +27,7 @@ @@ This would also make life easier when this technology is used @@ for cross-compilers. */ -/* The entry points in this file are fold, size_int_wide, size_binop - and force_fit_type_double. +/* The entry points in this file are fold, size_int_wide and size_binop. fold takes a tree as argument and returns a simplified tree. @@ -39,10 +38,6 @@ size_int takes an integer value, and creates a tree constant with type from `sizetype'. - force_fit_type_double takes a constant, an overflowable flag and a - prior overflow indicator. It forces the value to fit the type and - sets TREE_OVERFLOW. - Note: Since the folders get called on non-gimple code as well as gimple code, we need to handle GIMPLE tuples as well as their corresponding tree equivalents. */ @@ -141,7 +136,7 @@ static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree); static bool reorder_operands_p (const_tree, const_tree); static tree fold_negate_const (tree, tree); -static tree fold_not_const (tree, tree); +static tree fold_not_const (const_tree, tree); static tree fold_relational_const (enum tree_code, tree, tree, tree); static tree fold_convert_const (enum tree_code, tree, tree); @@ -1077,7 +1072,7 @@ } } else - t = force_fit_type_double (TREE_TYPE (arg1), res.low, res.high, 1, + t = force_fit_type_double (TREE_TYPE (arg1), res, 1, ((!uns || is_sizetype) && overflow) | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)); @@ -1521,8 +1516,7 @@ /* Given an integer constant, make new constant with new type, appropriately sign-extended or truncated. */ - t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1), - TREE_INT_CST_HIGH (arg1), + t = force_fit_type_double (type, tree_to_double_int (arg1), !POINTER_TYPE_P (TREE_TYPE (arg1)), (TREE_INT_CST_HIGH (arg1) < 0 && (TYPE_UNSIGNED (type) @@ -1602,8 +1596,7 @@ if (! overflow) real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r); - t = force_fit_type_double (type, val.low, val.high, -1, - overflow | TREE_OVERFLOW (arg1)); + t = force_fit_type_double (type, val, -1, overflow | TREE_OVERFLOW (arg1)); return t; } @@ -1646,7 +1639,7 @@ /* Given a fixed-point constant, make new constant with new type, appropriately sign-extended or truncated. */ - t = force_fit_type_double (type, temp.low, temp.high, -1, + t = force_fit_type_double (type, temp, -1, (double_int_negative_p (temp) && (TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (arg1)))) @@ -5963,8 +5956,7 @@ && 0 != (t1 = int_const_binop (MULT_EXPR, fold_convert (ctype, op1), fold_convert (ctype, c), 1)) - && 0 != (t1 = force_fit_type_double (ctype, TREE_INT_CST_LOW (t1), - TREE_INT_CST_HIGH (t1), + && 0 != (t1 = force_fit_type_double (ctype, tree_to_double_int (t1), (TYPE_UNSIGNED (ctype) && tcode != MULT_EXPR) ? -1 : 1, TREE_OVERFLOW (t1))) @@ -6368,8 +6360,7 @@ tree prod, tmp, hi, lo; tree arg00 = TREE_OPERAND (arg0, 0); tree arg01 = TREE_OPERAND (arg0, 1); - unsigned HOST_WIDE_INT lpart; - HOST_WIDE_INT hpart; + double_int val; bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0)); bool neg_overflow; int overflow; @@ -6380,9 +6371,8 @@ TREE_INT_CST_HIGH (arg01), TREE_INT_CST_LOW (arg1), TREE_INT_CST_HIGH (arg1), - &lpart, &hpart, unsigned_p); - prod = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart, - -1, overflow); + &val.low, &val.high, unsigned_p); + prod = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow); neg_overflow = false; if (unsigned_p) @@ -6396,8 +6386,8 @@ TREE_INT_CST_HIGH (prod), TREE_INT_CST_LOW (tmp), TREE_INT_CST_HIGH (tmp), - &lpart, &hpart, unsigned_p); - hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart, + &val.low, &val.high, unsigned_p); + hi = force_fit_type_double (TREE_TYPE (arg00), val, -1, overflow | TREE_OVERFLOW (prod)); } else if (tree_int_cst_sgn (arg01) >= 0) @@ -6850,9 +6840,8 @@ return NULL_TREE; if (TREE_CODE (arg1) == INTEGER_CST) - arg1 = force_fit_type_double (inner_type, TREE_INT_CST_LOW (arg1), - TREE_INT_CST_HIGH (arg1), 0, - TREE_OVERFLOW (arg1)); + arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1), + 0, TREE_OVERFLOW (arg1)); else arg1 = fold_convert_loc (loc, inner_type, arg1); @@ -7957,9 +7946,8 @@ } if (change) { - tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1), - TREE_INT_CST_HIGH (and1), 0, - TREE_OVERFLOW (and1)); + tem = force_fit_type_double (type, tree_to_double_int (and1), + 0, TREE_OVERFLOW (and1)); return fold_build2_loc (loc, BIT_AND_EXPR, type, fold_convert_loc (loc, type, and0), tem); } @@ -15155,12 +15143,10 @@ { case INTEGER_CST: { - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; - int overflow = neg_double (TREE_INT_CST_LOW (arg0), - TREE_INT_CST_HIGH (arg0), - &low, &high); - t = force_fit_type_double (type, low, high, 1, + double_int val = tree_to_double_int (arg0); + int overflow = neg_double (val.low, val.high, &val.low, &val.high); + + t = force_fit_type_double (type, val, 1, (overflow | TREE_OVERFLOW (arg0)) && !TYPE_UNSIGNED (type)); break; @@ -15203,25 +15189,26 @@ switch (TREE_CODE (arg0)) { case INTEGER_CST: - /* If the value is unsigned, then the absolute value is - the same as the ordinary value. */ - if (TYPE_UNSIGNED (type)) - t = arg0; - /* Similarly, if the value is non-negative. */ - else if (INT_CST_LT (integer_minus_one_node, arg0)) - t = arg0; - /* If the value is negative, then the absolute value is - its negation. */ - else - { - unsigned HOST_WIDE_INT low; - HOST_WIDE_INT high; - int overflow = neg_double (TREE_INT_CST_LOW (arg0), - TREE_INT_CST_HIGH (arg0), - &low, &high); - t = force_fit_type_double (type, low, high, -1, - overflow | TREE_OVERFLOW (arg0)); - } + { + double_int val = tree_to_double_int (arg0); + + /* If the value is unsigned or non-negative, then the absolute value + is the same as the ordinary value. */ + if (TYPE_UNSIGNED (type) + || !double_int_negative_p (val)) + t = arg0; + + /* If the value is negative, then the absolute value is + its negation. */ + else + { + int overflow; + + overflow = neg_double (val.low, val.high, &val.low, &val.high); + t = force_fit_type_double (type, val, -1, + overflow | TREE_OVERFLOW (arg0)); + } + } break; case REAL_CST: @@ -15242,17 +15229,14 @@ constant. TYPE is the type of the result. */ static tree -fold_not_const (tree arg0, tree type) +fold_not_const (const_tree arg0, tree type) { - tree t = NULL_TREE; + double_int val; gcc_assert (TREE_CODE (arg0) == INTEGER_CST); - t = force_fit_type_double (type, ~TREE_INT_CST_LOW (arg0), - ~TREE_INT_CST_HIGH (arg0), 0, - TREE_OVERFLOW (arg0)); - - return t; + val = double_int_not (tree_to_double_int (arg0)); + return force_fit_type_double (type, val, 0, TREE_OVERFLOW (arg0)); } /* Given CODE, a relational operator, the target type, TYPE and two @@ -15650,25 +15634,23 @@ { if (TREE_CODE (value) == INTEGER_CST) { - unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (value); - unsigned HOST_WIDE_INT high; + double_int val = tree_to_double_int (value); bool overflow_p; - if ((low & (divisor - 1)) == 0) + if ((val.low & (divisor - 1)) == 0) return value; overflow_p = TREE_OVERFLOW (value); - high = TREE_INT_CST_HIGH (value); - low &= ~(divisor - 1); - low += divisor; - if (low == 0) + val.low &= ~(divisor - 1); + val.low += divisor; + if (val.low == 0) { - high++; - if (high == 0) + val.high++; + if (val.high == 0) overflow_p = true; } - return force_fit_type_double (TREE_TYPE (value), low, high, + return force_fit_type_double (TREE_TYPE (value), val, -1, overflow_p); } else Index: gcc/double-int.c =================================================================== --- gcc/double-int.c (revision 161254) +++ gcc/double-int.c (working copy) @@ -134,56 +134,6 @@ return l1 != low0 || h1 != high0; } -/* We force the double-int HIGH:LOW to the range of the type TYPE by - sign or zero extending it. - 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 return a new tree node for the extended double-int. The node - is shared if no overflow flags are set. */ - -tree -force_fit_type_double (tree type, unsigned HOST_WIDE_INT low, - HOST_WIDE_INT high, int overflowable, - bool overflowed) -{ - int sign_extended_type; - bool overflow; - - /* Size types *are* sign extended. */ - sign_extended_type = (!TYPE_UNSIGNED (type) - || (TREE_CODE (type) == INTEGER_TYPE - && TYPE_IS_SIZETYPE (type))); - - overflow = fit_double_type (low, high, &low, &high, type); - - /* If we need to set overflow flags, return a new unshared node. */ - if (overflowed || overflow) - { - if (overflowed - || overflowable < 0 - || (overflowable > 0 && sign_extended_type)) - { - tree t = make_node (INTEGER_CST); - TREE_INT_CST_LOW (t) = low; - TREE_INT_CST_HIGH (t) = high; - TREE_TYPE (t) = type; - TREE_OVERFLOW (t) = 1; - return t; - } - } - - /* Else build a shared node. */ - return build_int_cst_wide (type, low, high); -} - /* Add two doubleword integers with doubleword result. Return nonzero if the operation overflows according to UNSIGNED_P. Each argument is given as two `HOST_WIDE_INT' pieces. Index: gcc/double-int.h =================================================================== --- gcc/double-int.h (revision 161254) +++ gcc/double-int.h (working copy) @@ -269,8 +269,6 @@ /* Legacy interface with decomposed high/low parts. */ -extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT, - int, bool); extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, const_tree); Index: gcc/convert.c =================================================================== --- gcc/convert.c (revision 161254) +++ gcc/convert.c (working copy) @@ -46,7 +46,8 @@ /* Propagate overflow to the NULL pointer. */ if (integer_zerop (expr)) - return force_fit_type_double (type, 0, 0, 0, TREE_OVERFLOW (expr)); + return force_fit_type_double (type, double_int_zero, 0, + TREE_OVERFLOW (expr)); switch (TREE_CODE (TREE_TYPE (expr))) {