aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2005-12-27 23:27:34 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2005-12-27 23:27:34 +0000
commitfd6c76f46242891b11b7abbacb3c735f0012a240 (patch)
tree3a566e041774c2831cfd87b087b4ca55259f0e53 /gcc/fold-const.c
parent5156c0c3a78803759bd723877af0ef2baafea938 (diff)
downloadgcc-fd6c76f46242891b11b7abbacb3c735f0012a240.zip
gcc-fd6c76f46242891b11b7abbacb3c735f0012a240.tar.gz
gcc-fd6c76f46242891b11b7abbacb3c735f0012a240.tar.bz2
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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c168
1 files changed, 77 insertions, 91 deletions
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;