/* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
static tree associate_trees (tree, tree, enum tree_code, tree);
static tree const_binop (enum tree_code, tree, tree, int);
-static tree build_zero_vector (tree);
-static tree fold_convert_const (enum tree_code, tree, tree);
static enum tree_code invert_tree_comparison (enum tree_code, bool);
static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code);
static tree extract_muldiv (tree, tree, enum tree_code, tree);
static tree extract_muldiv_1 (tree, tree, enum tree_code, tree);
static int multiple_of_p (tree, tree, tree);
-static tree fold_binary_op_with_conditional_arg (enum tree_code, tree, tree,
- tree, int);
+static tree fold_binary_op_with_conditional_arg (tree, enum tree_code,
+ tree, tree, int);
static bool fold_real_zero_addition_p (tree, tree, int);
static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
tree, tree, tree);
/* First clear all bits that are beyond the type's precision. */
- if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+ if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
;
else if (prec > HOST_BITS_PER_WIDE_INT)
high &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
if (!sign_extended_type)
/* No sign extension */;
- else if (prec == 2 * HOST_BITS_PER_WIDE_INT)
+ else if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
/* Correct width already. */;
else if (prec > HOST_BITS_PER_WIDE_INT)
{
REAL_VALUE_TYPE d1;
REAL_VALUE_TYPE d2;
REAL_VALUE_TYPE value;
+ REAL_VALUE_TYPE result;
+ bool inexact;
tree t, type;
d1 = TREE_REAL_CST (arg1);
else if (REAL_VALUE_ISNAN (d2))
return arg2;
- REAL_ARITHMETIC (value, code, d1, d2);
+ inexact = real_arithmetic (&value, code, &d1, &d2);
+ real_convert (&result, mode, &value);
+
+ /* Don't constant fold this floating point operation if the
+ result may dependent upon the run-time rounding mode and
+ flag_rounding_math is set, or if GCC's software emulation
+ is unable to accurately represent the result. */
+
+ if ((flag_rounding_math
+ || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
+ && !flag_unsafe_math_optimizations))
+ && (inexact || !real_identical (&result, &value)))
+ return NULL_TREE;
- t = build_real (type, real_value_truncate (mode, value));
+ t = build_real (type, result);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
TREE_CONSTANT_OVERFLOW (t)
arg1, arg0)));
}
\f
-/* Construct a vector of zero elements of vector type TYPE. */
+/* A subroutine of fold_convert_const handling conversions of an
+ INTEGER_CST to another integer type. */
static tree
-build_zero_vector (tree type)
+fold_convert_const_int_from_int (tree type, tree arg1)
{
- tree elem, list;
- int i, units;
+ tree t;
- elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
- units = TYPE_VECTOR_SUBPARTS (type);
+ /* Given an integer constant, make new constant with new type,
+ appropriately sign-extended or truncated. */
+ t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
+ TREE_INT_CST_HIGH (arg1));
+
+ t = force_fit_type (t,
+ /* Don't set the overflow when
+ converting a pointer */
+ !POINTER_TYPE_P (TREE_TYPE (arg1)),
+ (TREE_INT_CST_HIGH (arg1) < 0
+ && (TYPE_UNSIGNED (type)
+ < TYPE_UNSIGNED (TREE_TYPE (arg1))))
+ | TREE_OVERFLOW (arg1),
+ TREE_CONSTANT_OVERFLOW (arg1));
- list = NULL_TREE;
- for (i = 0; i < units; i++)
- list = tree_cons (NULL_TREE, elem, list);
- return build_vector (type, list);
+ return t;
}
-
-/* Attempt to fold type conversion operation CODE of expression ARG1 to
- type TYPE. If no simplification can be done return NULL_TREE. */
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+ to an integer type. */
static tree
-fold_convert_const (enum tree_code code, tree type, tree arg1)
+fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1)
{
int overflow = 0;
tree t;
- if (TREE_TYPE (arg1) == type)
- return arg1;
+ /* The following code implements the floating point to integer
+ conversion rules required by the Java Language Specification,
+ that IEEE NaNs are mapped to zero and values that overflow
+ the target precision saturate, i.e. values greater than
+ INT_MAX are mapped to INT_MAX, and values less than INT_MIN
+ are mapped to INT_MIN. These semantics are allowed by the
+ C and C++ standards that simply state that the behavior of
+ FP-to-integer conversion is unspecified upon overflow. */
- if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+ HOST_WIDE_INT high, low;
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+
+ switch (code)
{
- if (TREE_CODE (arg1) == INTEGER_CST)
- {
- /* If we would build a constant wider than GCC supports,
- leave the conversion unfolded. */
- if (TYPE_PRECISION (type) > 2 * HOST_BITS_PER_WIDE_INT)
- return NULL_TREE;
-
- /* Given an integer constant, make new constant with new type,
- appropriately sign-extended or truncated. */
- t = build_int_cst_wide (type, TREE_INT_CST_LOW (arg1),
- TREE_INT_CST_HIGH (arg1));
-
- t = force_fit_type (t,
- /* Don't set the overflow when
- converting a pointer */
- !POINTER_TYPE_P (TREE_TYPE (arg1)),
- (TREE_INT_CST_HIGH (arg1) < 0
- && (TYPE_UNSIGNED (type)
- < TYPE_UNSIGNED (TREE_TYPE (arg1))))
- | TREE_OVERFLOW (arg1),
- TREE_CONSTANT_OVERFLOW (arg1));
- return t;
- }
- else if (TREE_CODE (arg1) == REAL_CST)
- {
- /* The following code implements the floating point to integer
- conversion rules required by the Java Language Specification,
- that IEEE NaNs are mapped to zero and values that overflow
- the target precision saturate, i.e. values greater than
- INT_MAX are mapped to INT_MAX, and values less than INT_MIN
- are mapped to INT_MIN. These semantics are allowed by the
- C and C++ standards that simply state that the behavior of
- FP-to-integer conversion is unspecified upon overflow. */
+ case FIX_TRUNC_EXPR:
+ real_trunc (&r, VOIDmode, &x);
+ break;
+
+ case FIX_CEIL_EXPR:
+ real_ceil (&r, VOIDmode, &x);
+ break;
- HOST_WIDE_INT high, low;
- REAL_VALUE_TYPE r;
- REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
+ case FIX_FLOOR_EXPR:
+ real_floor (&r, VOIDmode, &x);
+ break;
- switch (code)
- {
- case FIX_TRUNC_EXPR:
- real_trunc (&r, VOIDmode, &x);
- break;
+ case FIX_ROUND_EXPR:
+ real_round (&r, VOIDmode, &x);
+ break;
- case FIX_CEIL_EXPR:
- real_ceil (&r, VOIDmode, &x);
- break;
+ default:
+ gcc_unreachable ();
+ }
- case FIX_FLOOR_EXPR:
- real_floor (&r, VOIDmode, &x);
- break;
+ /* If R is NaN, return zero and show we have an overflow. */
+ if (REAL_VALUE_ISNAN (r))
+ {
+ overflow = 1;
+ high = 0;
+ low = 0;
+ }
- case FIX_ROUND_EXPR:
- real_round (&r, VOIDmode, &x);
- break;
+ /* See if R is less than the lower bound or greater than the
+ upper bound. */
- default:
- gcc_unreachable ();
- }
+ if (! overflow)
+ {
+ tree lt = TYPE_MIN_VALUE (type);
+ REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
+ if (REAL_VALUES_LESS (r, l))
+ {
+ overflow = 1;
+ high = TREE_INT_CST_HIGH (lt);
+ low = TREE_INT_CST_LOW (lt);
+ }
+ }
- /* If R is NaN, return zero and show we have an overflow. */
- if (REAL_VALUE_ISNAN (r))
+ if (! overflow)
+ {
+ tree ut = TYPE_MAX_VALUE (type);
+ if (ut)
+ {
+ REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
+ if (REAL_VALUES_LESS (u, r))
{
overflow = 1;
- high = 0;
- low = 0;
+ high = TREE_INT_CST_HIGH (ut);
+ low = TREE_INT_CST_LOW (ut);
}
+ }
+ }
- /* See if R is less than the lower bound or greater than the
- upper bound. */
+ if (! overflow)
+ REAL_VALUE_TO_INT (&low, &high, r);
- if (! overflow)
- {
- tree lt = TYPE_MIN_VALUE (type);
- REAL_VALUE_TYPE l = real_value_from_int_cst (NULL_TREE, lt);
- if (REAL_VALUES_LESS (r, l))
- {
- overflow = 1;
- high = TREE_INT_CST_HIGH (lt);
- low = TREE_INT_CST_LOW (lt);
- }
- }
+ t = build_int_cst_wide (type, low, high);
- if (! overflow)
- {
- tree ut = TYPE_MAX_VALUE (type);
- if (ut)
- {
- REAL_VALUE_TYPE u = real_value_from_int_cst (NULL_TREE, ut);
- if (REAL_VALUES_LESS (u, r))
- {
- overflow = 1;
- high = TREE_INT_CST_HIGH (ut);
- low = TREE_INT_CST_LOW (ut);
- }
- }
- }
+ t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
+ TREE_CONSTANT_OVERFLOW (arg1));
+ return t;
+}
- if (! overflow)
- REAL_VALUE_TO_INT (&low, &high, r);
+/* A subroutine of fold_convert_const handling conversions a REAL_CST
+ to another floating point type. */
- t = build_int_cst_wide (type, low, high);
+static tree
+fold_convert_const_real_from_real (tree type, tree arg1)
+{
+ REAL_VALUE_TYPE value;
+ tree t;
- t = force_fit_type (t, -1, overflow | TREE_OVERFLOW (arg1),
- TREE_CONSTANT_OVERFLOW (arg1));
- return t;
- }
+ real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
+ t = build_real (type, value);
+
+ TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
+ return t;
+}
+
+/* Attempt to fold type conversion operation CODE of expression ARG1 to
+ type TYPE. If no simplification can be done return NULL_TREE. */
+
+static tree
+fold_convert_const (enum tree_code code, tree type, tree arg1)
+{
+ if (TREE_TYPE (arg1) == type)
+ return arg1;
+
+ if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
+ {
+ if (TREE_CODE (arg1) == INTEGER_CST)
+ return fold_convert_const_int_from_int (type, arg1);
+ else if (TREE_CODE (arg1) == REAL_CST)
+ return fold_convert_const_int_from_real (code, type, arg1);
}
else if (TREE_CODE (type) == REAL_TYPE)
{
if (TREE_CODE (arg1) == INTEGER_CST)
return build_real_from_int_cst (type, arg1);
if (TREE_CODE (arg1) == REAL_CST)
- {
- if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
- {
- /* We make a copy of ARG1 so that we don't modify an
- existing constant tree. */
- t = copy_node (arg1);
- TREE_TYPE (t) = type;
- return t;
- }
-
- t = build_real (type,
- real_value_truncate (TYPE_MODE (type),
- TREE_REAL_CST (arg1)));
-
- TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
- TREE_CONSTANT_OVERFLOW (t)
- = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
- return t;
- }
+ return fold_convert_const_real_from_real (type, arg1);
}
return NULL_TREE;
}
+/* Construct a vector of zero elements of vector type TYPE. */
+
+static tree
+build_zero_vector (tree type)
+{
+ tree elem, list;
+ int i, units;
+
+ elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+ units = TYPE_VECTOR_SUBPARTS (type);
+
+ list = NULL_TREE;
+ for (i = 0; i < units; i++)
+ list = tree_cons (NULL_TREE, elem, list);
+ return build_vector (type, list);
+}
+
/* Convert expression ARG to type TYPE. Used by the middle-end for
simple conversions in preference to calling the front-end's convert. */
if (flags & OEP_ONLY_CONST)
return 0;
-/* Define macros to test an operan from arg0 and arg1 for equality and a
+/* Define macros to test an operand from arg0 and arg1 for equality and a
variant that allows null and views null as being different from any
non-null value. In the latter case, if either is null, the both
must be; otherwise, do the normal comparison. */
switch (code)
{
case INTEGER_CST:
- return fold_convert (type,
- build_int_cst (NULL_TREE, integer_zerop (arg)));
+ return constant_boolean_node (integer_zerop (arg), type);
case TRUTH_AND_EXPR:
return build2 (TRUTH_OR_EXPR, type,
make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos,
int unsignedp)
{
- tree result = build3 (BIT_FIELD_REF, type, inner,
- size_int (bitsize), bitsize_int (bitpos));
+ tree result;
+
+ if (bitpos == 0)
+ {
+ tree size = TYPE_SIZE (TREE_TYPE (inner));
+ if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
+ || POINTER_TYPE_P (TREE_TYPE (inner)))
+ && host_integerp (size, 0)
+ && tree_low_cst (size, 0) == bitsize)
+ return fold_convert (type, inner);
+ }
+
+ result = build3 (BIT_FIELD_REF, type, inner,
+ size_int (bitsize), bitsize_int (bitpos));
BIT_FIELD_REF_UNSIGNED (result) = unsignedp;
do anything if the inner expression is a PLACEHOLDER_EXPR since we
then will no longer be able to replace it. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
- &lunsignedp, &lvolatilep);
+ &lunsignedp, &lvolatilep, false);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
return 0;
/* If this is not a constant, we can only do something if bit positions,
sizes, and signedness are the same. */
rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
- &runsignedp, &rvolatilep);
+ &runsignedp, &rvolatilep, false);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
|| lunsignedp != runsignedp || offset != 0
}
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
- punsignedp, pvolatilep);
+ punsignedp, pvolatilep, false);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
- if (first_rtl_op (code) > 0)
+ if (TREE_CODE_LENGTH (code) > 0)
arg0 = TREE_OPERAND (exp, 0);
if (TREE_CODE_CLASS (code) == tcc_comparison
|| TREE_CODE_CLASS (code) == tcc_unary
return value ? integer_one_node : integer_zero_node;
else if (type == boolean_type_node)
return value ? boolean_true_node : boolean_false_node;
- else if (TREE_CODE (type) == BOOLEAN_TYPE)
- return lang_hooks.truthvalue_conversion (value ? integer_one_node
- : integer_zero_node);
else
return build_int_cst (type, value);
}
+
+/* Return true if expr looks like an ARRAY_REF and set base and
+ offset to the appropriate trees. If there is no offset,
+ offset is set to NULL_TREE. */
+
+static bool
+extract_array_ref (tree expr, tree *base, tree *offset)
+{
+ /* We have to be careful with stripping nops as with the
+ base type the meaning of the offset can change. */
+ tree inner_expr = expr;
+ STRIP_NOPS (inner_expr);
+ /* One canonical form is a PLUS_EXPR with the first
+ argument being an ADDR_EXPR with a possible NOP_EXPR
+ attached. */
+ if (TREE_CODE (expr) == PLUS_EXPR)
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ STRIP_NOPS (op0);
+ if (TREE_CODE (op0) == ADDR_EXPR)
+ {
+ *base = TREE_OPERAND (expr, 0);
+ *offset = TREE_OPERAND (expr, 1);
+ return true;
+ }
+ }
+ /* Other canonical form is an ADDR_EXPR of an ARRAY_REF,
+ which we transform into an ADDR_EXPR with appropriate
+ offset. For other arguments to the ADDR_EXPR we assume
+ zero offset and as such do not care about the ADDR_EXPR
+ type and strip possible nops from it. */
+ else if (TREE_CODE (inner_expr) == ADDR_EXPR)
+ {
+ tree op0 = TREE_OPERAND (inner_expr, 0);
+ if (TREE_CODE (op0) == ARRAY_REF)
+ {
+ *base = build_fold_addr_expr (TREE_OPERAND (op0, 0));
+ *offset = TREE_OPERAND (op0, 1);
+ }
+ else
+ {
+ *base = inner_expr;
+ *offset = NULL_TREE;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+
/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
possible. */
static tree
-fold_binary_op_with_conditional_arg (enum tree_code code, tree type,
- tree cond, tree arg, int cond_first_p)
+fold_binary_op_with_conditional_arg (tree t, enum tree_code code, tree cond,
+ tree arg, int cond_first_p)
{
+ const tree type = TREE_TYPE (t);
+ tree cond_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 0))
+ : TREE_TYPE (TREE_OPERAND (t, 1));
+ tree arg_type = cond_first_p ? TREE_TYPE (TREE_OPERAND (t, 1))
+ : TREE_TYPE (TREE_OPERAND (t, 0));
tree test, true_value, false_value;
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
/* This transformation is only worthwhile if we don't have to wrap
- arg in a SAVE_EXPR, and the operation can be simplified on atleast
+ arg in a SAVE_EXPR, and the operation can be simplified on at least
one of the branches once its pushed inside the COND_EXPR. */
if (!TREE_CONSTANT (arg))
return NULL_TREE;
false_value = constant_boolean_node (false, testtype);
}
+ arg = fold_convert (arg_type, arg);
if (lhs == 0)
- lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
+ {
+ true_value = fold_convert (cond_type, true_value);
+ lhs = fold (cond_first_p ? build2 (code, type, true_value, arg)
: build2 (code, type, arg, true_value));
+ }
if (rhs == 0)
- rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
+ {
+ false_value = fold_convert (cond_type, false_value);
+ rhs = fold (cond_first_p ? build2 (code, type, false_value, arg)
: build2 (code, type, arg, false_value));
+ }
test = fold (build3 (COND_EXPR, type, test, lhs, rhs));
return fold_convert (type, test);
fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
tree result_type)
{
- /* If this is a TRUTH_NOT_EXPR, it may have a single bit test inside
- operand 0. */
- if (code == TRUTH_NOT_EXPR)
- {
- code = TREE_CODE (arg0);
- if (code != NE_EXPR && code != EQ_EXPR)
- return NULL_TREE;
-
- /* Extract the arguments of the EQ/NE. */
- arg1 = TREE_OPERAND (arg0, 1);
- arg0 = TREE_OPERAND (arg0, 0);
-
- /* This requires us to invert the code. */
- code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
- }
-
/* If this is testing a single bit, we can optimize the test. */
if ((code == NE_EXPR || code == EQ_EXPR)
&& TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
operations as unsigned. If we must use the AND, we have a choice.
Normally unsigned is faster, but for some machines signed is. */
#ifdef LOAD_EXTEND_OP
- ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
+ ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND
+ && !flag_syntax_only) ? 0 : 1;
#else
ops_unsigned = 1;
#endif
if (arg0_unw == arg0)
return NULL_TREE;
shorter_type = TREE_TYPE (arg0_unw);
-
+
+ if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
+ return NULL_TREE;
+
arg1_unw = get_unwidened (arg1, shorter_type);
if (!arg1_unw)
return NULL_TREE;
|| TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
&& (TREE_TYPE (arg1_unw) == shorter_type
|| (TREE_CODE (arg1_unw) == INTEGER_CST
+ && TREE_CODE (shorter_type) == INTEGER_TYPE
&& int_fits_type_p (arg1_unw, shorter_type))))
return fold (build (code, type, arg0_unw,
fold_convert (shorter_type, arg1_unw)));
{
case EQ_EXPR:
if (above || below)
- return constant_boolean_node (false, type);
+ return omit_one_operand (type, integer_zero_node, arg0);
break;
case NE_EXPR:
if (above || below)
- return constant_boolean_node (true, type);
+ return omit_one_operand (type, integer_one_node, arg0);
break;
case LT_EXPR:
case LE_EXPR:
if (above)
- return constant_boolean_node (true, type);
+ return omit_one_operand (type, integer_one_node, arg0);
else if (below)
- return constant_boolean_node (false, type);;
+ return omit_one_operand (type, integer_zero_node, arg0);
case GT_EXPR:
case GE_EXPR:
if (above)
- return constant_boolean_node (false, type);
+ return omit_one_operand (type, integer_zero_node, arg0);
else if (below)
- return constant_boolean_node (true, type);;
+ return omit_one_operand (type, integer_one_node, arg0);
default:
break;
}
/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
- step of the array. TYPE is the type of the expression. ADDR is the address.
- MULT is the multiplicative expression. If the function succeeds, the new
- address expression is returned. Otherwise NULL_TREE is returned. */
+ step of the array. ADDR is the address. MULT is the multiplicative expression.
+ If the function succeeds, the new address expression is returned. Otherwise
+ NULL_TREE is returned. */
static tree
-try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
+try_move_mult_to_index (enum tree_code code, tree addr, tree mult)
{
tree s, delta, step;
tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
/* If the type sizes do not match, we might run into problems
when one of them would overflow. */
- if (TYPE_PRECISION (itype) != TYPE_PRECISION (type))
+ if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
continue;
if (!operand_equal_p (step, fold_convert (itype, s), 0))
TREE_OPERAND (pos, 1),
delta));
- return build1 (ADDR_EXPR, type, ret);
+ return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
}
return fold (build2 (GE_EXPR, type, a, y));
}
-/* Perform constant folding and related simplification of EXPR.
- The related simplifications include x*1 => x, x*0 => 0, etc.,
- and application of the associative law.
- NOP_EXPR conversions may be removed freely (as long as we
- are careful not to change the type of the overall expression).
- We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
- but we can constant-fold them if they have constant operands. */
+/* Fold complex addition when both components are accessible by parts.
+ Return non-null if successful. CODE should be PLUS_EXPR for addition,
+ or MINUS_EXPR for subtraction. */
-#ifdef ENABLE_FOLD_CHECKING
-# define fold(x) fold_1 (x)
-static tree fold_1 (tree);
-static
-#endif
-tree
-fold (tree expr)
+static tree
+fold_complex_add (tree type, tree ac, tree bc, enum tree_code code)
{
- const tree t = expr;
- const tree type = TREE_TYPE (expr);
- tree t1 = NULL_TREE;
- tree tem;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE;
- enum tree_code code = TREE_CODE (t);
- enum tree_code_class kind = TREE_CODE_CLASS (code);
+ tree ar, ai, br, bi, rr, ri, inner_type;
- /* WINS will be nonzero when the switch is done
- if all operands are constant. */
- int wins = 1;
+ if (TREE_CODE (ac) == COMPLEX_EXPR)
+ ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+ else if (TREE_CODE (ac) == COMPLEX_CST)
+ ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+ else
+ return NULL;
- /* Return right away if a constant. */
- if (kind == tcc_constant)
- return t;
+ if (TREE_CODE (bc) == COMPLEX_EXPR)
+ br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+ else if (TREE_CODE (bc) == COMPLEX_CST)
+ br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+ else
+ return NULL;
- if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
- {
- tree subop;
+ inner_type = TREE_TYPE (type);
- /* Special case for conversion ops that can have fixed point args. */
- arg0 = TREE_OPERAND (t, 0);
+ rr = fold (build2 (code, inner_type, ar, br));
+ ri = fold (build2 (code, inner_type, ai, bi));
- /* Don't use STRIP_NOPS, because signedness of argument type matters. */
- if (arg0 != 0)
- STRIP_SIGN_NOPS (arg0);
+ return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
- if (arg0 != 0 && TREE_CODE (arg0) == COMPLEX_CST)
- subop = TREE_REALPART (arg0);
- else
- subop = arg0;
+/* Perform some simplifications of complex multiplication when one or more
+ of the components are constants or zeros. Return non-null if successful. */
- if (subop != 0 && 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;
- }
- else if (IS_EXPR_CODE_CLASS (kind))
- {
- int len = first_rtl_op (code);
- int i;
- for (i = 0; i < len; i++)
- {
- tree op = TREE_OPERAND (t, i);
- tree subop;
+tree
+fold_complex_mult_parts (tree type, tree ar, tree ai, tree br, tree bi)
+{
+ tree rr, ri, inner_type, zero;
+ bool ar0, ai0, br0, bi0, bi1;
- if (op == 0)
- continue; /* Valid for CALL_EXPR, at least. */
+ inner_type = TREE_TYPE (type);
+ zero = NULL;
- /* 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 (SCALAR_FLOAT_TYPE_P (inner_type))
+ {
+ ar0 = ai0 = br0 = bi0 = bi1 = false;
- 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 (op);
- else
- STRIP_NOPS (op);
+ /* We're only interested in +0.0 here, thus we don't use real_zerop. */
- if (TREE_CODE (op) == COMPLEX_CST)
- subop = TREE_REALPART (op);
- else
- subop = op;
+ if (TREE_CODE (ar) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+ ar0 = true, zero = ar;
- 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 (TREE_CODE (ai) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+ ai0 = true, zero = ai;
- if (i == 0)
- arg0 = op;
- else if (i == 1)
- arg1 = op;
+ if (TREE_CODE (br) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+ br0 = true, zero = br;
+
+ if (TREE_CODE (bi) == REAL_CST)
+ {
+ if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+ bi0 = true, zero = bi;
+ else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+ bi1 = true;
+ }
+ }
+ else
+ {
+ ar0 = integer_zerop (ar);
+ if (ar0)
+ zero = ar;
+ ai0 = integer_zerop (ai);
+ if (ai0)
+ zero = ai;
+ br0 = integer_zerop (br);
+ if (br0)
+ zero = br;
+ bi0 = integer_zerop (bi);
+ if (bi0)
+ {
+ zero = bi;
+ bi1 = false;
}
+ else
+ bi1 = integer_onep (bi);
}
- /* 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_swap_operands_p (arg0, arg1, true))
- return fold (build2 (code, type, TREE_OPERAND (t, 1),
- TREE_OPERAND (t, 0)));
+ /* We won't optimize anything below unless something is zero. */
+ if (zero == NULL)
+ return NULL;
- /* 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).
+ if (ai0 && br0 && bi1)
+ {
+ rr = zero;
+ ri = ar;
+ }
+ else if (ai0 && bi0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+ ri = zero;
+ }
+ else if (ai0 && br0)
+ {
+ rr = zero;
+ ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+ }
+ else if (ar0 && bi0)
+ {
+ rr = zero;
+ ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+ }
+ else if (ar0 && br0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+ rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+ ri = zero;
+ }
+ else if (bi0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+ ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+ }
+ else if (ai0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ar, br));
+ ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+ }
+ else if (br0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+ rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+ ri = fold (build2 (MULT_EXPR, inner_type, ar, bi));
+ }
+ else if (ar0)
+ {
+ rr = fold (build2 (MULT_EXPR, inner_type, ai, bi));
+ rr = fold (build1 (NEGATE_EXPR, inner_type, rr));
+ ri = fold (build2 (MULT_EXPR, inner_type, ai, br));
+ }
+ else
+ return NULL;
- First check for cases where an arithmetic operation is applied to a
- compound, conditional, or comparison operation. Push the arithmetic
- operation inside the compound or conditional to see if any folding
- can then be done. Convert comparison to conditional for this purpose.
- The also optimizes non-constant cases that used to be done in
- expand_expr.
+ return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
- Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
- one of the operands is a comparison and the other is a comparison, a
- BIT_AND_EXPR with the constant 1, or a truth value. In that case, the
- code below would make the expression more complex. Change it to a
- TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
- TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */
+static tree
+fold_complex_mult (tree type, tree ac, tree bc)
+{
+ tree ar, ai, br, bi;
- if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
- || code == EQ_EXPR || code == NE_EXPR)
- && ((truth_value_p (TREE_CODE (arg0))
- && (truth_value_p (TREE_CODE (arg1))
- || (TREE_CODE (arg1) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg1, 1)))))
- || (truth_value_p (TREE_CODE (arg1))
- && (truth_value_p (TREE_CODE (arg0))
- || (TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1)))))))
+ if (TREE_CODE (ac) == COMPLEX_EXPR)
+ ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+ else if (TREE_CODE (ac) == COMPLEX_CST)
+ ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+ else
+ return NULL;
+
+ if (TREE_CODE (bc) == COMPLEX_EXPR)
+ br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+ else if (TREE_CODE (bc) == COMPLEX_CST)
+ br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+ else
+ return NULL;
+
+ return fold_complex_mult_parts (type, ar, ai, br, bi);
+}
+
+/* Perform some simplifications of complex division when one or more of
+ the components are constants or zeros. Return non-null if successful. */
+
+tree
+fold_complex_div_parts (tree type, tree ar, tree ai, tree br, tree bi,
+ enum tree_code code)
+{
+ tree rr, ri, inner_type, zero;
+ bool ar0, ai0, br0, bi0, bi1;
+
+ inner_type = TREE_TYPE (type);
+ zero = NULL;
+
+ if (SCALAR_FLOAT_TYPE_P (inner_type))
{
- tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
- : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
- : TRUTH_XOR_EXPR,
- type, fold_convert (boolean_type_node, arg0),
- fold_convert (boolean_type_node, arg1)));
+ ar0 = ai0 = br0 = bi0 = bi1 = false;
- if (code == EQ_EXPR)
- tem = invert_truthvalue (tem);
+ /* We're only interested in +0.0 here, thus we don't use real_zerop. */
- return tem;
+ if (TREE_CODE (ar) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0))
+ ar0 = true, zero = ar;
+
+ if (TREE_CODE (ai) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0))
+ ai0 = true, zero = ai;
+
+ if (TREE_CODE (br) == REAL_CST
+ && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0))
+ br0 = true, zero = br;
+
+ if (TREE_CODE (bi) == REAL_CST)
+ {
+ if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0))
+ bi0 = true, zero = bi;
+ else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1))
+ bi1 = true;
+ }
+ }
+ else
+ {
+ ar0 = integer_zerop (ar);
+ if (ar0)
+ zero = ar;
+ ai0 = integer_zerop (ai);
+ if (ai0)
+ zero = ai;
+ br0 = integer_zerop (br);
+ if (br0)
+ zero = br;
+ bi0 = integer_zerop (bi);
+ if (bi0)
+ {
+ zero = bi;
+ bi1 = false;
+ }
+ else
+ bi1 = integer_onep (bi);
+ }
+
+ /* We won't optimize anything below unless something is zero. */
+ if (zero == NULL)
+ return NULL;
+
+ if (ai0 && bi0)
+ {
+ rr = fold (build2 (code, inner_type, ar, br));
+ ri = zero;
+ }
+ else if (ai0 && br0)
+ {
+ rr = zero;
+ ri = fold (build2 (code, inner_type, ar, bi));
+ ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+ }
+ else if (ar0 && bi0)
+ {
+ rr = zero;
+ ri = fold (build2 (code, inner_type, ai, br));
+ }
+ else if (ar0 && br0)
+ {
+ rr = fold (build2 (code, inner_type, ai, bi));
+ ri = zero;
+ }
+ else if (bi0)
+ {
+ rr = fold (build2 (code, inner_type, ar, br));
+ ri = fold (build2 (code, inner_type, ai, br));
+ }
+ else if (br0)
+ {
+ rr = fold (build2 (code, inner_type, ai, bi));
+ ri = fold (build2 (code, inner_type, ar, bi));
+ ri = fold (build1 (NEGATE_EXPR, inner_type, ri));
+ }
+ else
+ return NULL;
+
+ return fold (build2 (COMPLEX_EXPR, type, rr, ri));
+}
+
+static tree
+fold_complex_div (tree type, tree ac, tree bc, enum tree_code code)
+{
+ tree ar, ai, br, bi;
+
+ if (TREE_CODE (ac) == COMPLEX_EXPR)
+ ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1);
+ else if (TREE_CODE (ac) == COMPLEX_CST)
+ ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac);
+ else
+ return NULL;
+
+ if (TREE_CODE (bc) == COMPLEX_EXPR)
+ br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1);
+ else if (TREE_CODE (bc) == COMPLEX_CST)
+ br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc);
+ else
+ return NULL;
+
+ return fold_complex_div_parts (type, ar, ai, br, bi, code);
+}
+
+/* Fold a unary expression EXPR. Return the folded expression if
+ folding is successful. Otherwise, return the original
+ expression. */
+
+static tree
+fold_unary (tree expr)
+{
+ const tree t = expr;
+ const tree type = TREE_TYPE (expr);
+ tree tem;
+ tree op0, arg0;
+ enum tree_code code = TREE_CODE (t);
+ enum tree_code_class kind = TREE_CODE_CLASS (code);
+
+ gcc_assert (IS_EXPR_CODE_CLASS (kind)
+ && TREE_CODE_LENGTH (code) == 1);
+
+
+ arg0 = op0 = TREE_OPERAND (t, 0);
+ if (arg0)
+ {
+ if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
+ {
+ /* Don't use STRIP_NOPS, because signedness of argument type matters. */
+ STRIP_SIGN_NOPS (arg0);
+ }
+ else
+ {
+ /* 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.
+
+ 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. */
+ STRIP_NOPS (arg0);
+ }
}
if (TREE_CODE_CLASS (code) == tcc_unary)
&& ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
&& (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
== TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
- && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
- && (INTEGRAL_TYPE_P
- (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
- && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD))
+ && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
+ && (INTEGRAL_TYPE_P
+ (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
+ && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
+ || flag_syntax_only))
tem = build1 (code, type,
build3 (COND_EXPR,
TREE_TYPE (TREE_OPERAND
integer_zero_node))));
}
}
- else if (TREE_CODE_CLASS (code) == tcc_comparison
- && TREE_CODE (arg0) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
- else if (TREE_CODE_CLASS (code) == tcc_comparison
- && TREE_CODE (arg1) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
- else if (TREE_CODE_CLASS (code) == tcc_binary
- || TREE_CODE_CLASS (code) == tcc_comparison)
- {
- if (TREE_CODE (arg0) == COMPOUND_EXPR)
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build2 (code, type, TREE_OPERAND (arg0, 1),
- arg1)));
- if (TREE_CODE (arg1) == COMPOUND_EXPR
- && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
- return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build2 (code, type,
- arg0, TREE_OPERAND (arg1, 1))));
-
- if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
- {
- tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
- /*cond_first_p=*/1);
- if (tem != NULL_TREE)
- return tem;
- }
-
- if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
- {
- tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
- /*cond_first_p=*/0);
- if (tem != NULL_TREE)
- return tem;
- }
- }
switch (code)
{
- case CONST_DECL:
- return fold (DECL_INITIAL (t));
-
case NOP_EXPR:
case FLOAT_EXPR:
case CONVERT_EXPR:
case FIX_CEIL_EXPR:
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
- if (TREE_TYPE (TREE_OPERAND (t, 0)) == type)
- return TREE_OPERAND (t, 0);
+ if (TREE_TYPE (op0) == type)
+ return op0;
/* Handle cases of two conversions in a row. */
- if (TREE_CODE (TREE_OPERAND (t, 0)) == NOP_EXPR
- || TREE_CODE (TREE_OPERAND (t, 0)) == CONVERT_EXPR)
+ if (TREE_CODE (op0) == NOP_EXPR
+ || TREE_CODE (op0) == CONVERT_EXPR)
{
- tree inside_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
- tree inter_type = TREE_TYPE (TREE_OPERAND (t, 0));
+ tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0));
+ tree inter_type = TREE_TYPE (op0);
int inside_int = INTEGRAL_TYPE_P (inside_type);
int inside_ptr = POINTER_TYPE_P (inside_type);
int inside_float = FLOAT_TYPE_P (inside_type);
if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
&& ((inter_int && final_int) || (inter_float && final_float))
&& inter_prec >= final_prec)
- return fold (build1 (code, type,
- TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+ return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
/* Likewise, if the intermediate and final types are either both
float or both integer, we don't need the middle conversion if
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
&& ! final_ptr)
- return fold (build1 (code, type,
- TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+ return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
/* If we have a sign-extension of a zero-extended value, we can
replace that by a single zero-extension. */
if (inside_int && inter_int && final_int
&& inside_prec < inter_prec && inter_prec < final_prec
&& inside_unsignedp && !inter_unsignedp)
- return fold (build1 (code, type,
- TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+ return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
/* Two conversions in a row are not needed unless:
- some conversion is floating-point (overstrict for now), or
&& ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
&& TYPE_MODE (type) == TYPE_MODE (inter_type))
&& ! final_ptr)
- return fold (build1 (code, type,
- TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+ return fold (build1 (code, type, TREE_OPERAND (op0, 0)));
}
- if (TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
- && TREE_CONSTANT (TREE_OPERAND (TREE_OPERAND (t, 0), 1))
+ if (TREE_CODE (op0) == MODIFY_EXPR
+ && TREE_CONSTANT (TREE_OPERAND (op0, 1))
/* Detect assigning a bitfield. */
- && !(TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 1))))
+ && !(TREE_CODE (TREE_OPERAND (op0, 0)) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (op0, 0), 1))))
{
/* Don't leave an assignment inside a conversion
unless assigning a bitfield. */
- tree prev = TREE_OPERAND (t, 0);
tem = copy_node (t);
- TREE_OPERAND (tem, 0) = TREE_OPERAND (prev, 1);
+ TREE_OPERAND (tem, 0) = TREE_OPERAND (op0, 1);
/* First do the assignment, then return converted constant. */
- tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), prev, fold (tem));
+ tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), op0, fold (tem));
TREE_NO_WARNING (tem) = 1;
TREE_USED (tem) = 1;
return tem;
in c). This folds extension into the BIT_AND_EXPR. */
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (type) != BOOLEAN_TYPE
- && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+ && TREE_CODE (op0) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
{
- tree and = TREE_OPERAND (t, 0);
+ tree and = op0;
tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
int change = 0;
change = (cst == 0);
#ifdef LOAD_EXTEND_OP
if (change
+ && !flag_syntax_only
&& (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
== ZERO_EXTEND))
{
#endif
}
if (change)
- return fold (build2 (BIT_AND_EXPR, type,
- fold_convert (type, and0),
- fold_convert (type, and1)));
+ {
+ tem = build_int_cst_wide (type, TREE_INT_CST_LOW (and1),
+ TREE_INT_CST_HIGH (and1));
+ tem = force_fit_type (tem, 0, TREE_OVERFLOW (and1),
+ TREE_CONSTANT_OVERFLOW (and1));
+ return fold (build2 (BIT_AND_EXPR, type,
+ fold_convert (type, and0), tem));
+ }
}
/* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
T2 being pointers to types of the same size. */
- if (POINTER_TYPE_P (TREE_TYPE (t))
+ if (POINTER_TYPE_P (type)
&& BINARY_CLASS_P (arg0)
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
tree arg00 = TREE_OPERAND (arg0, 0);
- tree t0 = TREE_TYPE (t);
+ tree t0 = type;
tree t1 = TREE_TYPE (arg00);
tree tt0 = TREE_TYPE (t0);
tree tt1 = TREE_TYPE (t1);
return tem ? tem : t;
case VIEW_CONVERT_EXPR:
- if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
- return build1 (VIEW_CONVERT_EXPR, type,
- TREE_OPERAND (TREE_OPERAND (t, 0), 0));
- return t;
-
- case COMPONENT_REF:
- if (TREE_CODE (arg0) == CONSTRUCTOR
- && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
- {
- tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
- if (m)
- return TREE_VALUE (m);
- }
- return t;
-
- case RANGE_EXPR:
- if (TREE_CONSTANT (t) != wins)
- {
- tem = copy_node (t);
- TREE_CONSTANT (tem) = wins;
- TREE_INVARIANT (tem) = wins;
- return tem;
- }
+ if (TREE_CODE (op0) == VIEW_CONVERT_EXPR)
+ return build1 (VIEW_CONVERT_EXPR, type, TREE_OPERAND (op0, 0));
return t;
case NEGATE_EXPR:
if (negate_expr_p (arg0))
return fold_convert (type, negate_expr (arg0));
+ /* Convert - (~A) to A + 1. */
+ if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == BIT_NOT_EXPR)
+ return fold (build2 (PLUS_EXPR, type, TREE_OPERAND (arg0, 0),
+ build_int_cst (type, 1)));
return t;
case ABS_EXPR:
}
else if (tree_expr_nonnegative_p (arg0))
return arg0;
+
+ /* Strip sign ops from argument. */
+ if (TREE_CODE (type) == REAL_TYPE)
+ {
+ tem = fold_strip_sign_ops (arg0);
+ if (tem)
+ return fold (build1 (ABS_EXPR, type, fold_convert (type, tem)));
+ }
return t;
case CONJ_EXPR:
return TREE_OPERAND (arg0, 0);
return t;
- case BIT_NOT_EXPR:
- if (TREE_CODE (arg0) == INTEGER_CST)
- return fold_not_const (arg0, type);
- else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
- return TREE_OPERAND (arg0, 0);
+ case BIT_NOT_EXPR:
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ return fold_not_const (arg0, type);
+ else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
+ return TREE_OPERAND (arg0, 0);
+ /* Convert ~ (-A) to A - 1. */
+ else if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == NEGATE_EXPR)
+ return fold (build2 (MINUS_EXPR, type, TREE_OPERAND (arg0, 0),
+ build_int_cst (type, 1)));
+ /* Convert ~ (A - 1) or ~ (A + -1) to -A. */
+ else if (INTEGRAL_TYPE_P (type)
+ && ((TREE_CODE (arg0) == MINUS_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1)))
+ || (TREE_CODE (arg0) == PLUS_EXPR
+ && integer_all_onesp (TREE_OPERAND (arg0, 1)))))
+ return fold (build1 (NEGATE_EXPR, type, TREE_OPERAND (arg0, 0)));
+ return t;
+
+ case TRUTH_NOT_EXPR:
+ /* The argument to invert_truthvalue must have Boolean type. */
+ if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
+ arg0 = fold_convert (boolean_type_node, arg0);
+
+ /* Note that the operand of this must be an int
+ and its values must be 0 or 1.
+ ("true" is a fixed value perhaps depending on the language,
+ but we don't handle values other than 1 correctly yet.) */
+ tem = invert_truthvalue (arg0);
+ /* Avoid infinite recursion. */
+ if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
+ return t;
+ return fold_convert (type, tem);
+
+ case REALPART_EXPR:
+ if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+ return t;
+ else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+ return omit_one_operand (type, TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ else if (TREE_CODE (arg0) == COMPLEX_CST)
+ return TREE_REALPART (arg0);
+ else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build1 (REALPART_EXPR, type,
+ TREE_OPERAND (arg0, 0))),
+ fold (build1 (REALPART_EXPR, type,
+ TREE_OPERAND (arg0, 1)))));
+ return t;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
+ return fold_convert (type, integer_zero_node);
+ else if (TREE_CODE (arg0) == COMPLEX_EXPR)
+ return omit_one_operand (type, TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg0, 0));
+ else if (TREE_CODE (arg0) == COMPLEX_CST)
+ return TREE_IMAGPART (arg0);
+ else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ return fold (build2 (TREE_CODE (arg0), type,
+ fold (build1 (IMAGPART_EXPR, type,
+ TREE_OPERAND (arg0, 0))),
+ fold (build1 (IMAGPART_EXPR, type,
+ TREE_OPERAND (arg0, 1)))));
+ return t;
+
+ default:
+ return t;
+ } /* switch (code) */
+}
+
+/* Fold a ternary expression EXPR. Return the folded expression if
+ folding is successful. Otherwise, return the original
+ expression. */
+
+static tree
+fold_ternary (tree expr)
+{
+ const tree t = expr;
+ const tree type = TREE_TYPE (expr);
+ tree tem;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (t);
+ enum tree_code_class kind = TREE_CODE_CLASS (code);
+ int i;
+
+ gcc_assert (IS_EXPR_CODE_CLASS (kind)
+ && TREE_CODE_LENGTH (code) == 3);
+
+ /* For now, we iterate only twice even though we are handling
+ ternary expressions. This is because we haven't defined arg2
+ yet. */
+ for (i = 0; i < 2; i++)
+ {
+ tree op = TREE_OPERAND (t, i);
+
+ if (op == 0)
+ continue; /* Valid for CALL_EXPR, at least. */
+
+ /* 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. */
+ STRIP_NOPS (op);
+
+ if (i == 0)
+ arg0 = op;
+ else if (i == 1)
+ arg1 = op;
+ }
+
+ switch (code)
+ {
+ case COMPONENT_REF:
+ if (TREE_CODE (arg0) == CONSTRUCTOR
+ && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
+ {
+ tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
+ if (m)
+ return TREE_VALUE (m);
+ }
+ return t;
+
+ case COND_EXPR:
+ /* Pedantic ANSI C says that a conditional expression is never an lvalue,
+ so all simple results must be passed through pedantic_non_lvalue. */
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ {
+ tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
+ /* Only optimize constant conditions when the selected branch
+ has the same type as the COND_EXPR. This avoids optimizing
+ away "c ? x : throw", where the throw has a void type. */
+ if (! VOID_TYPE_P (TREE_TYPE (tem))
+ || VOID_TYPE_P (type))
+ return pedantic_non_lvalue (tem);
+ return t;
+ }
+ if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
+ return pedantic_omit_one_operand (type, arg1, arg0);
+
+ /* If we have A op B ? A : C, we may be able to convert this to a
+ simpler expression, depending on the operation and the values
+ of B and C. Signed zeros prevent all of these transformations,
+ for reasons given above each one.
+
+ Also try swapping the arguments and inverting the conditional. */
+ if (COMPARISON_CLASS_P (arg0)
+ && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+ arg1, TREE_OPERAND (arg0, 1))
+ && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
+ {
+ tem = fold_cond_expr_with_comparison (type, arg0,
+ TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 2));
+ if (tem)
+ return tem;
+ }
+
+ if (COMPARISON_CLASS_P (arg0)
+ && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (t, 2),
+ TREE_OPERAND (arg0, 1))
+ && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
+ {
+ tem = invert_truthvalue (arg0);
+ if (COMPARISON_CLASS_P (tem))
+ {
+ tem = fold_cond_expr_with_comparison (type, tem,
+ TREE_OPERAND (t, 2),
+ TREE_OPERAND (t, 1));
+ if (tem)
+ return tem;
+ }
+ }
+
+ /* If the second operand is simpler than the third, swap them
+ since that produces better jump optimization results. */
+ if (tree_swap_operands_p (TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 2), false))
+ {
+ /* See if this can be inverted. If it can't, possibly because
+ it was a floating-point inequality comparison, don't do
+ anything. */
+ tem = invert_truthvalue (arg0);
+
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return fold (build3 (code, type, tem,
+ TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+ }
+
+ /* Convert A ? 1 : 0 to simply A. */
+ if (integer_onep (TREE_OPERAND (t, 1))
+ && integer_zerop (TREE_OPERAND (t, 2))
+ /* If we try to convert TREE_OPERAND (t, 0) to our type, the
+ call to fold will try to move the conversion inside
+ a COND, which will recurse. In that case, the COND_EXPR
+ is probably the best choice, so leave it alone. */
+ && type == TREE_TYPE (arg0))
+ return pedantic_non_lvalue (arg0);
+
+ /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
+ over COND_EXPR in cases such as floating point comparisons. */
+ if (integer_zerop (TREE_OPERAND (t, 1))
+ && integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0)))
+ return pedantic_non_lvalue (fold_convert (type,
+ invert_truthvalue (arg0)));
+
+ /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
+ if (TREE_CODE (arg0) == LT_EXPR
+ && integer_zerop (TREE_OPERAND (arg0, 1))
+ && integer_zerop (TREE_OPERAND (t, 2))
+ && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
+ return fold_convert (type, fold (build2 (BIT_AND_EXPR,
+ TREE_TYPE (tem), tem, arg1)));
+
+ /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N). A & 1 was
+ already handled above. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1))
+ && integer_zerop (TREE_OPERAND (t, 2))
+ && integer_pow2p (arg1))
+ {
+ tree tem = TREE_OPERAND (arg0, 0);
+ STRIP_NOPS (tem);
+ if (TREE_CODE (tem) == RSHIFT_EXPR
+ && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
+ && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
+ TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
+ return fold (build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (tem, 0), arg1));
+ }
+
+ /* A & N ? N : 0 is simply A & N if N is a power of two. This
+ is probably obsolete because the first operand should be a
+ truth value (that's why we have the two cases above), but let's
+ leave it in until we can confirm this for all front-ends. */
+ if (integer_zerop (TREE_OPERAND (t, 2))
+ && TREE_CODE (arg0) == NE_EXPR
+ && integer_zerop (TREE_OPERAND (arg0, 1))
+ && integer_pow2p (arg1)
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+ arg1, OEP_ONLY_CONST))
+ return pedantic_non_lvalue (fold_convert (type,
+ TREE_OPERAND (arg0, 0)));
+
+ /* Convert A ? B : 0 into A && B if A and B are truth values. */
+ if (integer_zerop (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
+
+ /* Convert A ? B : 1 into !A || B if A and B are truth values. */
+ if (integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ {
+ /* Only perform transformation if ARG0 is easily inverted. */
+ tem = invert_truthvalue (arg0);
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
+ }
+
+ /* Convert A ? 0 : B into !A && B if A and B are truth values. */
+ if (integer_zerop (arg1)
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ {
+ /* Only perform transformation if ARG0 is easily inverted. */
+ tem = invert_truthvalue (arg0);
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
+ TREE_OPERAND (t, 2)));
+ }
+
+ /* Convert A ? 1 : B into A || B if A and B are truth values. */
+ if (integer_onep (arg1)
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
+ TREE_OPERAND (t, 2)));
+
+ return t;
+
+ case CALL_EXPR:
+ /* Check for a built-in function. */
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
+ == FUNCTION_DECL)
+ && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
+ {
+ tree tmp = fold_builtin (t, false);
+ if (tmp)
+ return tmp;
+ }
+ return t;
+
+ default:
+ return t;
+ } /* switch (code) */
+}
+
+/* Perform constant folding and related simplification of EXPR.
+ The related simplifications include x*1 => x, x*0 => 0, etc.,
+ and application of the associative law.
+ NOP_EXPR conversions may be removed freely (as long as we
+ are careful not to change the type of the overall expression).
+ We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
+ but we can constant-fold them if they have constant operands. */
+
+#ifdef ENABLE_FOLD_CHECKING
+# define fold(x) fold_1 (x)
+static tree fold_1 (tree);
+static
+#endif
+tree
+fold (tree expr)
+{
+ const tree t = expr;
+ const tree type = TREE_TYPE (expr);
+ tree t1 = NULL_TREE;
+ tree tem;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ enum tree_code code = TREE_CODE (t);
+ 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;
+
+ /* Return right away if a constant. */
+ if (kind == tcc_constant)
+ return t;
+
+ if (IS_EXPR_CODE_CLASS (kind))
+ {
+ switch (TREE_CODE_LENGTH (code))
+ {
+ case 1:
+ return fold_unary (expr);
+ case 3:
+ return fold_ternary (expr);
+ default:
+ break;
+ }
+ }
+
+ if (IS_EXPR_CODE_CLASS (kind))
+ {
+ int len = TREE_CODE_LENGTH (code);
+ int i;
+ for (i = 0; i < len; i++)
+ {
+ tree op = TREE_OPERAND (t, i);
+ tree subop;
+
+ if (op == 0)
+ continue; /* Valid for CALL_EXPR, at least. */
+
+ /* 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 (op);
+ else
+ STRIP_NOPS (op);
+
+ if (TREE_CODE (op) == COMPLEX_CST)
+ subop = TREE_REALPART (op);
+ else
+ subop = op;
+
+ 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 (i == 0)
+ arg0 = op;
+ else if (i == 1)
+ arg1 = op;
+ }
+ }
+
+ /* 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_swap_operands_p (arg0, arg1, true))
+ return fold (build2 (code, type, TREE_OPERAND (t, 1),
+ TREE_OPERAND (t, 0)));
+
+ /* 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).
+
+ First check for cases where an arithmetic operation is applied to a
+ compound, conditional, or comparison operation. Push the arithmetic
+ operation inside the compound or conditional to see if any folding
+ can then be done. Convert comparison to conditional for this purpose.
+ The also optimizes non-constant cases that used to be done in
+ expand_expr.
+
+ Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
+ one of the operands is a comparison and the other is a comparison, a
+ BIT_AND_EXPR with the constant 1, or a truth value. In that case, the
+ code below would make the expression more complex. Change it to a
+ TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
+ TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */
+
+ if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
+ || code == EQ_EXPR || code == NE_EXPR)
+ && ((truth_value_p (TREE_CODE (arg0))
+ && (truth_value_p (TREE_CODE (arg1))
+ || (TREE_CODE (arg1) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg1, 1)))))
+ || (truth_value_p (TREE_CODE (arg1))
+ && (truth_value_p (TREE_CODE (arg0))
+ || (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1)))))))
+ {
+ tem = fold (build2 (code == BIT_AND_EXPR ? TRUTH_AND_EXPR
+ : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+ : TRUTH_XOR_EXPR,
+ type, fold_convert (boolean_type_node, arg0),
+ fold_convert (boolean_type_node, arg1)));
+
+ if (code == EQ_EXPR)
+ tem = invert_truthvalue (tem);
+
+ return tem;
+ }
+
+ if (TREE_CODE_CLASS (code) == tcc_comparison
+ && TREE_CODE (arg0) == COMPOUND_EXPR)
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build2 (code, type, TREE_OPERAND (arg0, 1), arg1)));
+ else if (TREE_CODE_CLASS (code) == tcc_comparison
+ && TREE_CODE (arg1) == COMPOUND_EXPR)
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ fold (build2 (code, type, arg0, TREE_OPERAND (arg1, 1))));
+ else if (TREE_CODE_CLASS (code) == tcc_binary
+ || TREE_CODE_CLASS (code) == tcc_comparison)
+ {
+ if (TREE_CODE (arg0) == COMPOUND_EXPR)
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
+ fold (build2 (code, type, TREE_OPERAND (arg0, 1),
+ arg1)));
+ if (TREE_CODE (arg1) == COMPOUND_EXPR
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+ return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
+ fold (build2 (code, type,
+ arg0, TREE_OPERAND (arg1, 1))));
+
+ if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
+ {
+ tem = fold_binary_op_with_conditional_arg (t, code, arg0, arg1,
+ /*cond_first_p=*/1);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+
+ if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
+ {
+ tem = fold_binary_op_with_conditional_arg (t, code, arg1, arg0,
+ /*cond_first_p=*/0);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+ }
+
+ switch (code)
+ {
+ case CONST_DECL:
+ return fold (DECL_INITIAL (t));
+
+ case RANGE_EXPR:
+ if (TREE_CONSTANT (t) != wins)
+ {
+ tem = copy_node (t);
+ TREE_CONSTANT (tem) = wins;
+ TREE_INVARIANT (tem) = wins;
+ return tem;
+ }
return t;
case PLUS_EXPR:
if (TREE_CODE (arg0) == NEGATE_EXPR
&& reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0)));
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR);
+ if (tem)
+ return tem;
+ }
+
if (! FLOAT_TYPE_P (type))
{
if (integer_zerop (arg1))
if (TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (arg1) == MULT_EXPR)
{
- tem = try_move_mult_to_index (type, PLUS_EXPR, arg0, arg1);
+ tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
if (tem)
- return fold (tem);
+ return fold_convert (type, fold (tem));
}
else if (TREE_CODE (arg1) == ADDR_EXPR
&& TREE_CODE (arg0) == MULT_EXPR)
{
- tem = try_move_mult_to_index (type, PLUS_EXPR, arg1, arg0);
+ tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
if (tem)
- return fold (tem);
+ return fold_convert (type, fold (tem));
}
}
else
return fold (build2 (MINUS_EXPR, type, negate_expr (arg1),
TREE_OPERAND (arg0, 0)));
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR);
+ if (tem)
+ return tem;
+ }
+
if (! FLOAT_TYPE_P (type))
{
if (! wins && integer_zerop (arg0))
if (TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (arg1) == MULT_EXPR)
{
- tem = try_move_mult_to_index (type, MINUS_EXPR, arg0, arg1);
+ tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
if (tem)
- return fold (tem);
+ return fold_convert (type, fold (tem));
}
if (TREE_CODE (arg0) == MULT_EXPR
negate_expr (arg0),
TREE_OPERAND (arg1, 0)));
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tem = fold_complex_mult (type, arg0, arg1);
+ if (tem)
+ return tem;
+ }
+
if (! FLOAT_TYPE_P (type))
{
if (integer_zerop (arg1))
TREE_OPERAND (arg0, 1)));
}
+ /* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */
+ if (operand_equal_p (arg0, arg1, 0))
+ {
+ tree tem = fold_strip_sign_ops (arg0);
+ if (tem != NULL_TREE)
+ {
+ tem = fold_convert (type, tem);
+ return fold (build2 (MULT_EXPR, type, tem, tem));
+ }
+ }
+
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode0 = builtin_mathfn_code (arg0);
TREE_OPERAND (arg1, 0)));
}
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tem = fold_complex_div (type, arg0, arg1, code);
+ if (tem)
+ return tem;
+ }
+
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode = builtin_mathfn_code (arg1);
code, NULL_TREE)))
return fold_convert (type, tem);
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tem = fold_complex_div (type, arg0, arg1, code);
+ if (tem)
+ return tem;
+ }
goto binary;
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case TRUNC_MOD_EXPR:
+ /* X % 1 is always zero, but be sure to preserve any side
+ effects in X. */
if (integer_onep (arg1))
return omit_one_operand (type, integer_zero_node, arg0);
+
+ /* X % 0, return X % 0 unchanged so that we can get the
+ proper warnings and errors. */
if (integer_zerop (arg1))
return t;
+ /* 0 % X is always zero, but be sure to preserve any side
+ effects in X. Place this after checking for X == 0. */
+ if (integer_zerop (arg0))
+ return omit_one_operand (type, integer_zero_node, arg1);
+
/* X % -1 is zero. */
if (!TYPE_UNSIGNED (type)
&& TREE_CODE (arg1) == INTEGER_CST
return omit_one_operand (type, arg1, arg0);
goto associate;
- case TRUTH_NOT_EXPR:
- /* The argument to invert_truthvalue must have Boolean type. */
- if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
- arg0 = fold_convert (boolean_type_node, arg0);
-
- /* Note that the operand of this must be an int
- and its values must be 0 or 1.
- ("true" is a fixed value perhaps depending on the language,
- but we don't handle values other than 1 correctly yet.) */
- tem = invert_truthvalue (arg0);
- /* Avoid infinite recursion. */
- if (TREE_CODE (tem) == TRUTH_NOT_EXPR)
- {
- tem = fold_single_bit_test (code, arg0, arg1, type);
- if (tem)
- return tem;
- return t;
- }
- return fold_convert (type, tem);
-
case TRUTH_ANDIF_EXPR:
/* Note that the operands of this must be ints
and their values must be 0 or 1.
? code == EQ_EXPR : code != EQ_EXPR,
type);
+ /* If this is a comparison of two exprs that look like an
+ ARRAY_REF of the same object, then we can fold this to a
+ comparison of the two offsets. */
+ if (COMPARISON_CLASS_P (t))
+ {
+ tree base0, offset0, base1, offset1;
+
+ if (extract_array_ref (arg0, &base0, &offset0)
+ && extract_array_ref (arg1, &base1, &offset1)
+ && operand_equal_p (base0, base1, 0))
+ {
+ if (offset0 == NULL_TREE
+ && offset1 == NULL_TREE)
+ {
+ offset0 = integer_zero_node;
+ offset1 = integer_zero_node;
+ }
+ else if (offset0 == NULL_TREE)
+ offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+ else if (offset1 == NULL_TREE)
+ offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+
+ if (TREE_TYPE (offset0) == TREE_TYPE (offset1))
+ return fold (build2 (code, type, offset0, offset1));
+ }
+ }
+
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree targ0 = strip_float_extensions (arg0);
/* 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, my
- attempts to share the code have been nothing but trouble.
- I give up for now. */
+ This is quite similar to fold_relational_hi_lo, however,
+ attempts to share the code have been nothing but trouble. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
if (TREE_CODE (arg1) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1)
- && width <= HOST_BITS_PER_WIDE_INT
+ && width <= 2 * HOST_BITS_PER_WIDE_INT
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
- unsigned HOST_WIDE_INT signed_max;
- unsigned HOST_WIDE_INT max, min;
+ HOST_WIDE_INT signed_max_hi;
+ unsigned HOST_WIDE_INT signed_max_lo;
+ unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
- signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
-
- if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ if (width <= HOST_BITS_PER_WIDE_INT)
{
- max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
- min = 0;
+ signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+ - 1;
+ signed_max_hi = 0;
+ max_hi = 0;
+
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ {
+ max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+ min_lo = 0;
+ min_hi = 0;
+ }
+ else
+ {
+ max_lo = signed_max_lo;
+ min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ min_hi = -1;
+ }
}
else
{
- max = signed_max;
- min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ width -= HOST_BITS_PER_WIDE_INT;
+ signed_max_lo = -1;
+ signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+ - 1;
+ max_lo = -1;
+ min_lo = 0;
+
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ {
+ max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+ min_hi = 0;
+ }
+ else
+ {
+ max_hi = signed_max_hi;
+ min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ }
}
- if (TREE_INT_CST_HIGH (arg1) == 0
- && TREE_INT_CST_LOW (arg1) == max)
+ if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
+ && TREE_INT_CST_LOW (arg1) == max_lo)
switch (code)
{
case GT_EXPR:
default:
break;
}
- else if (TREE_INT_CST_HIGH (arg1) == 0
- && TREE_INT_CST_LOW (arg1) == max - 1)
+ else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+ == max_hi
+ && TREE_INT_CST_LOW (arg1) == max_lo - 1)
switch (code)
{
case GT_EXPR:
default:
break;
}
- else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
- && TREE_INT_CST_LOW (arg1) == min)
+ else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+ == min_hi
+ && TREE_INT_CST_LOW (arg1) == min_lo)
switch (code)
{
case LT_EXPR:
default:
break;
}
- else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
- && TREE_INT_CST_LOW (arg1) == min + 1)
+ else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+ == min_hi
+ && TREE_INT_CST_LOW (arg1) == min_lo + 1)
switch (code)
{
case GE_EXPR:
}
else if (!in_gimple_form
- && TREE_INT_CST_HIGH (arg1) == 0
- && TREE_INT_CST_LOW (arg1) == signed_max
+ && TREE_INT_CST_HIGH (arg1) == signed_max_hi
+ && TREE_INT_CST_LOW (arg1) == signed_max_lo
&& TYPE_UNSIGNED (TREE_TYPE (arg1))
/* signed_type does not work on pointer types. */
&& INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
build2 (LE_EXPR, type,
TREE_OPERAND (arg0, 0), arg1)));
+ /* Convert ABS_EXPR<x> >= 0 to true. */
+ else if (code == GE_EXPR
+ && tree_expr_nonnegative_p (arg0)
+ && (integer_zerop (arg1)
+ || (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_zerop (arg1))))
+ return omit_one_operand (type, integer_one_node, arg0);
+
+ /* Convert ABS_EXPR<x> < 0 to false. */
+ else if (code == LT_EXPR
+ && tree_expr_nonnegative_p (arg0)
+ && (integer_zerop (arg1) || real_zerop (arg1)))
+ return omit_one_operand (type, integer_zero_node, arg0);
+
+ /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
+ else if ((code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (arg0) == ABS_EXPR
+ && (integer_zerop (arg1) || real_zerop (arg1)))
+ return fold (build2 (code, type, TREE_OPERAND (arg0, 0), arg1));
+
/* If this is an EQ or NE comparison with zero and ARG0 is
(1 << foo) & bar, convert it to (bar >> foo) & 1. Both require
two operations, but the latter can be done in one less insn
tree arglist;
if (fndecl
- && DECL_BUILT_IN (fndecl)
- && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
&& (arglist = TREE_OPERAND (arg0, 1))
&& TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
&& ! TREE_CHAIN (arglist))
- return fold (build2 (code, type,
- build1 (INDIRECT_REF, char_type_node,
- TREE_VALUE (arglist)),
- fold_convert (char_type_node,
- integer_zero_node)));
- }
-
- /* We can fold X/C1 op C2 where C1 and C2 are integer constants
- into a single range test. */
- if (TREE_CODE (arg0) == TRUNC_DIV_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !integer_zerop (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && !TREE_OVERFLOW (arg1))
- {
- t1 = fold_div_compare (code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
- }
-
- if ((code == EQ_EXPR || code == NE_EXPR)
- && !TREE_SIDE_EFFECTS (arg0)
- && integer_zerop (arg1)
- && tree_expr_nonzero_p (arg0))
- return constant_boolean_node (code==NE_EXPR, type);
-
- t1 = fold_relational_const (code, type, arg0, arg1);
- return t1 == NULL_TREE ? t : t1;
-
- case UNORDERED_EXPR:
- case ORDERED_EXPR:
- case UNLT_EXPR:
- case UNLE_EXPR:
- case UNGT_EXPR:
- case UNGE_EXPR:
- case UNEQ_EXPR:
- case LTGT_EXPR:
- if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
- {
- t1 = fold_relational_const (code, type, arg0, arg1);
- if (t1 != NULL_TREE)
- return t1;
- }
-
- /* If the first operand is NaN, the result is constant. */
- if (TREE_CODE (arg0) == REAL_CST
- && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
- && (code != LTGT_EXPR || ! flag_trapping_math))
- {
- t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
- ? integer_zero_node
- : integer_one_node;
- return omit_one_operand (type, t1, arg1);
- }
-
- /* If the second operand is NaN, the result is constant. */
- if (TREE_CODE (arg1) == REAL_CST
- && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
- && (code != LTGT_EXPR || ! flag_trapping_math))
- {
- t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
- ? integer_zero_node
- : integer_one_node;
- return omit_one_operand (type, t1, arg0);
- }
-
- /* Simplify unordered comparison of something with itself. */
- if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
- && operand_equal_p (arg0, arg1, 0))
- return constant_boolean_node (1, type);
-
- if (code == LTGT_EXPR
- && !flag_trapping_math
- && operand_equal_p (arg0, arg1, 0))
- return constant_boolean_node (0, type);
-
- /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
- {
- tree targ0 = strip_float_extensions (arg0);
- tree targ1 = strip_float_extensions (arg1);
- tree newtype = TREE_TYPE (targ0);
-
- if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
- newtype = TREE_TYPE (targ1);
-
- if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold (build2 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1)));
- }
-
- return t;
-
- case COND_EXPR:
- /* Pedantic ANSI C says that a conditional expression is never an lvalue,
- so all simple results must be passed through pedantic_non_lvalue. */
- if (TREE_CODE (arg0) == INTEGER_CST)
- {
- tem = TREE_OPERAND (t, (integer_zerop (arg0) ? 2 : 1));
- /* Only optimize constant conditions when the selected branch
- has the same type as the COND_EXPR. This avoids optimizing
- away "c ? x : throw", where the throw has a void type. */
- if (! VOID_TYPE_P (TREE_TYPE (tem))
- || VOID_TYPE_P (type))
- return pedantic_non_lvalue (tem);
- return t;
- }
- if (operand_equal_p (arg1, TREE_OPERAND (t, 2), 0))
- return pedantic_omit_one_operand (type, arg1, arg0);
-
- /* If we have A op B ? A : C, we may be able to convert this to a
- simpler expression, depending on the operation and the values
- of B and C. Signed zeros prevent all of these transformations,
- for reasons given above each one.
-
- Also try swapping the arguments and inverting the conditional. */
- if (COMPARISON_CLASS_P (arg0)
- && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
- arg1, TREE_OPERAND (arg0, 1))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
- {
- tem = fold_cond_expr_with_comparison (type, arg0,
- TREE_OPERAND (t, 1),
- TREE_OPERAND (t, 2));
- if (tem)
- return tem;
- }
-
- if (COMPARISON_CLASS_P (arg0)
- && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (t, 2),
- TREE_OPERAND (arg0, 1))
- && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
- {
- tem = invert_truthvalue (arg0);
- if (COMPARISON_CLASS_P (tem))
- {
- tem = fold_cond_expr_with_comparison (type, tem,
- TREE_OPERAND (t, 2),
- TREE_OPERAND (t, 1));
- if (tem)
- return tem;
- }
- }
-
- /* If the second operand is simpler than the third, swap them
- since that produces better jump optimization results. */
- if (tree_swap_operands_p (TREE_OPERAND (t, 1),
- TREE_OPERAND (t, 2), false))
- {
- /* See if this can be inverted. If it can't, possibly because
- it was a floating-point inequality comparison, don't do
- anything. */
- tem = invert_truthvalue (arg0);
-
- if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold (build3 (code, type, tem,
- TREE_OPERAND (t, 2), TREE_OPERAND (t, 1)));
+ return fold (build2 (code, type,
+ build1 (INDIRECT_REF, char_type_node,
+ TREE_VALUE (arglist)),
+ fold_convert (char_type_node,
+ integer_zero_node)));
}
- /* Convert A ? 1 : 0 to simply A. */
- if (integer_onep (TREE_OPERAND (t, 1))
- && integer_zerop (TREE_OPERAND (t, 2))
- /* If we try to convert TREE_OPERAND (t, 0) to our type, the
- call to fold will try to move the conversion inside
- a COND, which will recurse. In that case, the COND_EXPR
- is probably the best choice, so leave it alone. */
- && type == TREE_TYPE (arg0))
- return pedantic_non_lvalue (arg0);
+ /* We can fold X/C1 op C2 where C1 and C2 are integer constants
+ into a single range test. */
+ if ((TREE_CODE (arg0) == TRUNC_DIV_EXPR
+ || TREE_CODE (arg0) == EXACT_DIV_EXPR)
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && !integer_zerop (TREE_OPERAND (arg0, 1))
+ && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+ && !TREE_OVERFLOW (arg1))
+ {
+ t1 = fold_div_compare (code, type, arg0, arg1);
+ if (t1 != NULL_TREE)
+ return t1;
+ }
- /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
- over COND_EXPR in cases such as floating point comparisons. */
- if (integer_zerop (TREE_OPERAND (t, 1))
- && integer_onep (TREE_OPERAND (t, 2))
- && truth_value_p (TREE_CODE (arg0)))
- return pedantic_non_lvalue (fold_convert (type,
- invert_truthvalue (arg0)));
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && !TREE_SIDE_EFFECTS (arg0)
+ && integer_zerop (arg1)
+ && tree_expr_nonzero_p (arg0))
+ return constant_boolean_node (code==NE_EXPR, type);
- /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
- if (TREE_CODE (arg0) == LT_EXPR
- && integer_zerop (TREE_OPERAND (arg0, 1))
- && integer_zerop (TREE_OPERAND (t, 2))
- && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
- return fold_convert (type, fold (build2 (BIT_AND_EXPR,
- TREE_TYPE (tem), tem, arg1)));
+ t1 = fold_relational_const (code, type, arg0, arg1);
+ return t1 == NULL_TREE ? t : t1;
- /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N). A & 1 was
- already handled above. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1))
- && integer_zerop (TREE_OPERAND (t, 2))
- && integer_pow2p (arg1))
+ case UNORDERED_EXPR:
+ case ORDERED_EXPR:
+ case UNLT_EXPR:
+ case UNLE_EXPR:
+ case UNGT_EXPR:
+ case UNGE_EXPR:
+ case UNEQ_EXPR:
+ case LTGT_EXPR:
+ if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
{
- tree tem = TREE_OPERAND (arg0, 0);
- STRIP_NOPS (tem);
- if (TREE_CODE (tem) == RSHIFT_EXPR
- && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
- && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
- TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
- return fold (build2 (BIT_AND_EXPR, type,
- TREE_OPERAND (tem, 0), arg1));
+ t1 = fold_relational_const (code, type, arg0, arg1);
+ if (t1 != NULL_TREE)
+ return t1;
}
- /* A & N ? N : 0 is simply A & N if N is a power of two. This
- is probably obsolete because the first operand should be a
- truth value (that's why we have the two cases above), but let's
- leave it in until we can confirm this for all front-ends. */
- if (integer_zerop (TREE_OPERAND (t, 2))
- && TREE_CODE (arg0) == NE_EXPR
- && integer_zerop (TREE_OPERAND (arg0, 1))
- && integer_pow2p (arg1)
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
- arg1, OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_convert (type,
- TREE_OPERAND (arg0, 0)));
-
- /* Convert A ? B : 0 into A && B if A and B are truth values. */
- if (integer_zerop (TREE_OPERAND (t, 2))
- && truth_value_p (TREE_CODE (arg0))
- && truth_value_p (TREE_CODE (arg1)))
- return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
-
- /* Convert A ? B : 1 into !A || B if A and B are truth values. */
- if (integer_onep (TREE_OPERAND (t, 2))
- && truth_value_p (TREE_CODE (arg0))
- && truth_value_p (TREE_CODE (arg1)))
+ /* If the first operand is NaN, the result is constant. */
+ if (TREE_CODE (arg0) == REAL_CST
+ && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
+ && (code != LTGT_EXPR || ! flag_trapping_math))
{
- /* Only perform transformation if ARG0 is easily inverted. */
- tem = invert_truthvalue (arg0);
- if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
+ t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+ ? integer_zero_node
+ : integer_one_node;
+ return omit_one_operand (type, t1, arg1);
}
- /* Convert A ? 0 : B into !A && B if A and B are truth values. */
- if (integer_zerop (arg1)
- && truth_value_p (TREE_CODE (arg0))
- && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ /* If the second operand is NaN, the result is constant. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+ && (code != LTGT_EXPR || ! flag_trapping_math))
{
- /* Only perform transformation if ARG0 is easily inverted. */
- tem = invert_truthvalue (arg0);
- if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
- return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
- TREE_OPERAND (t, 2)));
+ t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+ ? integer_zero_node
+ : integer_one_node;
+ return omit_one_operand (type, t1, arg0);
}
- /* Convert A ? 1 : B into A || B if A and B are truth values. */
- if (integer_onep (arg1)
- && truth_value_p (TREE_CODE (arg0))
- && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
- return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
- TREE_OPERAND (t, 2)));
+ /* Simplify unordered comparison of something with itself. */
+ if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
+ && operand_equal_p (arg0, arg1, 0))
+ return constant_boolean_node (1, type);
+
+ if (code == LTGT_EXPR
+ && !flag_trapping_math
+ && operand_equal_p (arg0, arg1, 0))
+ return constant_boolean_node (0, type);
+
+ /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
+ {
+ tree targ0 = strip_float_extensions (arg0);
+ tree targ1 = strip_float_extensions (arg1);
+ tree newtype = TREE_TYPE (targ0);
+
+ if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
+ newtype = TREE_TYPE (targ1);
+
+ if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+ return fold (build2 (code, type, fold_convert (newtype, targ0),
+ fold_convert (newtype, targ1)));
+ }
return t;
return build_complex (type, arg0, arg1);
return t;
- case REALPART_EXPR:
- if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return t;
- else if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return omit_one_operand (type, TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- else if (TREE_CODE (arg0) == COMPLEX_CST)
- return TREE_REALPART (arg0);
- else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build2 (TREE_CODE (arg0), type,
- fold (build1 (REALPART_EXPR, type,
- TREE_OPERAND (arg0, 0))),
- fold (build1 (REALPART_EXPR, type,
- TREE_OPERAND (arg0, 1)))));
- return t;
-
- case IMAGPART_EXPR:
- if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert (type, integer_zero_node);
- else if (TREE_CODE (arg0) == COMPLEX_EXPR)
- return omit_one_operand (type, TREE_OPERAND (arg0, 1),
- TREE_OPERAND (arg0, 0));
- else if (TREE_CODE (arg0) == COMPLEX_CST)
- return TREE_IMAGPART (arg0);
- else if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- return fold (build2 (TREE_CODE (arg0), type,
- fold (build1 (IMAGPART_EXPR, type,
- TREE_OPERAND (arg0, 0))),
- fold (build1 (IMAGPART_EXPR, type,
- TREE_OPERAND (arg0, 1)))));
- return t;
-
- case CALL_EXPR:
- /* Check for a built-in function. */
- if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
- == FUNCTION_DECL)
- && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
- {
- tree tmp = fold_builtin (t, false);
- if (tmp)
- return tmp;
- }
- return t;
-
default:
return t;
} /* switch (code) */
case tcc_unary:
case tcc_binary:
case tcc_statement:
- len = first_rtl_op (code);
+ len = TREE_CODE_LENGTH (code);
for (i = 0; i < len; ++i)
fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
break;
{
int saved_signaling_nans = flag_signaling_nans;
int saved_trapping_math = flag_trapping_math;
+ int saved_rounding_math = flag_rounding_math;
int saved_trapv = flag_trapv;
tree result;
flag_signaling_nans = 0;
flag_trapping_math = 0;
+ flag_rounding_math = 0;
flag_trapv = 0;
result = fold (expr);
flag_signaling_nans = saved_signaling_nans;
flag_trapping_math = saved_trapping_math;
+ flag_rounding_math = saved_rounding_math;
flag_trapv = saved_trapv;
return result;
switch (TREE_CODE (top))
{
+ case BIT_AND_EXPR:
+ /* Bitwise and provides a power of two multiple. If the mask is
+ a multiple of BOTTOM then TOP is a multiple of BOTTOM. */
+ if (!integer_pow2p (bottom))
+ return 0;
+ /* FALLTHRU */
+
case MULT_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
|| multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
{
tree fndecl = get_callee_fndecl (t);
tree arglist = TREE_OPERAND (t, 1);
- if (fndecl
- && DECL_BUILT_IN (fndecl)
- && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD)
+ if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
#define CASE_BUILTIN_F(BUILT_IN_FN) \
it with a cleanup point expression. */
if (!TREE_SIDE_EFFECTS (expr))
return expr;
+
+ /* If the expression is a return, check to see if the expression inside the
+ return has no side effects or the right hand side of the modify expression
+ inside the return. If either don't have side effects set we don't need to
+ wrap the expression in a cleanup point expression. Note we don't check the
+ left hand side of the modify because it should always be a return decl. */
+ if (TREE_CODE (expr) == RETURN_EXPR)
+ {
+ tree op = TREE_OPERAND (expr, 0);
+ if (!op || !TREE_SIDE_EFFECTS (op))
+ return expr;
+ op = TREE_OPERAND (op, 1);
+ if (!TREE_SIDE_EFFECTS (op))
+ return expr;
+ }
return build1 (CLEANUP_POINT_EXPR, type, expr);
}
{
tree base = t;
- while (handled_component_p (base)
- || TREE_CODE (base) == REALPART_EXPR
- || TREE_CODE (base) == IMAGPART_EXPR)
+ while (handled_component_p (base))
base = TREE_OPERAND (base, 0);
if (DECL_P (base))
TREE_ADDRESSABLE (base) = 1;
return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
}
-/* Builds an expression for an indirection through T, simplifying some
- cases. */
+/* Given a pointer value T, return a simplified version of an indirection
+ through T, or NULL_TREE if no simplification is possible. */
-tree
-build_fold_indirect_ref (tree t)
+static tree
+fold_indirect_ref_1 (tree t)
{
tree type = TREE_TYPE (TREE_TYPE (t));
tree sub = t;
tree subtype;
STRIP_NOPS (sub);
+ subtype = TREE_TYPE (sub);
+ if (!POINTER_TYPE_P (subtype))
+ return NULL_TREE;
+
if (TREE_CODE (sub) == ADDR_EXPR)
{
tree op = TREE_OPERAND (sub, 0);
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
&& lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
- return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
+ {
+ tree type_domain = TYPE_DOMAIN (optype);
+ tree min_val = size_zero_node;
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
+ }
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
- subtype = TREE_TYPE (sub);
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
&& lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
{
+ tree type_domain;
+ tree min_val = size_zero_node;
sub = build_fold_indirect_ref (sub);
- return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
+ type_domain = TYPE_DOMAIN (TREE_TYPE (sub));
+ if (type_domain && TYPE_MIN_VALUE (type_domain))
+ min_val = TYPE_MIN_VALUE (type_domain);
+ return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE);
}
- return build1 (INDIRECT_REF, type, t);
+ return NULL_TREE;
+}
+
+/* Builds an expression for an indirection through T, simplifying some
+ cases. */
+
+tree
+build_fold_indirect_ref (tree t)
+{
+ tree sub = fold_indirect_ref_1 (t);
+
+ if (sub)
+ return sub;
+ else
+ return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+}
+
+/* Given an INDIRECT_REF T, return either T or a simplified version. */
+
+tree
+fold_indirect_ref (tree t)
+{
+ tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+
+ if (sub)
+ return sub;
+ else
+ return t;
}
/* Strip non-trapping, non-side-effecting tree nodes from an expression
if (TREE_CODE (exp) == ADDR_EXPR)
{
core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
- poffset, &mode, &unsignedp, &volatilep);
+ poffset, &mode, &unsignedp, &volatilep,
+ false);
if (TREE_CODE (core) == INDIRECT_REF)
core = TREE_OPERAND (core, 0);
*diff += (bitpos1 - bitpos2) / BITS_PER_UNIT;
return true;
}
+
+/* Simplify the floating point expression EXP when the sign of the
+ result is not significant. Return NULL_TREE if no simplification
+ is possible. */
+
+tree
+fold_strip_sign_ops (tree exp)
+{
+ tree arg0, arg1;
+
+ switch (TREE_CODE (exp))
+ {
+ case ABS_EXPR:
+ case NEGATE_EXPR:
+ arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+ return arg0 ? arg0 : TREE_OPERAND (exp, 0);
+
+ case MULT_EXPR:
+ case RDIV_EXPR:
+ if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (TREE_TYPE (exp))))
+ return NULL_TREE;
+ arg0 = fold_strip_sign_ops (TREE_OPERAND (exp, 0));
+ arg1 = fold_strip_sign_ops (TREE_OPERAND (exp, 1));
+ if (arg0 != NULL_TREE || arg1 != NULL_TREE)
+ return fold (build2 (TREE_CODE (exp), TREE_TYPE (exp),
+ arg0 ? arg0 : TREE_OPERAND (exp, 0),
+ arg1 ? arg1 : TREE_OPERAND (exp, 1)));
+ break;
+
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+