From 32cef1cc3ac15ce6c31c7d28dc20c467c5ba915d Mon Sep 17 00:00:00 2001 From: sayle Date: Tue, 27 Dec 2005 23:27:34 +0000 Subject: [PATCH] * fold-const.c (int_const_binop): Return NULL_TREE when an expression can't be evaluated at compile-time (instead of calling abort). Return NULL_TREE for division (and modulus) by zero. (const_binop): Return NULL_TREE for floating point operators that aren't handled by real_arithmetic. (fold_binary): Eliminate "wins" variable, and "binary" label, by folding operators with constant operands early. Assert that operands are non-NULL. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109088 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 11 ++++ gcc/fold-const.c | 168 +++++++++++++++++++++++++------------------------------ 2 files changed, 88 insertions(+), 91 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ae1ffcb..2103a66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2005-12-27 Roger Sayle + + * fold-const.c (int_const_binop): Return NULL_TREE when an expression + can't be evaluated at compile-time (instead of calling abort). + Return NULL_TREE for division (and modulus) by zero. + (const_binop): Return NULL_TREE for floating point operators that + aren't handled by real_arithmetic. + (fold_binary): Eliminate "wins" variable, and "binary" label, by + folding operators with constant operands early. Assert that + operands are non-NULL. + 2005-12-27 Kazu Hirata * tree-vrp.c (extract_range_from_binary_expr): Use diff --git a/gcc/fold-const.c b/gcc/fold-const.c index eeb20ce..4006d89 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1345,7 +1345,8 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type) } /* Combine two integer constants ARG1 and ARG2 under operation CODE - to produce a new constant. + to produce a new constant. Return NULL_TREE if we don't know how + to evaluate CODE at compile-time. If NOTRUNC is nonzero, do not truncate the result to fit the data type. */ @@ -1434,6 +1435,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) /* ... fall through ... */ case ROUND_DIV_EXPR: + if (int2h == 0 && int2l == 0) + return NULL_TREE; if (int2h == 0 && int2l == 1) { low = int1l, hi = int1h; @@ -1466,6 +1469,8 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) /* ... fall through ... */ case ROUND_MOD_EXPR: + if (int2h == 0 && int2l == 0) + return NULL_TREE; overflow = div_and_round_double (code, uns, int1l, int1h, int2l, int2h, &garbagel, &garbageh, &low, &hi); @@ -1490,7 +1495,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) break; default: - gcc_unreachable (); + return NULL_TREE; } t = build_int_cst_wide (TREE_TYPE (arg1), low, hi); @@ -1546,6 +1551,21 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) bool inexact; tree t, type; + /* The following codes are handled by real_arithmetic. */ + switch (code) + { + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case RDIV_EXPR: + case MIN_EXPR: + case MAX_EXPR: + break; + + default: + return NULL_TREE; + } + d1 = TREE_REAL_CST (arg1); d2 = TREE_REAL_CST (arg2); @@ -1605,6 +1625,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) | TREE_CONSTANT_OVERFLOW (arg2); return t; } + if (TREE_CODE (arg1) == COMPLEX_CST) { tree type = TREE_TYPE (arg1); @@ -1680,11 +1701,11 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) break; default: - gcc_unreachable (); + return NULL_TREE; } return t; } - return 0; + return NULL_TREE; } /* Create a size type INT_CST node with NUMBER sign extended. KIND @@ -7171,80 +7192,57 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) tree arg0 = NULL_TREE, arg1 = NULL_TREE; enum tree_code_class kind = TREE_CODE_CLASS (code); - /* WINS will be nonzero when the switch is done - if all operands are constant. */ - int wins = 1; - gcc_assert (IS_EXPR_CODE_CLASS (kind) - && TREE_CODE_LENGTH (code) == 2); + && TREE_CODE_LENGTH (code) == 2 + && op0 != NULL_TREE + && op1 != NULL_TREE); arg0 = op0; arg1 = op1; - if (arg0) - { - tree subop; - - /* Strip any conversions that don't change the mode. This is - safe for every expression, except for a comparison expression - because its signedness is derived from its operands. So, in - the latter case, only strip conversions that don't change the - signedness. - - Note that this is done as an internal manipulation within the - constant folder, in order to find the simplest representation - of the arguments so that their form can be studied. In any - cases, the appropriate type conversions should be put back in - the tree that will get out of the constant folder. */ - if (kind == tcc_comparison) - STRIP_SIGN_NOPS (arg0); - else - STRIP_NOPS (arg0); + /* Strip any conversions that don't change the mode. This is + safe for every expression, except for a comparison expression + because its signedness is derived from its operands. So, in + the latter case, only strip conversions that don't change the + signedness. - if (TREE_CODE (arg0) == COMPLEX_CST) - subop = TREE_REALPART (arg0); - else - subop = arg0; + Note that this is done as an internal manipulation within the + constant folder, in order to find the simplest representation + of the arguments so that their form can be studied. In any + cases, the appropriate type conversions should be put back in + the tree that will get out of the constant folder. */ - if (TREE_CODE (subop) != INTEGER_CST - && TREE_CODE (subop) != REAL_CST) - /* Note that TREE_CONSTANT isn't enough: - static var addresses are constant but we can't - do arithmetic on them. */ - wins = 0; + if (kind == tcc_comparison) + { + STRIP_SIGN_NOPS (arg0); + STRIP_SIGN_NOPS (arg1); } - - if (arg1) + else { - tree subop; - - /* Strip any conversions that don't change the mode. This is - safe for every expression, except for a comparison expression - because its signedness is derived from its operands. So, in - the latter case, only strip conversions that don't change the - signedness. - - Note that this is done as an internal manipulation within the - constant folder, in order to find the simplest representation - of the arguments so that their form can be studied. In any - cases, the appropriate type conversions should be put back in - the tree that will get out of the constant folder. */ - if (kind == tcc_comparison) - STRIP_SIGN_NOPS (arg1); - else - STRIP_NOPS (arg1); + STRIP_NOPS (arg0); + STRIP_NOPS (arg1); + } - if (TREE_CODE (arg1) == COMPLEX_CST) - subop = TREE_REALPART (arg1); + /* Note that TREE_CONSTANT isn't enough: static var addresses are + constant but we can't do arithmetic on them. */ + if ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) + || (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST) + || (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST) + || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)) + { + if (kind == tcc_binary) + tem = const_binop (code, arg0, arg1, 0); + else if (kind == tcc_comparison) + tem = fold_relational_const (code, type, arg0, arg1); else - subop = arg1; + tem = NULL_TREE; - if (TREE_CODE (subop) != INTEGER_CST - && TREE_CODE (subop) != REAL_CST) - /* Note that TREE_CONSTANT isn't enough: - static var addresses are constant but we can't - do arithmetic on them. */ - wins = 0; + if (tem != NULL_TREE) + { + if (TREE_TYPE (tem) != type) + tem = fold_convert (type, tem); + return tem; + } } /* If this is a commutative operation, and ARG0 is a constant, move it @@ -7253,9 +7251,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && tree_swap_operands_p (arg0, arg1, true)) return fold_build2 (code, type, op1, op0); - /* Now WINS is set as described above, - ARG0 is the first operand of EXPR, - and ARG1 is the second operand (if it has more than one operand). + /* ARG0 is the first operand of EXPR, and ARG1 is the second operand. First check for cases where an arithmetic operation is applied to a compound, conditional, or comparison operation. Push the arithmetic @@ -7577,8 +7573,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) don't associate floats at all, unless the user has specified -funsafe-math-optimizations. */ - if (! wins - && (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations)) + if (! FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations) { tree var0, con0, lit0, minus_lit0; tree var1, con1, lit1, minus_lit1; @@ -7652,18 +7647,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) } } - binary: - if (wins) - t1 = const_binop (code, arg0, arg1, 0); - if (t1 != NULL_TREE) - { - /* The return value should always have - the same type as the original expression. */ - if (TREE_TYPE (t1) != type) - t1 = fold_convert (type, t1); - - return t1; - } return NULL_TREE; case MINUS_EXPR: @@ -7691,7 +7674,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) if (! FLOAT_TYPE_P (type)) { - if (! wins && integer_zerop (arg0)) + if (integer_zerop (arg0)) return negate_expr (fold_convert (type, arg1)); if (integer_zerop (arg1)) return non_lvalue (fold_convert (type, arg0)); @@ -7739,7 +7722,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0). So check whether ARG0 is zero and X + ARG0 reduces to X, since that would mean (-ARG1 + ARG0) reduces to -ARG1. */ - else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0)) + else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0)) return negate_expr (fold_convert (type, arg1)); /* Fold &x - &x. This can happen from &x.foo - &x. @@ -7753,7 +7736,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return fold_convert (type, integer_zero_node); /* A - B -> A + (-B) if B is easily negatable. */ - if (!wins && negate_expr_p (arg1) + if (negate_expr_p (arg1) && ((FLOAT_TYPE_P (type) /* Avoid this transformation if B is a positive REAL_CST. */ && (TREE_CODE (arg1) != REAL_CST @@ -8488,7 +8471,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return fold_build2 (MULT_EXPR, type, arg0, arg1); } } - goto binary; + return NULL_TREE; case TRUNC_DIV_EXPR: case ROUND_DIV_EXPR: @@ -8533,7 +8516,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE))) return fold_convert (type, tem); - goto binary; + return NULL_TREE; case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: @@ -8613,7 +8596,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE))) return fold_convert (type, tem); - goto binary; + return NULL_TREE; case LROTATE_EXPR: case RROTATE_EXPR: @@ -8727,7 +8710,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type)))) return TREE_OPERAND (arg0, 0); - goto binary; + return NULL_TREE; case MIN_EXPR: if (operand_equal_p (arg0, arg1, 0)) @@ -9998,7 +9981,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return pedantic_non_lvalue (tem); case COMPLEX_EXPR: - if (wins) + if ((TREE_CODE (arg0) == REAL_CST + && TREE_CODE (arg1) == REAL_CST) + || (TREE_CODE (arg0) == INTEGER_CST + && TREE_CODE (arg1) == INTEGER_CST)) return build_complex (type, arg0, arg1); return NULL_TREE; -- 2.7.4