fold-const.c (int_const_binop): Return NULL_TREE when an expression can't be evaluated at compile-time (instead...
* 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. From-SVN: r109088
This commit is contained in:
parent
5156c0c3a7
commit
fd6c76f462
@ -1,3 +1,14 @@
|
||||
2005-12-27 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* 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 <kazu@codesourcery.com>
|
||||
|
||||
* tree-vrp.c (extract_range_from_binary_expr): Use
|
||||
|
170
gcc/fold-const.c
170
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)
|
||||
/* 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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (TREE_CODE (arg0) == COMPLEX_CST)
|
||||
subop = TREE_REALPART (arg0);
|
||||
else
|
||||
subop = arg0;
|
||||
|
||||
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;
|
||||
STRIP_SIGN_NOPS (arg0);
|
||||
STRIP_SIGN_NOPS (arg1);
|
||||
}
|
||||
else
|
||||
{
|
||||
STRIP_NOPS (arg0);
|
||||
STRIP_NOPS (arg1);
|
||||
}
|
||||
|
||||
if (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))
|
||||
{
|
||||
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);
|
||||
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
|
||||
STRIP_NOPS (arg1);
|
||||
tem = NULL_TREE;
|
||||
|
||||
if (TREE_CODE (arg1) == COMPLEX_CST)
|
||||
subop = TREE_REALPART (arg1);
|
||||
else
|
||||
subop = arg1;
|
||||
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user