}
\f
/* 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. */
/* ... fall through ... */
case ROUND_DIV_EXPR:
+ if (int2h == 0 && int2l == 0)
+ return NULL_TREE;
if (int2h == 0 && int2l == 1)
{
low = int1l, hi = int1h;
/* ... 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);
break;
default:
- gcc_unreachable ();
+ return NULL_TREE;
}
t = build_int_cst_wide (TREE_TYPE (arg1), low, hi);
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);
| TREE_CONSTANT_OVERFLOW (arg2);
return t;
}
+
if (TREE_CODE (arg1) == COMPLEX_CST)
{
tree type = TREE_TYPE (arg1);
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
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
&& 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
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;
}
}
- 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:
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));
/* (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.
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
return fold_build2 (MULT_EXPR, type, arg0, arg1);
}
}
- goto binary;
+ return NULL_TREE;
case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR:
&& 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:
&& 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:
== (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))
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;