diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b7448c7e40b..f3ba578fd78 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-04-15 Roger Sayle + + * fold-const.c (fold_relational_hi_lo): Delete function and prototype. + (fold_binary): Update comment mentioning fold_relational_hi_lo. + (fold_binary_to_constant): Simplify using fold_binary. + (fold_unary_to_constant): Likewise, simplify using fold_unary. + 2005-04-15 Rainer Orth * gthr-posix.c (pthread_cancel): Define. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 9487d3c4970..e9b0e219e0a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -133,8 +133,6 @@ static bool reorder_operands_p (tree, tree); static tree fold_negate_const (tree, tree); static tree fold_not_const (tree, tree); static tree fold_relational_const (enum tree_code, tree, tree, tree); -static tree fold_relational_hi_lo (enum tree_code *, const tree, - tree *, tree *); static bool tree_expr_nonzero_p (tree); /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring @@ -9033,10 +9031,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } /* Comparisons with the highest or lowest possible integer of - the specified size will have known values. - - This is quite similar to fold_relational_hi_lo, however, - attempts to share the code have been nothing but trouble. */ + the specified size will have known values. */ { int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1))); @@ -10793,155 +10788,6 @@ tree_expr_nonzero_p (tree t) return false; } -/* See if we are applying CODE, a relational to the highest or lowest - possible integer of TYPE. If so, then the result is a compile - time constant. */ - -static tree -fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p, - tree *op1_p) -{ - tree op0 = *op0_p; - tree op1 = *op1_p; - enum tree_code code = *code_p; - int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (op1))); - - if (TREE_CODE (op1) == INTEGER_CST - && ! TREE_CONSTANT_OVERFLOW (op1) - && width <= HOST_BITS_PER_WIDE_INT - && (INTEGRAL_TYPE_P (TREE_TYPE (op1)) - || POINTER_TYPE_P (TREE_TYPE (op1)))) - { - unsigned HOST_WIDE_INT signed_max; - unsigned HOST_WIDE_INT max, min; - - signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; - - if (TYPE_UNSIGNED (TREE_TYPE (op1))) - { - max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; - min = 0; - } - else - { - max = signed_max; - min = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); - } - - if (TREE_INT_CST_HIGH (op1) == 0 - && TREE_INT_CST_LOW (op1) == max) - switch (code) - { - case GT_EXPR: - return omit_one_operand (type, integer_zero_node, op0); - - case GE_EXPR: - *code_p = EQ_EXPR; - break; - case LE_EXPR: - return omit_one_operand (type, integer_one_node, op0); - - case LT_EXPR: - *code_p = NE_EXPR; - break; - - /* The GE_EXPR and LT_EXPR cases above are not normally - reached because of previous transformations. */ - - default: - break; - } - else if (TREE_INT_CST_HIGH (op1) == 0 - && TREE_INT_CST_LOW (op1) == max - 1) - switch (code) - { - case GT_EXPR: - *code_p = EQ_EXPR; - *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0); - break; - case LE_EXPR: - *code_p = NE_EXPR; - *op1_p = const_binop (PLUS_EXPR, op1, integer_one_node, 0); - break; - default: - break; - } - else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0) - && TREE_INT_CST_LOW (op1) == min) - switch (code) - { - case LT_EXPR: - return omit_one_operand (type, integer_zero_node, op0); - - case LE_EXPR: - *code_p = EQ_EXPR; - break; - - case GE_EXPR: - return omit_one_operand (type, integer_one_node, op0); - - case GT_EXPR: - *code_p = NE_EXPR; - break; - - default: - break; - } - else if (TREE_INT_CST_HIGH (op1) == (min ? -1 : 0) - && TREE_INT_CST_LOW (op1) == min + 1) - switch (code) - { - case GE_EXPR: - *code_p = NE_EXPR; - *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0); - break; - case LT_EXPR: - *code_p = EQ_EXPR; - *op1_p = const_binop (MINUS_EXPR, op1, integer_one_node, 0); - break; - default: - break; - } - - else if (TREE_INT_CST_HIGH (op1) == 0 - && TREE_INT_CST_LOW (op1) == signed_max - && TYPE_UNSIGNED (TREE_TYPE (op1)) - /* signed_type does not work on pointer types. */ - && INTEGRAL_TYPE_P (TREE_TYPE (op1))) - { - /* The following case also applies to X < signed_max+1 - and X >= signed_max+1 because previous transformations. */ - if (code == LE_EXPR || code == GT_EXPR) - { - tree st0, st1, exp, retval; - st0 = lang_hooks.types.signed_type (TREE_TYPE (op0)); - st1 = lang_hooks.types.signed_type (TREE_TYPE (op1)); - - exp = build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR, - type, - fold_convert (st0, op0), - fold_convert (st1, integer_zero_node)); - - retval = fold_binary_to_constant (TREE_CODE (exp), - TREE_TYPE (exp), - TREE_OPERAND (exp, 0), - TREE_OPERAND (exp, 1)); - - /* If we are in gimple form, then returning EXP would create - non-gimple expressions. Clearing it is safe and insures - we do not allow a non-gimple expression to escape. */ - if (in_gimple_form) - exp = NULL; - - return (retval ? retval : exp); - } - } - } - - return NULL_TREE; -} - - /* Given the components of a binary expression CODE, TYPE, OP0 and OP1, attempt to fold the expression to a constant without modifying TYPE, OP0 or OP1. @@ -10958,282 +10804,8 @@ fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p, tree fold_binary_to_constant (enum tree_code code, tree type, tree op0, tree op1) { - int wins = 1; - tree subop0; - tree subop1; - tree tem; - - /* If this is a commutative operation, and ARG0 is a constant, move it - to ARG1 to reduce the number of tests below. */ - if (commutative_tree_code (code) - && (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST)) - { - tem = op0; - op0 = op1; - op1 = tem; - } - - /* If either operand is a complex type, extract its real component. */ - if (TREE_CODE (op0) == COMPLEX_CST) - subop0 = TREE_REALPART (op0); - else - subop0 = op0; - - if (TREE_CODE (op1) == COMPLEX_CST) - subop1 = TREE_REALPART (op1); - else - subop1 = op1; - - /* Note if either argument is not a real or integer constant. - With a few exceptions, simplification is limited to cases - where both arguments are constants. */ - if ((TREE_CODE (subop0) != INTEGER_CST - && TREE_CODE (subop0) != REAL_CST) - || (TREE_CODE (subop1) != INTEGER_CST - && TREE_CODE (subop1) != REAL_CST)) - wins = 0; - - switch (code) - { - case PLUS_EXPR: - /* (plus (address) (const_int)) is a constant. */ - if (TREE_CODE (op0) == PLUS_EXPR - && TREE_CODE (op1) == INTEGER_CST - && (TREE_CODE (TREE_OPERAND (op0, 0)) == ADDR_EXPR - || (TREE_CODE (TREE_OPERAND (op0, 0)) == NOP_EXPR - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (op0, 0), 0)) - == ADDR_EXPR))) - && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST) - { - return build2 (PLUS_EXPR, type, TREE_OPERAND (op0, 0), - const_binop (PLUS_EXPR, op1, - TREE_OPERAND (op0, 1), 0)); - } - case BIT_XOR_EXPR: - - binary: - if (!wins) - return NULL_TREE; - - /* Both arguments are constants. Simplify. */ - tem = const_binop (code, op0, op1, 0); - if (tem != NULL_TREE) - { - /* The return value should always have the same type as - the original expression. */ - if (TREE_TYPE (tem) != type) - tem = fold_convert (type, tem); - - return tem; - } - return NULL_TREE; - - case MINUS_EXPR: - /* Fold &x - &x. This can happen from &x.foo - &x. - This is unsafe for certain floats even in non-IEEE formats. - In IEEE, it is unsafe because it does wrong for NaNs. - Also note that operand_equal_p is always false if an - operand is volatile. */ - if (! FLOAT_TYPE_P (type) && operand_equal_p (op0, op1, 0)) - return fold_convert (type, integer_zero_node); - - goto binary; - - case MULT_EXPR: - case BIT_AND_EXPR: - /* Special case multiplication or bitwise AND where one argument - is zero. */ - if (! FLOAT_TYPE_P (type) && integer_zerop (op1)) - return omit_one_operand (type, op1, op0); - else - if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (op0))) - && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0))) - && real_zerop (op1)) - return omit_one_operand (type, op1, op0); - - goto binary; - - case BIT_IOR_EXPR: - /* Special case when we know the result will be all ones. */ - if (integer_all_onesp (op1)) - return omit_one_operand (type, op1, op0); - - goto binary; - - case TRUNC_DIV_EXPR: - case ROUND_DIV_EXPR: - case FLOOR_DIV_EXPR: - case CEIL_DIV_EXPR: - case EXACT_DIV_EXPR: - case TRUNC_MOD_EXPR: - case ROUND_MOD_EXPR: - case FLOOR_MOD_EXPR: - case CEIL_MOD_EXPR: - case RDIV_EXPR: - /* Division by zero is undefined. */ - if (integer_zerop (op1)) - return NULL_TREE; - - if (TREE_CODE (op1) == REAL_CST - && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (op1))) - && real_zerop (op1)) - return NULL_TREE; - - goto binary; - - case MIN_EXPR: - if (INTEGRAL_TYPE_P (type) - && operand_equal_p (op1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST)) - return omit_one_operand (type, op1, op0); - - goto binary; - - case MAX_EXPR: - if (INTEGRAL_TYPE_P (type) - && TYPE_MAX_VALUE (type) - && operand_equal_p (op1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST)) - return omit_one_operand (type, op1, op0); - - goto binary; - - case RSHIFT_EXPR: - /* Optimize -1 >> x for arithmetic right shifts. */ - if (integer_all_onesp (op0) && ! TYPE_UNSIGNED (type)) - return omit_one_operand (type, op0, op1); - /* ... fall through ... */ - - case LSHIFT_EXPR: - if (integer_zerop (op0)) - return omit_one_operand (type, op0, op1); - - /* Since negative shift count is not well-defined, don't - try to compute it in the compiler. */ - if (TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sgn (op1) < 0) - return NULL_TREE; - - goto binary; - - case LROTATE_EXPR: - case RROTATE_EXPR: - /* -1 rotated either direction by any amount is still -1. */ - if (integer_all_onesp (op0)) - return omit_one_operand (type, op0, op1); - - /* 0 rotated either direction by any amount is still zero. */ - if (integer_zerop (op0)) - return omit_one_operand (type, op0, op1); - - goto binary; - - case COMPLEX_EXPR: - if (wins) - return build_complex (type, op0, op1); - return NULL_TREE; - - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case EQ_EXPR: - case NE_EXPR: - /* If one arg is a real or integer constant, put it last. */ - if ((TREE_CODE (op0) == INTEGER_CST - && TREE_CODE (op1) != INTEGER_CST) - || (TREE_CODE (op0) == REAL_CST - && TREE_CODE (op0) != REAL_CST)) - { - tree temp; - - temp = op0; - op0 = op1; - op1 = temp; - code = swap_tree_comparison (code); - } - - /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0. - This transformation affects the cases which are handled in later - optimizations involving comparisons with non-negative constants. */ - if (TREE_CODE (op1) == INTEGER_CST - && TREE_CODE (op0) != INTEGER_CST - && tree_int_cst_sgn (op1) > 0) - { - switch (code) - { - case GE_EXPR: - code = GT_EXPR; - op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0); - break; - - case LT_EXPR: - code = LE_EXPR; - op1 = const_binop (MINUS_EXPR, op1, integer_one_node, 0); - break; - - default: - break; - } - } - - tem = fold_relational_hi_lo (&code, type, &op0, &op1); - if (tem) - return tem; - - /* Fall through. */ - - case ORDERED_EXPR: - case UNORDERED_EXPR: - case UNLT_EXPR: - case UNLE_EXPR: - case UNGT_EXPR: - case UNGE_EXPR: - case UNEQ_EXPR: - case LTGT_EXPR: - if (!wins) - return NULL_TREE; - - return fold_relational_const (code, type, op0, op1); - - case RANGE_EXPR: - /* This could probably be handled. */ - return NULL_TREE; - - case TRUTH_AND_EXPR: - /* If second arg is constant zero, result is zero, but first arg - must be evaluated. */ - if (integer_zerop (op1)) - return omit_one_operand (type, op1, op0); - /* Likewise for first arg, but note that only the TRUTH_AND_EXPR - case will be handled here. */ - if (integer_zerop (op0)) - return omit_one_operand (type, op0, op1); - if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) - return constant_boolean_node (true, type); - return NULL_TREE; - - case TRUTH_OR_EXPR: - /* If second arg is constant true, result is true, but we must - evaluate first arg. */ - if (TREE_CODE (op1) == INTEGER_CST && ! integer_zerop (op1)) - return omit_one_operand (type, op1, op0); - /* Likewise for first arg, but note this only occurs here for - TRUTH_OR_EXPR. */ - if (TREE_CODE (op0) == INTEGER_CST && ! integer_zerop (op0)) - return omit_one_operand (type, op0, op1); - if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) - return constant_boolean_node (false, type); - return NULL_TREE; - - case TRUTH_XOR_EXPR: - if (TREE_CODE (op0) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST) - { - int x = ! integer_zerop (op0) ^ ! integer_zerop (op1); - return constant_boolean_node (x, type); - } - return NULL_TREE; - - default: - return NULL_TREE; - } + tree tem = fold_binary (code, type, op0, op1); + return (tem && TREE_CONSTANT (tem)) ? tem : NULL_TREE; } /* Given the components of a unary expression CODE, TYPE and OP0, @@ -11252,71 +10824,8 @@ fold_binary_to_constant (enum tree_code code, tree type, tree op0, tree op1) tree fold_unary_to_constant (enum tree_code code, tree type, tree op0) { - /* Make sure we have a suitable constant argument. */ - if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR) - { - tree subop; - - if (TREE_CODE (op0) == COMPLEX_CST) - subop = TREE_REALPART (op0); - else - subop = op0; - - if (TREE_CODE (subop) != INTEGER_CST && TREE_CODE (subop) != REAL_CST) - return NULL_TREE; - } - - switch (code) - { - case NOP_EXPR: - case FLOAT_EXPR: - case CONVERT_EXPR: - case FIX_TRUNC_EXPR: - case FIX_FLOOR_EXPR: - case FIX_CEIL_EXPR: - case FIX_ROUND_EXPR: - return fold_convert_const (code, type, op0); - - case NEGATE_EXPR: - if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) - return fold_negate_const (op0, type); - else - return NULL_TREE; - - case ABS_EXPR: - if (TREE_CODE (op0) == INTEGER_CST || TREE_CODE (op0) == REAL_CST) - return fold_abs_const (op0, type); - else - return NULL_TREE; - - case BIT_NOT_EXPR: - if (TREE_CODE (op0) == INTEGER_CST) - return fold_not_const (op0, type); - else - return NULL_TREE; - - case REALPART_EXPR: - if (TREE_CODE (op0) == COMPLEX_CST) - return TREE_REALPART (op0); - else - return NULL_TREE; - - case IMAGPART_EXPR: - if (TREE_CODE (op0) == COMPLEX_CST) - return TREE_IMAGPART (op0); - else - return NULL_TREE; - - case CONJ_EXPR: - if (TREE_CODE (op0) == COMPLEX_CST - && TREE_CODE (TREE_TYPE (op0)) == COMPLEX_TYPE) - return build_complex (type, TREE_REALPART (op0), - negate_expr (TREE_IMAGPART (op0))); - return NULL_TREE; - - default: - return NULL_TREE; - } + tree tem = fold_unary (code, type, op0); + return (tem && TREE_CONSTANT (tem)) ? tem : NULL_TREE; } /* If EXP represents referencing an element in a constant string