2007-01-08 Richard Guenther * tree.h (force_fit_type_double): Export. (force_fit_type): Remove. * fold-const.c (force_fit_type_double): New function. (force_fit_type): Remove. (int_const_binop): Use it. (fold_convert_const_int_from_int): Likewise. (fold_convert_const_int_from_real): Likewise. (fold_div_compare): Likewise. (fold_sign_changed_comparison): Likewise. (fold_unary): Likewise. (fold_negate_const): Likewise. (fold_abs_const): Likewise. (fold_not_const): Likewise. * c-common.c (shorten_compare): Use force_fit_type_double. * convert.c (convert_to_pointer): Likewise. Index: gcc/c-common.c =================================================================== *** gcc.orig/c-common.c 2007-01-08 20:43:56.000000000 +0100 --- gcc/c-common.c 2007-01-08 20:49:13.000000000 +0100 *************** shorten_compare (tree *op0_ptr, tree *op *** 2316,2327 **** { /* Convert primop1 to target type, but do not introduce additional overflow. We know primop1 is an int_cst. */ ! tree tmp = build_int_cst_wide (*restype_ptr, ! TREE_INT_CST_LOW (primop1), ! TREE_INT_CST_HIGH (primop1)); ! ! primop1 = force_fit_type (tmp, 0, TREE_OVERFLOW (primop1), ! TREE_CONSTANT_OVERFLOW (primop1)); } if (type != *restype_ptr) { --- 2316,2326 ---- { /* 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_CONSTANT_OVERFLOW (primop1)); } if (type != *restype_ptr) { Index: gcc/convert.c =================================================================== *** gcc.orig/convert.c 2007-01-08 20:43:56.000000000 +0100 --- gcc/convert.c 2007-01-08 20:49:13.000000000 +0100 *************** convert_to_pointer (tree type, tree expr *** 44,57 **** if (TREE_TYPE (expr) == type) return expr; if (integer_zerop (expr)) ! { ! tree t = build_int_cst (type, 0); ! if (TREE_OVERFLOW (expr) || TREE_CONSTANT_OVERFLOW (expr)) ! t = force_fit_type (t, 0, TREE_OVERFLOW (expr), ! TREE_CONSTANT_OVERFLOW (expr)); ! return t; ! } switch (TREE_CODE (TREE_TYPE (expr))) { --- 44,53 ---- if (TREE_TYPE (expr) == type) return expr; + /* Propagate overflow to the NULL pointer. */ if (integer_zerop (expr)) ! return force_fit_type_double (type, 0, 0, 0, TREE_OVERFLOW (expr), ! TREE_CONSTANT_OVERFLOW (expr)); switch (TREE_CODE (TREE_TYPE (expr))) { Index: gcc/fold-const.c =================================================================== *** gcc.orig/fold-const.c 2007-01-08 20:43:56.000000000 +0100 --- gcc/fold-const.c 2007-01-08 20:54:29.000000000 +0100 *************** fit_double_type (unsigned HOST_WIDE_INT *** 263,268 **** --- 263,333 ---- 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 set TREE_CONSTANT_OVERFLOWED if, + CONST_OVERFLOWED is nonzero + or we set TREE_OVERFLOWED. + 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, bool overflowed_const) + { + 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 || overflowed_const || 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; + TREE_CONSTANT_OVERFLOW (t) = 1; + + return t; + } + else if (overflowed_const) + { + tree t = make_node (INTEGER_CST); + TREE_INT_CST_LOW (t) = low; + TREE_INT_CST_HIGH (t) = high; + TREE_TYPE (t) = type; + TREE_CONSTANT_OVERFLOW (t) = 1; + + return t; + } + } + + /* Else build a shared node. */ + return build_int_cst_wide (type, low, high); + } + #if 0 /* 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 *************** force_fit_type (tree t, int overflowable *** 321,326 **** --- 386,392 ---- return t; } + #endif /* Add two doubleword integers with doubleword result. Return nonzero if the operation overflows according to UNSIGNED_P. *************** int_const_binop (enum tree_code code, tr *** 1601,1610 **** return NULL_TREE; } - t = build_int_cst_wide (TREE_TYPE (arg1), low, hi); - if (notrunc) { /* Propagate overflow flags ourselves. */ if (((!uns || is_sizetype) && overflow) | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)) --- 1667,1676 ---- return NULL_TREE; } if (notrunc) { + t = build_int_cst_wide (TREE_TYPE (arg1), low, hi); + /* Propagate overflow flags ourselves. */ if (((!uns || is_sizetype) && overflow) | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2)) *************** int_const_binop (enum tree_code code, tr *** 1620,1630 **** } } else ! t = force_fit_type (t, 1, ! ((!uns || is_sizetype) && overflow) ! | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2), ! TREE_CONSTANT_OVERFLOW (arg1) ! | TREE_CONSTANT_OVERFLOW (arg2)); return t; } --- 1686,1696 ---- } } else ! t = force_fit_type_double (TREE_TYPE (arg1), low, hi, 1, ! ((!uns || is_sizetype) && overflow) ! | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2), ! TREE_CONSTANT_OVERFLOW (arg1) ! | TREE_CONSTANT_OVERFLOW (arg2)); return t; } *************** fold_convert_const_int_from_int (tree ty *** 1896,1913 **** /* Given an integer constant, make new constant with new type, appropriately sign-extended or truncated. */ ! t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1), ! TREE_INT_CST_HIGH (arg1)); ! ! t = force_fit_type (t, ! /* Don't set the overflow when ! converting a pointer */ ! !POINTER_TYPE_P (TREE_TYPE (arg1)), ! (TREE_INT_CST_HIGH (arg1) < 0 ! && (TYPE_UNSIGNED (type) ! < TYPE_UNSIGNED (TREE_TYPE (arg1)))) ! | TREE_OVERFLOW (arg1), ! TREE_CONSTANT_OVERFLOW (arg1)); return t; } --- 1962,1977 ---- /* 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), ! /* Don't set the overflow when ! converting a pointer */ ! !POINTER_TYPE_P (TREE_TYPE (arg1)), ! (TREE_INT_CST_HIGH (arg1) < 0 ! && (TYPE_UNSIGNED (type) ! < TYPE_UNSIGNED (TREE_TYPE (arg1)))) ! | TREE_OVERFLOW (arg1), ! TREE_CONSTANT_OVERFLOW (arg1)); return t; } *************** fold_convert_const_int_from_real (enum t *** 1985,1994 **** if (! overflow) REAL_VALUE_TO_INT (&low, &high, r); ! t = build_int_cst_wide (type, low, high); ! ! t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1), ! TREE_CONSTANT_OVERFLOW (arg1)); return t; } --- 2049,2057 ---- if (! overflow) REAL_VALUE_TO_INT (&low, &high, r); ! t = force_fit_type_double (type, low, high, -1, ! overflow | TREE_OVERFLOW (arg1), ! TREE_CONSTANT_OVERFLOW (arg1)); return t; } *************** fold_div_compare (enum tree_code code, t *** 6172,6179 **** TREE_INT_CST_LOW (arg1), TREE_INT_CST_HIGH (arg1), &lpart, &hpart, unsigned_p); ! prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart); ! prod = force_fit_type (prod, -1, overflow, false); neg_overflow = false; if (unsigned_p) --- 6235,6242 ---- 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, false); neg_overflow = false; if (unsigned_p) *************** fold_div_compare (enum tree_code code, t *** 6188,6196 **** TREE_INT_CST_LOW (tmp), TREE_INT_CST_HIGH (tmp), &lpart, &hpart, unsigned_p); ! hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart); ! hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod), ! TREE_CONSTANT_OVERFLOW (prod)); } else if (tree_int_cst_sgn (arg01) >= 0) { --- 6251,6259 ---- TREE_INT_CST_LOW (tmp), TREE_INT_CST_HIGH (tmp), &lpart, &hpart, unsigned_p); ! hi = force_fit_type_double (TREE_TYPE (arg00), lpart, hpart, ! -1, overflow | TREE_OVERFLOW (prod), ! TREE_CONSTANT_OVERFLOW (prod)); } else if (tree_int_cst_sgn (arg01) >= 0) { *************** static tree *** 6589,6595 **** fold_sign_changed_comparison (enum tree_code code, tree type, tree arg0, tree arg1) { ! tree arg0_inner, tmp; tree inner_type, outer_type; if (TREE_CODE (arg0) != NOP_EXPR --- 6652,6658 ---- fold_sign_changed_comparison (enum tree_code code, tree type, tree arg0, tree arg1) { ! tree arg0_inner; tree inner_type, outer_type; if (TREE_CODE (arg0) != NOP_EXPR *************** fold_sign_changed_comparison (enum tree_ *** 6624,6637 **** return NULL_TREE; if (TREE_CODE (arg1) == INTEGER_CST) ! { ! tmp = build_int_cst_wide (inner_type, ! TREE_INT_CST_LOW (arg1), ! TREE_INT_CST_HIGH (arg1)); ! arg1 = force_fit_type (tmp, 0, ! TREE_OVERFLOW (arg1), ! TREE_CONSTANT_OVERFLOW (arg1)); ! } else arg1 = fold_convert (inner_type, arg1); --- 6687,6696 ---- 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), ! TREE_CONSTANT_OVERFLOW (arg1)); else arg1 = fold_convert (inner_type, arg1); *************** fold_unary (enum tree_code code, tree ty *** 7563,7572 **** } if (change) { ! tem = build_int_cst_wide (type, TREE_INT_CST_LOW (and1), ! TREE_INT_CST_HIGH (and1)); ! tem = force_fit_type (tem, 0, TREE_OVERFLOW (and1), ! TREE_CONSTANT_OVERFLOW (and1)); return fold_build2 (BIT_AND_EXPR, type, fold_convert (type, and0), tem); } --- 7622,7631 ---- } if (change) { ! tem = force_fit_type_double (type, TREE_INT_CST_LOW (and1), ! TREE_INT_CST_HIGH (and1), 0, ! TREE_OVERFLOW (and1), ! TREE_CONSTANT_OVERFLOW (and1)); return fold_build2 (BIT_AND_EXPR, type, fold_convert (type, and0), tem); } *************** fold_negate_const (tree arg0, tree type) *** 13056,13066 **** int overflow = neg_double (TREE_INT_CST_LOW (arg0), TREE_INT_CST_HIGH (arg0), &low, &high); ! t = build_int_cst_wide (type, low, high); ! t = force_fit_type (t, 1, ! (overflow | TREE_OVERFLOW (arg0)) ! && !TYPE_UNSIGNED (type), ! TREE_CONSTANT_OVERFLOW (arg0)); break; } --- 13115,13124 ---- 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)) ! && !TYPE_UNSIGNED (type), ! TREE_CONSTANT_OVERFLOW (arg0)); break; } *************** fold_abs_const (tree arg0, tree type) *** 13104,13112 **** int overflow = neg_double (TREE_INT_CST_LOW (arg0), TREE_INT_CST_HIGH (arg0), &low, &high); ! t = build_int_cst_wide (type, low, high); ! t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg0), ! TREE_CONSTANT_OVERFLOW (arg0)); } break; --- 13162,13170 ---- 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), ! TREE_CONSTANT_OVERFLOW (arg0)); } break; *************** fold_not_const (tree arg0, tree type) *** 13134,13144 **** gcc_assert (TREE_CODE (arg0) == INTEGER_CST); ! t = build_int_cst_wide (type, ! ~ TREE_INT_CST_LOW (arg0), ! ~ TREE_INT_CST_HIGH (arg0)); ! t = force_fit_type (t, 0, TREE_OVERFLOW (arg0), ! TREE_CONSTANT_OVERFLOW (arg0)); return t; } --- 13192,13201 ---- 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), ! TREE_CONSTANT_OVERFLOW (arg0)); return t; } Index: gcc/tree.h =================================================================== *** gcc.orig/tree.h 2007-01-08 20:49:25.000000000 +0100 --- gcc/tree.h 2007-01-08 20:50:03.000000000 +0100 *************** extern tree fold_ignored_result (tree); *** 4321,4327 **** extern tree fold_abs_const (tree, tree); 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); --- 4321,4328 ---- extern tree fold_abs_const (tree, tree); extern tree fold_indirect_ref_1 (tree, tree); ! extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT, ! int, bool, bool); extern int fit_double_type (unsigned HOST_WIDE_INT, HOST_WIDE_INT, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, tree);