static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
tree);
static tree fold_range_test (tree);
-static tree fold_cond_expr_with_comparison (tree, tree, tree);
+static tree fold_cond_expr_with_comparison (tree, tree, tree, tree);
static tree unextend (tree, int, int, tree);
static tree fold_truthop (enum tree_code, tree, tree, tree);
static tree optimize_minmax_comparison (tree);
|| TREE_CODE (orig) == ERROR_MARK)
return error_mark_node;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig))
+ if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (orig)
+ || lang_hooks.types_compatible_p (TYPE_MAIN_VARIANT (type),
+ TYPE_MAIN_VARIANT (orig)))
return fold (build1 (NOP_EXPR, type, arg));
if (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
return fold (build1 (NOP_EXPR, type, arg));
}
else if (VOID_TYPE_P (type))
- return fold (build1 (CONVERT_EXPR, type, arg));
+ return fold (build1 (CONVERT_EXPR, type, fold_ignored_result (arg)));
abort ();
}
\f
case COMPONENT_REF:
case INDIRECT_REF:
case ARRAY_REF:
- case BIT_FIELD_REF:
- case BUFFER_REF:
case ARRAY_RANGE_REF:
- case VTABLE_REF:
+ case BIT_FIELD_REF:
+ case OBJ_TYPE_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
case BIND_EXPR:
case MIN_EXPR:
case MAX_EXPR:
- case RTL_EXPR:
break;
default:
}
else if (flag_trapping_math)
{
- /* Check that the original operation and the optimized ones will trap
+ /* Check that the original operation and the optimized ones will trap
under the same condition. */
bool ltrap = (lcompcode & COMPCODE_UNORD) == 0
&& (lcompcode != COMPCODE_EQ)
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
return operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0), flags);
&& operand_equal_p (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 0), flags));
- case RTL_EXPR:
- return rtx_equal_p (RTL_EXPR_RTL (arg0), RTL_EXPR_RTL (arg1));
-
case CALL_EXPR:
/* If the CALL_EXPRs call different functions, then they
clearly can not be equal. */
|| code == COMPOUND_EXPR))
class = '2';
- else if (class == 'e' && code == SAVE_EXPR && SAVE_EXPR_RTL (arg) == 0
+ else if (class == 'e' && code == SAVE_EXPR
&& ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
{
/* If we've already found a CVAL1 or CVAL2, this expression is
tree t = fold_convert (type, result);
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, omitted, t);
+ return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
return non_lvalue (t);
}
tree t = fold_convert (type, result);
if (TREE_SIDE_EFFECTS (omitted))
- return build2 (COMPOUND_EXPR, type, omitted, t);
+ return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t);
return pedantic_non_lvalue (t);
}
/* If the number of bits in the reference is the same as the bitsize of
the outer type, then the outer type gives the signedness. Otherwise
(in case of a small bitfield) the signedness is unchanged. */
- if (outer_type && *pbitsize == tree_low_cst (TYPE_SIZE (outer_type), 1))
+ if (outer_type && *pbitsize == TYPE_PRECISION (outer_type))
*punsignedp = TYPE_UNSIGNED (outer_type);
/* Compute the mask to access the bitfield. */
make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
{
enum tree_code code;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE, type = NULL_TREE;
- tree orig_type = NULL_TREE;
+ tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+ tree exp_type = NULL_TREE, arg0_type = NULL_TREE;
int in_p, n_in_p;
tree low, high, n_low, n_high;
while (1)
{
code = TREE_CODE (exp);
+ exp_type = TREE_TYPE (exp);
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
{
if (TREE_CODE_CLASS (code) == '<'
|| TREE_CODE_CLASS (code) == '1'
|| TREE_CODE_CLASS (code) == '2')
- type = TREE_TYPE (arg0);
+ arg0_type = TREE_TYPE (arg0);
if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<'
|| (TREE_CODE_CLASS (code) == 'e'
arg1 = TREE_OPERAND (exp, 1);
}
- /* Set ORIG_TYPE as soon as TYPE is non-null so that we do not
- lose a cast by accident. */
- if (type != NULL_TREE && orig_type == NULL_TREE)
- orig_type = type;
-
switch (code)
{
case TRUTH_NOT_EXPR:
abort ();
}
- exp = arg0;
-
/* If this is an unsigned comparison, we also know that EXP is
greater than or equal to zero. We base the range tests we make
on that fact, so we record it here so we can parse existing
- range tests. */
- if (TYPE_UNSIGNED (type) && (low == 0 || high == 0))
+ range tests. We test arg0_type since often the return type
+ of, e.g. EQ_EXPR, is boolean. */
+ if (TYPE_UNSIGNED (arg0_type) && (low == 0 || high == 0))
{
if (! merge_ranges (&n_in_p, &n_low, &n_high, in_p, low, high,
- 1, fold_convert (type, integer_zero_node),
+ 1, fold_convert (arg0_type, integer_zero_node),
NULL_TREE))
break;
in_p = ! in_p;
high = range_binop (MINUS_EXPR, NULL_TREE, low, 0,
integer_one_node, 0);
- low = fold_convert (type, integer_zero_node);
+ low = fold_convert (arg0_type, integer_zero_node);
}
}
+
+ exp = arg0;
continue;
case NEGATE_EXPR:
/* (-x) IN [a,b] -> x in [-b, -a] */
- n_low = range_binop (MINUS_EXPR, type,
- fold_convert (type, integer_zero_node),
+ n_low = range_binop (MINUS_EXPR, exp_type,
+ fold_convert (exp_type, integer_zero_node),
0, high, 1);
- n_high = range_binop (MINUS_EXPR, type,
- fold_convert (type, integer_zero_node),
+ n_high = range_binop (MINUS_EXPR, exp_type,
+ fold_convert (exp_type, integer_zero_node),
0, low, 0);
low = n_low, high = n_high;
exp = arg0;
case BIT_NOT_EXPR:
/* ~ X -> -X - 1 */
- exp = build2 (MINUS_EXPR, type, negate_expr (arg0),
- fold_convert (type, integer_one_node));
+ exp = build2 (MINUS_EXPR, exp_type, negate_expr (arg0),
+ fold_convert (exp_type, integer_one_node));
continue;
case PLUS_EXPR: case MINUS_EXPR:
the bounds don't overflow. For unsigned, overflow is defined
and this is exactly the right thing. */
n_low = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
- type, low, 0, arg1, 0);
+ arg0_type, low, 0, arg1, 0);
n_high = range_binop (code == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR,
- type, high, 1, arg1, 0);
+ arg0_type, high, 1, arg1, 0);
if ((n_low != 0 && TREE_OVERFLOW (n_low))
|| (n_high != 0 && TREE_OVERFLOW (n_high)))
break;
value thus making n_high < n_low, and normalize it. */
if (n_low && n_high && tree_int_cst_lt (n_high, n_low))
{
- low = range_binop (PLUS_EXPR, type, n_high, 0,
+ low = range_binop (PLUS_EXPR, arg0_type, n_high, 0,
integer_one_node, 0);
- high = range_binop (MINUS_EXPR, type, n_low, 0,
+ high = range_binop (MINUS_EXPR, arg0_type, n_low, 0,
integer_one_node, 0);
/* If the range is of the form +/- [ x+1, x ], we won't
continue;
case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
- if (TYPE_PRECISION (type) > TYPE_PRECISION (orig_type))
+ if (TYPE_PRECISION (arg0_type) > TYPE_PRECISION (exp_type))
break;
- if (! INTEGRAL_TYPE_P (type)
- || (low != 0 && ! int_fits_type_p (low, type))
- || (high != 0 && ! int_fits_type_p (high, type)))
+ if (! INTEGRAL_TYPE_P (arg0_type)
+ || (low != 0 && ! int_fits_type_p (low, arg0_type))
+ || (high != 0 && ! int_fits_type_p (high, arg0_type)))
break;
n_low = low, n_high = high;
if (n_low != 0)
- n_low = fold_convert (type, n_low);
+ n_low = fold_convert (arg0_type, n_low);
if (n_high != 0)
- n_high = fold_convert (type, n_high);
+ n_high = fold_convert (arg0_type, n_high);
+
- /* If we're converting from an unsigned to a signed type,
- we will be doing the comparison as unsigned. The tests above
- have already verified that LOW and HIGH are both positive.
+ /* If we're converting arg0 from an unsigned type, to exp,
+ a signed type, we will be doing the comparison as unsigned.
+ The tests above have already verified that LOW and HIGH
+ are both positive.
- So we have to make sure that the original unsigned value will
- be interpreted as positive. */
- if (TYPE_UNSIGNED (type) && ! TYPE_UNSIGNED (TREE_TYPE (exp)))
+ So we have to ensure that we will handle large unsigned
+ values the same way that the current signed bounds treat
+ negative values. */
+
+ if (!TYPE_UNSIGNED (exp_type) && TYPE_UNSIGNED (arg0_type))
{
- tree equiv_type = lang_hooks.types.type_for_mode
- (TYPE_MODE (type), 1);
tree high_positive;
+ tree equiv_type = lang_hooks.types.type_for_mode
+ (TYPE_MODE (arg0_type), 1);
/* A range without an upper bound is, naturally, unbounded.
Since convert would have cropped a very large value, use
the max value for the destination type. */
high_positive
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
- : TYPE_MAX_VALUE (type);
+ : TYPE_MAX_VALUE (arg0_type);
- if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
- high_positive = fold (build2 (RSHIFT_EXPR, type,
- fold_convert (type,
+ if (TYPE_PRECISION (exp_type) == TYPE_PRECISION (arg0_type))
+ high_positive = fold (build2 (RSHIFT_EXPR, arg0_type,
+ fold_convert (arg0_type,
high_positive),
- fold_convert (type,
+ fold_convert (arg0_type,
integer_one_node)));
/* If the low bound is specified, "and" the range with the
{
if (! merge_ranges (&n_in_p, &n_low, &n_high,
1, n_low, n_high, 1,
- fold_convert (type, integer_zero_node),
+ fold_convert (arg0_type, integer_zero_node),
high_positive))
break;
that will be interpreted as negative. */
if (! merge_ranges (&n_in_p, &n_low, &n_high,
0, n_low, n_high, 1,
- fold_convert (type, integer_zero_node),
+ fold_convert (arg0_type, integer_zero_node),
high_positive))
break;
\f
/* Subroutine of fold, looking inside expressions of the form
- A op B ? A : C, where ARG0 is A op B and ARG2 is C. This
- function is being used also to optimize A op B ? C : A, by
- reversing the comparison first.
+ A op B ? A : C, where ARG0, ARG1 and ARG2 are the three operands
+ of the COND_EXPR. This function is being used also to optimize
+ A op B ? C : A, by reversing the comparison first.
Return a folded expression whose code is not a COND_EXPR
anymore, or NULL_TREE if no folding opportunity is found. */
static tree
-fold_cond_expr_with_comparison (tree type, tree arg0, tree arg2)
+fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
{
enum tree_code comp_code = TREE_CODE (arg0);
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg1_type = TREE_TYPE (arg1);
tree tem;
+
+ STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
/* If we have A op 0 ? A : -A, consider applying the following
? real_zerop (arg01)
: integer_zerop (arg01))
&& TREE_CODE (arg2) == NEGATE_EXPR
- && operand_equal_p (TREE_OPERAND (arg2, 0), arg00, 0))
+ && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
switch (comp_code)
{
case EQ_EXPR:
- return fold_convert (type, negate_expr (arg00));
+ tem = fold_convert (arg1_type, arg1);
+ return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
case NE_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg00));
+ return pedantic_non_lvalue (fold_convert (type, arg1));
case GE_EXPR:
case GT_EXPR:
- if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
- arg00 = fold_convert (lang_hooks.types.signed_type
- (TREE_TYPE (arg00)), arg00);
- tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = fold_convert (lang_hooks.types.signed_type
+ (TREE_TYPE (arg1)), arg1);
+ tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
return pedantic_non_lvalue (fold_convert (type, tem));
case LE_EXPR:
case LT_EXPR:
- if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
- arg00 = fold_convert (lang_hooks.types.signed_type
- (TREE_TYPE (arg00)), arg00);
- tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ arg1 = fold_convert (lang_hooks.types.signed_type
+ (TREE_TYPE (arg1)), arg1);
+ tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
return negate_expr (fold_convert (type, tem));
default:
abort ();
if (integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
- return pedantic_non_lvalue (fold_convert (type, arg00));
+ return pedantic_non_lvalue (fold_convert (type, arg1));
else if (comp_code == EQ_EXPR)
return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
}
if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
{
comp_type = type;
- comp_op0 = arg00;
+ comp_op0 = arg1;
comp_op1 = arg2;
}
case EQ_EXPR:
return pedantic_non_lvalue (fold_convert (type, arg2));
case NE_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg00));
+ return pedantic_non_lvalue (fold_convert (type, arg1));
case LE_EXPR:
case LT_EXPR:
/* In C++ a ?: expression can be an lvalue, so put the
operand which will be used if they are equal first
so that we can convert this back to the
corresponding COND_EXPR. */
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
return pedantic_non_lvalue (
fold_convert (type, fold (build2 (MIN_EXPR, comp_type,
(comp_code == LE_EXPR
break;
case GE_EXPR:
case GT_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
return pedantic_non_lvalue (
fold_convert (type, fold (build2 (MAX_EXPR, comp_type,
(comp_code == GE_EXPR
{
case EQ_EXPR:
/* We can replace A with C1 in this case. */
- arg00 = fold_convert (type, arg01);
- return fold (build3 (COND_EXPR, type, arg0, arg00, arg2));
+ arg1 = fold_convert (type, arg01);
+ return fold (build3 (COND_EXPR, type, arg0, arg1, arg2));
case LT_EXPR:
/* If C1 is C2 + 1, this is min(A, C2). */
integer_one_node, 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
- type, arg00, arg2)));
+ type, arg1, arg2)));
break;
case LE_EXPR:
integer_one_node, 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
- type, arg00, arg2)));
+ type, arg1, arg2)));
break;
case GT_EXPR:
integer_one_node, 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
- type, arg00, arg2)));
+ type, arg1, arg2)));
break;
case GE_EXPR:
integer_one_node, 0),
OEP_ONLY_CONST))
return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
- type, arg00, arg2)));
+ type, arg1, arg2)));
break;
case NE_EXPR:
break;
not appropriate if we are in gimple form. */
if (in_gimple_form)
return NULL_TREE;
-
+
temp = fold (build2 (neg ? LT_EXPR : GT_EXPR, type,
arg0, build_real (TREE_TYPE (arg0), max)));
return fold (build1 (TRUTH_NOT_EXPR, type, temp));
equality/inequality test, then return a simplified form of
the test using shifts and logical operations. Otherwise return
NULL. TYPE is the desired result type. */
-
+
tree
fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
tree result_type)
arg1 = TREE_OPERAND (arg0, 1);
arg0 = TREE_OPERAND (arg0, 0);
- /* This requires us to invert the code. */
+ /* This requires us to invert the code. */
code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
}
int ops_unsigned;
tree signed_type, unsigned_type, intermediate_type;
tree arg00;
-
+
/* If we have (A & C) != 0 where C is the sign bit of A, convert
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
fold_convert (stype, integer_zero_node)));
}
- /* Otherwise we have (A & C) != 0 where C is a single bit,
+ /* Otherwise we have (A & C) != 0 where C is a single bit,
convert that into ((A >> C2) & 1). Where C2 = log2(C).
Similarly for (A & C) == 0. */
inner, size_int (bitnum));
if (code == EQ_EXPR)
- inner = build2 (BIT_XOR_EXPR, intermediate_type,
- inner, integer_one_node);
+ inner = fold (build2 (BIT_XOR_EXPR, intermediate_type,
+ inner, integer_one_node));
/* Put the AND last so it can combine with more things. */
inner = build2 (BIT_AND_EXPR, intermediate_type,
return 0;
if (TREE_CONSTANT (arg0))
return 1;
-
+
if (optimize_size)
return 0;
if all operands are constant. */
int wins = 1;
- /* Don't try to process an RTL_EXPR since its operands aren't trees.
- Likewise for a SAVE_EXPR that's already been evaluated. */
- if (code == RTL_EXPR || (code == SAVE_EXPR && SAVE_EXPR_RTL (t) != 0))
- return t;
-
/* Return right away if a constant. */
if (kind == 'c')
return t;
if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
return non_lvalue (fold_convert (type, arg1));
+ /* Convert X + -C into X - C. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+ {
+ tem = fold_negate_const (arg1, type);
+ if (!TREE_OVERFLOW (arg1) || !flag_trapping_math)
+ return fold (build2 (MINUS_EXPR, type,
+ fold_convert (type, arg0),
+ fold_convert (type, tem)));
+ }
+
/* Convert x+x into x*2.0. */
if (operand_equal_p (arg0, arg1, 0)
&& SCALAR_FLOAT_TYPE_P (type))
tree mask0 = TREE_OPERAND (arg0, 1);
tree mask1 = TREE_OPERAND (arg1, 1);
tree tem = fold (build1 (BIT_NOT_EXPR, type, mask0));
-
+
if (operand_equal_p (tem, mask1, 0))
{
tem = fold (build2 (BIT_XOR_EXPR, type,
/* A - B -> A + (-B) if B is easily negatable. */
if (!wins && negate_expr_p (arg1)
- && (FLOAT_TYPE_P (type)
+ && ((FLOAT_TYPE_P (type)
+ /* Avoid this transformation if B is a positive REAL_CST. */
+ && (TREE_CODE (arg1) != REAL_CST
+ || REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
|| (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
return non_lvalue (fold_convert (type, arg0));
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue (fold_convert (type, arg0));
+
+ /* ~X | X is -1. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ {
+ t1 = build_int_2 (-1, -1);
+ TREE_TYPE (t1) = type;
+ force_fit_type (t1, 0);
+ return omit_one_operand (type, t1, arg1);
+ }
+
+ /* X | ~X is -1. */
+ if (TREE_CODE (arg1) == BIT_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ {
+ t1 = build_int_2 (-1, -1);
+ TREE_TYPE (t1) = type;
+ force_fit_type (t1, 0);
+ return omit_one_operand (type, t1, arg0);
+ }
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
if (operand_equal_p (arg0, arg1, 0))
return omit_one_operand (type, integer_zero_node, arg0);
+ /* ~X ^ X is -1. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ {
+ t1 = build_int_2 (-1, -1);
+ TREE_TYPE (t1) = type;
+ force_fit_type (t1, 0);
+ return omit_one_operand (type, t1, arg1);
+ }
+
+ /* X ^ ~X is -1. */
+ if (TREE_CODE (arg1) == BIT_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ {
+ t1 = build_int_2 (-1, -1);
+ TREE_TYPE (t1) = type;
+ force_fit_type (t1, 0);
+ return omit_one_operand (type, t1, arg0);
+ }
+
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
we should treat this as a BIT_IOR_EXPR since this may produce more
return omit_one_operand (type, arg1, arg0);
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue (fold_convert (type, arg0));
+
+ /* ~X & X is always zero. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand (type, integer_zero_node, arg1);
+
+ /* X & ~X is always zero. */
+ if (TREE_CODE (arg1) == BIT_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand (type, integer_zero_node, arg0);
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
return omit_one_operand (type, integer_zero_node, arg0);
if (integer_zerop (arg1))
return t;
+
/* X % -1 is zero. */
if (!TYPE_UNSIGNED (type)
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_INT_CST_HIGH (arg1) == -1)
return omit_one_operand (type, integer_zero_node, arg0);
+ /* Optimize unsigned TRUNC_MOD_EXPR by a power of two into a
+ BIT_AND_EXPR, i.e. "X % C" into "X & C2". */
+ if (code == TRUNC_MOD_EXPR
+ && TYPE_UNSIGNED (type)
+ && integer_pow2p (arg1))
+ {
+ unsigned HOST_WIDE_INT high, low;
+ tree mask;
+ int l;
+
+ l = tree_log2 (arg1);
+ if (l >= HOST_BITS_PER_WIDE_INT)
+ {
+ high = ((unsigned HOST_WIDE_INT) 1
+ << (l - HOST_BITS_PER_WIDE_INT)) - 1;
+ low = -1;
+ }
+ else
+ {
+ high = 0;
+ low = ((unsigned HOST_WIDE_INT) 1 << l) - 1;
+ }
+
+ mask = build_int_2 (low, high);
+ TREE_TYPE (mask) = type;
+ return fold (build2 (BIT_AND_EXPR, type,
+ fold_convert (type, arg0), mask));
+ }
+
+ /* X % -C is the same as X % C (for all rounding moduli). */
+ if (!TYPE_UNSIGNED (type)
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_INT_CST_HIGH (arg1) < 0
+ && !flag_trapv
+ /* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
+ && !sign_bit_p (arg1, arg1))
+ return fold (build2 (code, type, fold_convert (type, arg0),
+ fold_convert (type, negate_expr (arg1))));
+
+ /* X % -Y is the same as X % Y (for all rounding moduli). */
+ if (!TYPE_UNSIGNED (type)
+ && TREE_CODE (arg1) == NEGATE_EXPR
+ && !flag_trapv)
+ return fold (build2 (code, type, fold_convert (type, arg0),
+ fold_convert (type, TREE_OPERAND (arg1, 0))));
+
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (TREE_OPERAND (t, 0), arg1,
code, NULL_TREE)))
/* 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,
if (integer_zerop (arg0))
return omit_one_operand (type, arg0, arg1);
+ /* !X && X is always false. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand (type, integer_zero_node, arg1);
+ /* X && !X is always false. */
+ if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand (type, integer_zero_node, arg0);
+
truth_andor:
/* We only do these simplifications if we are optimizing. */
if (!optimize)
TRUTH_OR_EXPR. */
if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
return omit_one_operand (type, arg0, arg1);
+
+ /* !X || X is always true. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand (type, integer_one_node, arg1);
+ /* X || !X is always true. */
+ if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand (type, integer_one_node, arg0);
+
goto truth_andor;
case TRUTH_XOR_EXPR:
- /* If either arg is constant zero, drop it. */
- if (integer_zerop (arg0))
- return non_lvalue (fold_convert (type, arg1));
+ /* If the second arg is constant zero, drop it. */
if (integer_zerop (arg1))
return non_lvalue (fold_convert (type, arg0));
- /* If either arg is constant true, this is a logical inversion. */
- if (integer_onep (arg0))
- return non_lvalue (fold_convert (type, invert_truthvalue (arg1)));
+ /* If the second arg is constant true, this is a logical inversion. */
if (integer_onep (arg1))
return non_lvalue (fold_convert (type, invert_truthvalue (arg0)));
/* Identical arguments cancel to zero. */
if (operand_equal_p (arg0, arg1, 0))
return omit_one_operand (type, integer_zero_node, arg0);
+
+ /* !X ^ X is always true. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand (type, integer_one_node, arg1);
+
+ /* X ^ !X is always true. */
+ if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand (type, integer_one_node, arg0);
+
return t;
case EQ_EXPR:
/* If VAROP is a reference to a bitfield, we must mask
the constant by the width of the field. */
if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1)))
+ && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1))
+ && host_integerp (DECL_SIZE (TREE_OPERAND
+ (TREE_OPERAND (varop, 0), 1)), 1))
{
tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
- int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl));
+ HOST_WIDE_INT size = tree_low_cst (DECL_SIZE (fielddecl), 1);
tree folded_compare, shift;
/* First check whether the comparison would come out
always the same. If we don't do that we would
change the meaning with the masking. */
folded_compare = fold (build2 (code, type,
- TREE_OPERAND (varop, 0),
- arg1));
+ TREE_OPERAND (varop, 0), arg1));
if (integer_zerop (folded_compare)
|| integer_onep (folded_compare))
return omit_one_operand (type, folded_compare, varop);
shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
0);
+ shift = fold_convert (TREE_TYPE (varop), shift);
newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
newconst, shift));
newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop),
}
/* Comparisons with the highest or lowest possible integer of
- the specified size will have known values.
+ 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.
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
- tree newmod = build2 (TREE_CODE (arg0), newtype,
- fold_convert (newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert (newtype,
- TREE_OPERAND (arg0, 1)));
+ tree newmod = fold (build2 (TREE_CODE (arg0), newtype,
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 1))));
- return build2 (code, type, newmod, fold_convert (newtype, arg1));
+ return fold (build2 (code, type, newmod,
+ fold_convert (newtype, arg1)));
}
/* If this is an NE comparison of zero with an AND of one, remove the
&& !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;
tem = invert_truthvalue (arg0);
if (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
{
- tem = fold_cond_expr_with_comparison (type, tem, arg1);
+ tem = fold_cond_expr_with_comparison (type, tem,
+ TREE_OPERAND (t, 2),
+ TREE_OPERAND (t, 1));
if (tem)
return tem;
}
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
{
- tree tmp = fold_builtin (t);
+ tree tmp = fold_builtin (t, false);
if (tmp)
return tmp;
}
return;
*slot = expr;
code = TREE_CODE (expr);
- if (code == SAVE_EXPR && SAVE_EXPR_NOPLACEHOLDER (expr))
- {
- /* Allow SAVE_EXPR_NOPLACEHOLDER flag to be modified. */
- memcpy (buf, expr, tree_size (expr));
- expr = (tree) buf;
- SAVE_EXPR_NOPLACEHOLDER (expr) = 0;
- }
- else if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
+ if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
{
/* Allow DECL_ASSEMBLER_NAME to be modified. */
memcpy (buf, expr, tree_size (expr));
fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
- len = TREE_CODE_LENGTH (code);
switch (TREE_CODE_CLASS (code))
{
case 'c':
}
break;
case 'e':
- switch (code)
- {
- case SAVE_EXPR: len = 2; break;
- case GOTO_SUBROUTINE_EXPR: len = 0; break;
- case RTL_EXPR: len = 0; break;
- case WITH_CLEANUP_EXPR: len = 2; break;
- default: break;
- }
- /* Fall through. */
case 'r':
case '<':
case '1':
case '2':
case 's':
+ len = first_rtl_op (code);
for (i = 0; i < len; ++i)
fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
break;
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case FLOAT_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
- case RTL_EXPR:
- return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
case TARGET_EXPR:
{
return tem;
}
return NULL_TREE;
-
+
case MINUS_EXPR:
/* Fold &x - &x. This can happen from &x.foo - &x.
This is unsafe for certain floats even in non-IEEE formats.
return omit_one_operand (type, op1, op0);
goto binary;
-
+
case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR:
case FLOOR_DIV_EXPR:
/* Given the components of a unary expression CODE, TYPE and OP0,
attempt to fold the expression to a constant without modifying
- TYPE or OP0.
+ TYPE or OP0.
If the expression could be simplified to a constant, then return
the constant. If the expression would not be simplified to a
tree string;
if (TREE_CODE (exp) == INDIRECT_REF)
- {
- string = string_constant (exp1, &index);
- }
+ string = string_constant (exp1, &index);
else
{
- tree domain = TYPE_DOMAIN (TREE_TYPE (exp1));
- tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+ tree low_bound = array_ref_low_bound (exp);
index = fold_convert (sizetype, TREE_OPERAND (exp, 1));
-
+
/* Optimize the special-case of a zero lower bound.
We convert the low_bound to sizetype to avoid some problems
}
if (string
+ && TREE_TYPE (exp) == TREE_TYPE (TREE_TYPE (string))
&& TREE_CODE (string) == STRING_CST
&& TREE_CODE (index) == INTEGER_CST
&& compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
else
abort ();
#endif
-
+
return t;
}
else
abort ();
#endif
-
+
return t;
}
else
abort ();
#endif
-
+
return t;
}
else
{
tree base = t;
- while (TREE_CODE (base) == COMPONENT_REF
- || TREE_CODE (base) == ARRAY_REF)
+
+ while (handled_component_p (base)
+ || TREE_CODE (base) == REALPART_EXPR
+ || TREE_CODE (base) == IMAGPART_EXPR)
base = TREE_OPERAND (base, 0);
if (DECL_P (base))
TREE_ADDRESSABLE (base) = 1;
/* *(foo *)&fooarray => fooarray[0] */
else if (TREE_CODE (optype) == ARRAY_TYPE
&& lang_hooks.types_compatible_p (type, TREE_TYPE (optype)))
- return build2 (ARRAY_REF, type, op, size_zero_node);
+ return build4 (ARRAY_REF, type, op, size_zero_node, NULL_TREE, NULL_TREE);
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
&& lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
{
sub = build_fold_indirect_ref (sub);
- return build2 (ARRAY_REF, type, sub, size_zero_node);
+ return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
}
return build1 (INDIRECT_REF, type, t);
}
+/* Strip non-trapping, non-side-effecting tree nodes from an expression
+ whose result is ignored. The type of the returned tree need not be
+ the same as the original expression. */
+
+tree
+fold_ignored_result (tree t)
+{
+ if (!TREE_SIDE_EFFECTS (t))
+ return integer_zero_node;
+
+ for (;;)
+ switch (TREE_CODE_CLASS (TREE_CODE (t)))
+ {
+ case '1':
+ t = TREE_OPERAND (t, 0);
+ break;
+
+ case '2':
+ case '<':
+ if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+ t = TREE_OPERAND (t, 0);
+ else if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0)))
+ t = TREE_OPERAND (t, 1);
+ else
+ return t;
+ break;
+
+ case 'e':
+ switch (TREE_CODE (t))
+ {
+ case COMPOUND_EXPR:
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
+ return t;
+ t = TREE_OPERAND (t, 0);
+ break;
+
+ case COND_EXPR:
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1))
+ || TREE_SIDE_EFFECTS (TREE_OPERAND (t, 2)))
+ return t;
+ t = TREE_OPERAND (t, 0);
+ break;
+
+ default:
+ return t;
+ }
+ break;
+
+ default:
+ return t;
+ }
+}
+
#include "gt-fold-const.h"