add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
return overflow;
}
+
+/* If ARG2 divides ARG1 with zero remainder, carries out the division
+ of type CODE and returns the quotient.
+ Otherwise returns NULL_TREE. */
+
+static tree
+div_if_zero_remainder (enum tree_code code, tree arg1, tree arg2)
+{
+ unsigned HOST_WIDE_INT int1l, int2l;
+ HOST_WIDE_INT int1h, int2h;
+ unsigned HOST_WIDE_INT quol, reml;
+ HOST_WIDE_INT quoh, remh;
+ tree type = TREE_TYPE (arg1);
+ int uns = TYPE_UNSIGNED (type);
+
+ int1l = TREE_INT_CST_LOW (arg1);
+ int1h = TREE_INT_CST_HIGH (arg1);
+ int2l = TREE_INT_CST_LOW (arg2);
+ int2h = TREE_INT_CST_HIGH (arg2);
+
+ div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
+ &quol, &quoh, &reml, &remh);
+ if (remh != 0 || reml != 0)
+ return NULL_TREE;
+
+ return build_int_cst_wide (type, quol, quoh);
+}
\f
/* Return true if built-in mathematical function specified by CODE
preserves the sign of it argument, i.e. -f(x) == f(-x). */
return fold_build2 (TREE_CODE (arg0), type, common,
fold_build2 (code, type, left, right));
}
+
+/* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
+ with code CODE. This optimization is unsafe. */
+static tree
+distribute_real_division (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+ bool mul0 = TREE_CODE (arg0) == MULT_EXPR;
+ bool mul1 = TREE_CODE (arg1) == MULT_EXPR;
+
+ /* (A / C) +- (B / C) -> (A +- B) / C. */
+ if (mul0 == mul1
+ && operand_equal_p (TREE_OPERAND (arg0, 1),
+ TREE_OPERAND (arg1, 1), 0))
+ return fold_build2 (mul0 ? MULT_EXPR : RDIV_EXPR, type,
+ fold_build2 (code, type,
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0)),
+ TREE_OPERAND (arg0, 1));
+
+ /* (A / C1) +- (A / C2) -> A * (1 / C1 +- 1 / C2). */
+ if (operand_equal_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg1, 0), 0)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+ && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
+ {
+ REAL_VALUE_TYPE r0, r1;
+ r0 = TREE_REAL_CST (TREE_OPERAND (arg0, 1));
+ r1 = TREE_REAL_CST (TREE_OPERAND (arg1, 1));
+ if (!mul0)
+ real_arithmetic (&r0, RDIV_EXPR, &dconst1, &r0);
+ if (!mul1)
+ real_arithmetic (&r1, RDIV_EXPR, &dconst1, &r1);
+ real_arithmetic (&r0, code, &r0, &r1);
+ return fold_build2 (MULT_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ build_real (type, r0));
+ }
+
+ return NULL_TREE;
+}
\f
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
fold_convert (unsigned_type, rhs),
size_int (lbitsize), 0)))
{
- warning ("comparison is always %d due to width of bit-field",
+ warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
return constant_boolean_node (code == NE_EXPR, compare_type);
}
size_int (lbitsize - 1), 0);
if (! integer_zerop (tem) && ! integer_all_onesp (tem))
{
- warning ("comparison is always %d due to width of bit-field",
+ warning (0, "comparison is always %d due to width of bit-field",
code == NE_EXPR);
return constant_boolean_node (code == NE_EXPR, compare_type);
}
lntype, ll_mask),
0)))
{
- warning ("comparison is always %d", wanted_code == NE_EXPR);
+ warning (0, "comparison is always %d", wanted_code == NE_EXPR);
return constant_boolean_node (wanted_code == NE_EXPR, truth_type);
}
lntype, rl_mask),
0)))
{
- warning ("comparison is always %d", wanted_code == NE_EXPR);
+ warning (0, "comparison is always %d", wanted_code == NE_EXPR);
return constant_boolean_node (wanted_code == NE_EXPR, truth_type);
}
{
if (wanted_code == NE_EXPR)
{
- warning ("%<or%> of unmatched not-equal tests is always 1");
+ warning (0, "%<or%> of unmatched not-equal tests is always 1");
return constant_boolean_node (true, truth_type);
}
else
{
- warning ("%<and%> of mutually exclusive equal-tests is always 0");
+ warning (0, "%<and%> of mutually exclusive equal-tests is always 0");
return constant_boolean_node (false, truth_type);
}
}
/* If CODE with arguments ARG0 and ARG1 represents a single bit
- 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. */
+ equality/inequality test, then return a simplified form of the test
+ using a sign testing. 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)
+static tree
+fold_single_bit_test_into_sign_test (enum tree_code code, tree arg0, tree arg1,
+ tree result_type)
{
/* 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)
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
- tree inner = TREE_OPERAND (arg0, 0);
- tree type = TREE_TYPE (arg0);
- int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
- enum machine_mode operand_mode = TYPE_MODE (type);
- 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));
+ tree arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
+
if (arg00 != NULL_TREE
/* This is only a win if casting to a signed type is cheap,
i.e. when arg00's type is not a partial mode. */
result_type, fold_convert (stype, arg00),
fold_convert (stype, integer_zero_node));
}
+ }
+
+ return NULL_TREE;
+}
+
+/* If CODE with arguments ARG0 and ARG1 represents a single bit
+ 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)
+{
+ /* 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)
+ && integer_pow2p (TREE_OPERAND (arg0, 1)))
+ {
+ tree inner = TREE_OPERAND (arg0, 0);
+ tree type = TREE_TYPE (arg0);
+ int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
+ enum machine_mode operand_mode = TYPE_MODE (type);
+ int ops_unsigned;
+ tree signed_type, unsigned_type, intermediate_type;
+ tree tem;
+
+ /* First, see if we can fold the single bit test into a sign-bit
+ test. */
+ tem = fold_single_bit_test_into_sign_test (code, arg0, arg1,
+ result_type);
+ if (tem)
+ return tem;
/* Otherwise we have (A & C) != 0 where C is a single bit,
convert that into ((A >> C2) & 1). Where C2 = log2(C).
|| 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
+ && (TREE_CODE (shorter_type) == INTEGER_TYPE
+ || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
&& int_fits_type_p (arg1_unw, shorter_type))))
return fold_build2 (code, type, arg0_unw,
fold_convert (shorter_type, arg1_unw));
}
/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
- step of the array. ADDR is the address. MULT is the multiplicative expression.
+ step of the array. Reconstructs s and delta in the case of s * delta
+ being an integer constant (and thus already folded).
+ 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 (enum tree_code code, tree addr, tree mult)
+try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
{
tree s, delta, step;
- tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
tree ref = TREE_OPERAND (addr, 0), pref;
tree ret, pos;
tree itype;
- STRIP_NOPS (arg0);
- STRIP_NOPS (arg1);
-
- if (TREE_CODE (arg0) == INTEGER_CST)
+ /* Canonicalize op1 into a possibly non-constant delta
+ and an INTEGER_CST s. */
+ if (TREE_CODE (op1) == MULT_EXPR)
{
- s = arg0;
- delta = arg1;
+ tree arg0 = TREE_OPERAND (op1, 0), arg1 = TREE_OPERAND (op1, 1);
+
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
+ if (TREE_CODE (arg0) == INTEGER_CST)
+ {
+ s = arg0;
+ delta = arg1;
+ }
+ else if (TREE_CODE (arg1) == INTEGER_CST)
+ {
+ s = arg1;
+ delta = arg0;
+ }
+ else
+ return NULL_TREE;
}
- else if (TREE_CODE (arg1) == INTEGER_CST)
+ else if (TREE_CODE (op1) == INTEGER_CST)
{
- s = arg1;
- delta = arg0;
+ delta = op1;
+ s = NULL_TREE;
}
else
- return NULL_TREE;
+ {
+ /* Simulate we are delta * 1. */
+ delta = op1;
+ s = integer_one_node;
+ }
for (;; ref = TREE_OPERAND (ref, 0))
{
if (TREE_CODE (ref) == ARRAY_REF)
{
- step = array_ref_element_size (ref);
-
- if (TREE_CODE (step) != INTEGER_CST)
+ itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+ if (! itype)
continue;
- itype = TREE_TYPE (step);
-
- /* If the type sizes do not match, we might run into problems
- when one of them would overflow. */
- if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
+ step = array_ref_element_size (ref);
+ if (TREE_CODE (step) != INTEGER_CST)
continue;
- if (!operand_equal_p (step, fold_convert (itype, s), 0))
- continue;
+ if (s)
+ {
+ if (! tree_int_cst_equal (step, s))
+ continue;
+ }
+ else
+ {
+ /* Try if delta is a multiple of step. */
+ tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, delta, step);
+ if (! tmp)
+ continue;
+ delta = tmp;
+ }
- delta = fold_convert (itype, delta);
break;
}
}
TREE_OPERAND (pos, 1) = fold_build2 (code, itype,
- TREE_OPERAND (pos, 1),
- delta);
+ fold_convert (itype,
+ TREE_OPERAND (pos, 1)),
+ fold_convert (itype, delta));
return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
}
OP0. Return the folded expression if folding is successful.
Otherwise, return NULL_TREE. */
-static tree
+tree
fold_unary (enum tree_code code, tree type, tree op0)
{
tree tem;
|| (TREE_CODE (arg0) == PLUS_EXPR
&& integer_all_onesp (TREE_OPERAND (arg0, 1)))))
return fold_build1 (NEGATE_EXPR, type, TREE_OPERAND (arg0, 0));
+ /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
+ else if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && (tem = fold_unary (BIT_NOT_EXPR, type,
+ fold_convert (type,
+ TREE_OPERAND (arg0, 0)))))
+ return fold_build2 (BIT_XOR_EXPR, type, tem,
+ fold_convert (type, TREE_OPERAND (arg0, 1)));
+ else if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && (tem = fold_unary (BIT_NOT_EXPR, type,
+ fold_convert (type,
+ TREE_OPERAND (arg0, 1)))))
+ return fold_build2 (BIT_XOR_EXPR, type,
+ fold_convert (type, TREE_OPERAND (arg0, 0)), tem);
+
return NULL_TREE;
case TRUTH_NOT_EXPR:
OP0 and OP1. Return the folded expression if folding is
successful. Otherwise, return NULL_TREE. */
-static tree
+tree
fold_binary (enum tree_code code, tree type, tree op0, tree op1)
{
tree t1 = NULL_TREE;
case PLUS_EXPR:
/* A + (-B) -> A - B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2 (MINUS_EXPR, type, arg0, TREE_OPERAND (arg1, 0));
+ return fold_build2 (MINUS_EXPR, type,
+ fold_convert (type, arg0),
+ fold_convert (type, TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
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));
+ return fold_build2 (MINUS_EXPR, type,
+ fold_convert (type, arg1),
+ fold_convert (type, TREE_OPERAND (arg0, 0)));
/* Convert ~A + 1 to -A. */
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (arg0) == BIT_NOT_EXPR
fold_build2 (PLUS_EXPR, type,
fold_convert (type, alt0),
fold_convert (type, alt1)),
- same);
+ fold_convert (type, same));
}
/* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
of the array. Loop optimizer sometimes produce this type of
expressions. */
- if (TREE_CODE (arg0) == ADDR_EXPR
- && TREE_CODE (arg1) == MULT_EXPR)
+ if (TREE_CODE (arg0) == ADDR_EXPR)
{
tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
if (tem)
return fold_convert (type, fold (tem));
}
- else if (TREE_CODE (arg1) == ADDR_EXPR
- && TREE_CODE (arg0) == MULT_EXPR)
+ else if (TREE_CODE (arg1) == ADDR_EXPR)
{
tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
if (tem)
fold_convert (type, tem));
}
+ if (flag_unsafe_math_optimizations
+ && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
+ && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
+ && (tem = distribute_real_division (code, type, arg0, arg1)))
+ return tem;
+
/* Convert x+x into x*2.0. */
if (operand_equal_p (arg0, arg1, 0)
&& SCALAR_FLOAT_TYPE_P (type))
&& ptr_difference_const (arg0, arg1, &diff))
return build_int_cst_type (type, diff);
}
-
+
+ /* Fold &a[i] - &a[j] to i-j. */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF
+ && TREE_CODE (arg1) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == ARRAY_REF)
+ {
+ tree aref0 = TREE_OPERAND (arg0, 0);
+ tree aref1 = TREE_OPERAND (arg1, 0);
+ if (operand_equal_p (TREE_OPERAND (aref0, 0),
+ TREE_OPERAND (aref1, 0), 0))
+ {
+ tree op0 = fold_convert (type, TREE_OPERAND (aref0, 1));
+ tree op1 = fold_convert (type, TREE_OPERAND (aref1, 1));
+ tree esz = array_ref_element_size (aref0);
+ tree diff = build2 (MINUS_EXPR, type, op0, op1);
+ return fold_build2 (MULT_EXPR, type, diff,
+ fold_convert (type, esz));
+
+ }
+ }
+
/* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
of the array. Loop optimizer sometimes produce this type of
expressions. */
- if (TREE_CODE (arg0) == ADDR_EXPR
- && TREE_CODE (arg1) == MULT_EXPR)
+ if (TREE_CODE (arg0) == ADDR_EXPR)
{
tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
if (tem)
return fold_convert (type, fold (tem));
}
+ if (flag_unsafe_math_optimizations
+ && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
+ && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
+ && (tem = distribute_real_division (code, type, arg0, arg1)))
+ return tem;
+
if (TREE_CODE (arg0) == MULT_EXPR
&& TREE_CODE (arg1) == MULT_EXPR
&& (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
goto bit_ior;
}
+ /* Convert ~X ^ ~Y to X ^ Y. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ && TREE_CODE (arg1) == BIT_NOT_EXPR)
+ return fold_build2 (code, type,
+ fold_convert (type, TREE_OPERAND (arg0, 0)),
+ fold_convert (type, TREE_OPERAND (arg1, 0)));
+
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
if (code == TRUNC_MOD_EXPR
&& !TYPE_UNSIGNED (type)
&& TREE_CODE (arg1) == INTEGER_CST
+ && !TREE_CONSTANT_OVERFLOW (arg1)
&& TREE_INT_CST_HIGH (arg1) < 0
&& !flag_trapv
/* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
- case GE_EXPR:
+ case GE_EXPR:
/* If one arg is a real or integer constant, put it last. */
if (tree_swap_operands_p (arg0, arg1, true))
- return fold_build2 (swap_tree_comparison (code), type, arg1, arg0);
+ return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+
+ /* bool_var != 0 becomes bool_var. */
+ if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
+ && code == NE_EXPR)
+ return non_lvalue (fold_convert (type, arg0));
+
+ /* bool_var == 1 becomes bool_var. */
+ if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
+ && code == EQ_EXPR)
+ return non_lvalue (fold_convert (type, arg0));
/* If this is an equality comparison of the address of a non-weak
object against zero, then we know the result. */
}
}
+ /* Transform comparisons of the form X +- C CMP X. */
+ if ((code != EQ_EXPR && code != NE_EXPR)
+ && (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+ && !HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))))
+ || (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && !TYPE_UNSIGNED (TREE_TYPE (arg1))
+ && !(flag_wrapv || flag_trapv))))
+ {
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ enum tree_code code0 = TREE_CODE (arg0);
+ int is_positive;
+
+ if (TREE_CODE (arg01) == REAL_CST)
+ is_positive = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg01)) ? -1 : 1;
+ else
+ is_positive = tree_int_cst_sgn (arg01);
+
+ /* (X - c) > X becomes false. */
+ if (code == GT_EXPR
+ && ((code0 == MINUS_EXPR && is_positive >= 0)
+ || (code0 == PLUS_EXPR && is_positive <= 0)))
+ return constant_boolean_node (0, type);
+
+ /* Likewise (X + c) < X becomes false. */
+ if (code == LT_EXPR
+ && ((code0 == PLUS_EXPR && is_positive >= 0)
+ || (code0 == MINUS_EXPR && is_positive <= 0)))
+ return constant_boolean_node (0, type);
+
+ /* Convert (X - c) <= X to true. */
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ && code == LE_EXPR
+ && ((code0 == MINUS_EXPR && is_positive >= 0)
+ || (code0 == PLUS_EXPR && is_positive <= 0)))
+ return constant_boolean_node (1, type);
+
+ /* Convert (X + c) >= X to true. */
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1)))
+ && code == GE_EXPR
+ && ((code0 == PLUS_EXPR && is_positive >= 0)
+ || (code0 == MINUS_EXPR && is_positive <= 0)))
+ return constant_boolean_node (1, type);
+
+ if (TREE_CODE (arg01) == INTEGER_CST)
+ {
+ /* Convert X + c > X and X - c < X to true for integers. */
+ if (code == GT_EXPR
+ && ((code0 == PLUS_EXPR && is_positive > 0)
+ || (code0 == MINUS_EXPR && is_positive < 0)))
+ return constant_boolean_node (1, type);
+
+ if (code == LT_EXPR
+ && ((code0 == MINUS_EXPR && is_positive > 0)
+ || (code0 == PLUS_EXPR && is_positive < 0)))
+ return constant_boolean_node (1, type);
+
+ /* Convert X + c <= X and X - c >= X to false for integers. */
+ if (code == LE_EXPR
+ && ((code0 == PLUS_EXPR && is_positive > 0)
+ || (code0 == MINUS_EXPR && is_positive < 0)))
+ return constant_boolean_node (0, type);
+
+ if (code == GE_EXPR
+ && ((code0 == MINUS_EXPR && is_positive > 0)
+ || (code0 == PLUS_EXPR && is_positive < 0)))
+ return constant_boolean_node (0, type);
+ }
+ }
+
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree targ0 = strip_float_extensions (arg0);
arg0, fold_convert (TREE_TYPE (arg0),
integer_zero_node));
- /* If we have (A & C) != 0 or (A & C) == 0 and C is a power of
- 2, then fold the expression into shifts and logical operations. */
- tem = fold_single_bit_test (code, arg0, arg1, type);
+ /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
+ bit, then fold the expression into A < 0 or A >= 0. */
+ tem = fold_single_bit_test_into_sign_test (code, arg0, arg1, type);
if (tem)
return tem;
return t1;
}
+ /* Fold a comparison of the address of COMPONENT_REFs with the same
+ type and component to a comparison of the address of the base
+ object. In short, &x->a OP &y->a to x OP y and
+ &x->a OP &y.a to x OP &y */
+ if (TREE_CODE (arg0) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
+ && TREE_CODE (arg1) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
+ {
+ tree cref0 = TREE_OPERAND (arg0, 0);
+ tree cref1 = TREE_OPERAND (arg1, 0);
+ if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
+ {
+ tree op0 = TREE_OPERAND (cref0, 0);
+ tree op1 = TREE_OPERAND (cref1, 0);
+ return fold_build2 (code, type,
+ build_fold_addr_expr (op0),
+ build_fold_addr_expr (op1));
+ }
+ }
+
/* If this is a comparison of complex values and either or both sides
are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.
return build_complex (type, arg0, arg1);
return NULL_TREE;
+ case ASSERT_EXPR:
+ /* An ASSERT_EXPR should never be passed to fold_binary. */
+ gcc_unreachable ();
+
default:
return NULL_TREE;
} /* switch (code) */
}
+/* Callback for walk_tree, looking for LABEL_EXPR.
+ Returns tree TP if it is LABEL_EXPR. Otherwise it returns NULL_TREE.
+ Do not check the sub-tree of GOTO_EXPR. */
+
+static tree
+contains_label_1 (tree *tp,
+ int *walk_subtrees,
+ void *data ATTRIBUTE_UNUSED)
+{
+ switch (TREE_CODE (*tp))
+ {
+ case LABEL_EXPR:
+ return *tp;
+ case GOTO_EXPR:
+ *walk_subtrees = 0;
+ /* no break */
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* Checks whether the sub-tree ST contains a label LABEL_EXPR which is
+ accessible from outside the sub-tree. Returns NULL_TREE if no
+ addressable label is found. */
+
+static bool
+contains_label_p (tree st)
+{
+ return (walk_tree (&st, contains_label_1 , NULL, NULL) != NULL_TREE);
+}
+
/* Fold a ternary expression of code CODE and type TYPE with operands
OP0, OP1, and OP2. Return the folded expression if folding is
successful. Otherwise, return NULL_TREE. */
-static tree
+tree
fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
{
tree tem;
so all simple results must be passed through pedantic_non_lvalue. */
if (TREE_CODE (arg0) == INTEGER_CST)
{
+ tree unused_op = integer_zerop (arg0) ? op1 : op2;
tem = integer_zerop (arg0) ? op2 : op1;
/* 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))
+ away "c ? x : throw", where the throw has a void type.
+ Avoid throwing away that operand which contains label. */
+ if ((!TREE_SIDE_EFFECTS (unused_op)
+ || !contains_label_p (unused_op))
+ && (! VOID_TYPE_P (TREE_TYPE (tem))
+ || VOID_TYPE_P (type)))
return pedantic_non_lvalue (tem);
return NULL_TREE;
}
case CONST_DECL:
return fold (DECL_INITIAL (t));
- case ASSERT_EXPR:
- {
- /* Given ASSERT_EXPR <Y, COND>, return Y if COND can be folded
- to boolean_true_node. If COND folds to boolean_false_node,
- return ASSERT_EXPR <Y, 0>. Otherwise, return the original
- expression. */
- tree c = fold (ASSERT_EXPR_COND (t));
- if (c == boolean_true_node)
- return ASSERT_EXPR_VAR (t);
- else if (c == boolean_false_node)
- return build (ASSERT_EXPR, TREE_TYPE (t), ASSERT_EXPR_VAR (t), c);
- else
- return t;
- }
-
default:
return t;
} /* switch (code) */