/* 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, 2005 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
switch (TREE_CODE (type))
{
- case INTEGER_TYPE: case CHAR_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
case OFFSET_TYPE:
if (TREE_CODE (arg) == INTEGER_CST)
switch (TREE_CODE (orig))
{
- case INTEGER_TYPE: case CHAR_TYPE:
+ case INTEGER_TYPE:
case BOOLEAN_TYPE: case ENUMERAL_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
return fold_build1 (FLOAT_EXPR, type, arg);
case COMPLEX_TYPE:
switch (TREE_CODE (orig))
{
- case INTEGER_TYPE: case CHAR_TYPE:
+ case INTEGER_TYPE:
case BOOLEAN_TYPE: case ENUMERAL_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
case REAL_TYPE:
{
case INTEGER_TYPE:
case ENUMERAL_TYPE:
- case CHAR_TYPE:
/* There is no requirement that LOW be within the range of ETYPE
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */
break;
/* FALLTHROUGH */
case INTEGER_TYPE:
- case CHAR_TYPE:
if (tree_int_cst_equal (low0,
TYPE_MIN_VALUE (TREE_TYPE (low0))))
low0 = 0;
break;
/* FALLTHROUGH */
case INTEGER_TYPE:
- case CHAR_TYPE:
if (tree_int_cst_equal (high1,
TYPE_MAX_VALUE (TREE_TYPE (high1))))
high1 = 0;
case LT_EXPR:
if (TREE_OVERFLOW (lo))
- return omit_one_operand (type, integer_zero_node, arg00);
+ return omit_one_operand (type, integer_one_node, arg00);
return fold_build2 (LT_EXPR, type, arg00, lo);
case LE_EXPR:
case GE_EXPR:
if (TREE_OVERFLOW (lo))
- return omit_one_operand (type, integer_one_node, arg00);
+ return omit_one_operand (type, integer_zero_node, arg00);
return fold_build2 (GE_EXPR, type, arg00, lo);
default:
}
/* Fold a binary expression of code CODE and type TYPE with operands
+ OP0 and OP1, containing either a MIN-MAX or a MAX-MIN combination.
+ Return the folded expression if folding is successful. Otherwise,
+ return NULL_TREE. */
+
+static tree
+fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
+{
+ enum tree_code compl_code;
+
+ if (code == MIN_EXPR)
+ compl_code = MAX_EXPR;
+ else if (code == MAX_EXPR)
+ compl_code = MIN_EXPR;
+ else
+ gcc_unreachable ();
+
+ /* MIN (MAX (a, b), b) == b. */
+ if (TREE_CODE (op0) == compl_code
+ && operand_equal_p (TREE_OPERAND (op0, 1), op1, 0))
+ return omit_one_operand (type, op1, TREE_OPERAND (op0, 0));
+
+ /* MIN (MAX (b, a), b) == b. */
+ if (TREE_CODE (op0) == compl_code
+ && operand_equal_p (TREE_OPERAND (op0, 0), op1, 0)
+ && reorder_operands_p (TREE_OPERAND (op0, 1), op1))
+ return omit_one_operand (type, op1, TREE_OPERAND (op0, 1));
+
+ /* MIN (a, MAX (a, b)) == a. */
+ if (TREE_CODE (op1) == compl_code
+ && operand_equal_p (op0, TREE_OPERAND (op1, 0), 0)
+ && reorder_operands_p (op0, TREE_OPERAND (op1, 1)))
+ return omit_one_operand (type, op0, TREE_OPERAND (op1, 1));
+
+ /* MIN (a, MAX (b, a)) == a. */
+ if (TREE_CODE (op1) == compl_code
+ && operand_equal_p (op0, TREE_OPERAND (op1, 1), 0)
+ && reorder_operands_p (op0, TREE_OPERAND (op1, 0)))
+ return omit_one_operand (type, op0, TREE_OPERAND (op1, 0));
+
+ return NULL_TREE;
+}
+
+/* Subroutine of fold_binary. This routine performs all of the
+ transformations that are common to the equality/inequality
+ operators (EQ_EXPR and NE_EXPR) and the ordering operators
+ (LT_EXPR, LE_EXPR, GE_EXPR and GT_EXPR). Callers other than
+ fold_binary should call fold_binary. Fold a comparison with
+ tree code CODE and type TYPE with operands OP0 and OP1. Return
+ the folded comparison or NULL_TREE. */
+
+static tree
+fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
+{
+ tree arg0, arg1, tem;
+
+ arg0 = op0;
+ arg1 = op1;
+
+ STRIP_SIGN_NOPS (arg0);
+ STRIP_SIGN_NOPS (arg1);
+
+ tem = fold_relational_const (code, type, arg0, arg1);
+ if (tem != NULL_TREE)
+ return tem;
+
+ /* 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, op1, op0);
+
+ /* 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. */
+ {
+ tree base0, offset0, base1, offset1;
+
+ if (extract_array_ref (arg0, &base0, &offset0)
+ && extract_array_ref (arg1, &base1, &offset1)
+ && operand_equal_p (base0, base1, 0))
+ {
+ /* Handle no offsets on both sides specially. */
+ if (offset0 == NULL_TREE && offset1 == NULL_TREE)
+ return fold_build2 (code, type, integer_zero_node,
+ integer_zero_node);
+
+ if (!offset0 || !offset1
+ || TREE_TYPE (offset0) == TREE_TYPE (offset1))
+ {
+ if (offset0 == NULL_TREE)
+ offset0 = build_int_cst (TREE_TYPE (offset1), 0);
+ if (offset1 == NULL_TREE)
+ offset1 = build_int_cst (TREE_TYPE (offset0), 0);
+ return fold_build2 (code, type, offset0, offset1);
+ }
+ }
+ }
+
+ /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1. */
+ if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+ && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
+ && !TYPE_UNSIGNED (TREE_TYPE (arg1))
+ && !(flag_wrapv || flag_trapv))
+ && (TREE_CODE (arg1) == INTEGER_CST
+ && !TREE_OVERFLOW (arg1)))
+ {
+ tree const1 = TREE_OPERAND (arg0, 1);
+ tree const2 = arg1;
+ tree variable = TREE_OPERAND (arg0, 0);
+ tree lhs;
+ int lhs_add;
+ lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
+
+ lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
+ TREE_TYPE (arg1), const2, const1);
+ if (TREE_CODE (lhs) == TREE_CODE (arg1)
+ && (TREE_CODE (lhs) != INTEGER_CST
+ || !TREE_OVERFLOW (lhs)))
+ return fold_build2 (code, type, variable, lhs);
+ }
+
+ if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
+ {
+ 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);
+
+ /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
+ if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+ return fold_build2 (code, type, fold_convert (newtype, targ0),
+ fold_convert (newtype, targ1));
+
+ /* (-a) CMP (-b) -> b CMP a */
+ if (TREE_CODE (arg0) == NEGATE_EXPR
+ && TREE_CODE (arg1) == NEGATE_EXPR)
+ return fold_build2 (code, type, TREE_OPERAND (arg1, 0),
+ TREE_OPERAND (arg0, 0));
+
+ if (TREE_CODE (arg1) == REAL_CST)
+ {
+ REAL_VALUE_TYPE cst;
+ cst = TREE_REAL_CST (arg1);
+
+ /* (-a) CMP CST -> a swap(CMP) (-CST) */
+ if (TREE_CODE (arg0) == NEGATE_EXPR)
+ return fold_build2 (swap_tree_comparison (code), type,
+ TREE_OPERAND (arg0, 0),
+ build_real (TREE_TYPE (arg1),
+ REAL_VALUE_NEGATE (cst)));
+
+ /* IEEE doesn't distinguish +0 and -0 in comparisons. */
+ /* a CMP (-0) -> a CMP 0 */
+ if (REAL_VALUE_MINUS_ZERO (cst))
+ return fold_build2 (code, type, arg0,
+ build_real (TREE_TYPE (arg1), dconst0));
+
+ /* x != NaN is always true, other ops are always false. */
+ if (REAL_VALUE_ISNAN (cst)
+ && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
+ {
+ tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
+ return omit_one_operand (type, tem, arg0);
+ }
+
+ /* Fold comparisons against infinity. */
+ if (REAL_VALUE_ISINF (cst))
+ {
+ tem = fold_inf_compare (code, type, arg0, arg1);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+ }
+
+ /* If this is a comparison of a real constant with a PLUS_EXPR
+ or a MINUS_EXPR of a real constant, we can convert it into a
+ comparison with a revised real constant as long as no overflow
+ occurs when unsafe_math_optimizations are enabled. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == REAL_CST
+ && (TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+ && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+ ? MINUS_EXPR : PLUS_EXPR,
+ arg1, TREE_OPERAND (arg0, 1), 0))
+ && ! TREE_CONSTANT_OVERFLOW (tem))
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+ /* Likewise, we can simplify a comparison of a real constant with
+ a MINUS_EXPR whose first operand is also a real constant, i.e.
+ (c1 - x) < c2 becomes x > c1-c2. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == REAL_CST
+ && TREE_CODE (arg0) == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
+ && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
+ arg1, 0))
+ && ! TREE_CONSTANT_OVERFLOW (tem))
+ return fold_build2 (swap_tree_comparison (code), type,
+ TREE_OPERAND (arg0, 1), tem);
+
+ /* Fold comparisons against built-in math functions. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && flag_unsafe_math_optimizations
+ && ! flag_errno_math)
+ {
+ enum built_in_function fcode = builtin_mathfn_code (arg0);
+
+ if (fcode != END_BUILTINS)
+ {
+ tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+ }
+ }
+
+ /* Convert foo++ == CONST into ++foo == CONST + INCR. */
+ if (TREE_CONSTANT (arg1)
+ && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
+ || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
+ /* This optimization is invalid for ordered comparisons
+ if CONST+INCR overflows or if foo+incr might overflow.
+ This optimization is invalid for floating point due to rounding.
+ For pointer types we assume overflow doesn't happen. */
+ && (POINTER_TYPE_P (TREE_TYPE (arg0))
+ || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+ && (code == EQ_EXPR || code == NE_EXPR))))
+ {
+ tree varop, newconst;
+
+ if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
+ {
+ newconst = fold_build2 (PLUS_EXPR, TREE_TYPE (arg0),
+ arg1, TREE_OPERAND (arg0, 1));
+ varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ }
+ else
+ {
+ newconst = fold_build2 (MINUS_EXPR, TREE_TYPE (arg0),
+ arg1, TREE_OPERAND (arg0, 1));
+ varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ }
+
+
+ /* 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))
+ && host_integerp (DECL_SIZE (TREE_OPERAND
+ (TREE_OPERAND (varop, 0), 1)), 1))
+ {
+ tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
+ 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);
+ if (TREE_CODE (folded_compare) == INTEGER_CST)
+ return omit_one_operand (type, folded_compare, varop);
+
+ shift = build_int_cst (NULL_TREE,
+ TYPE_PRECISION (TREE_TYPE (varop)) - size);
+ 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),
+ newconst, shift);
+ }
+
+ return fold_build2 (code, type, varop, newconst);
+ }
+
+ if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
+ && (TREE_CODE (arg0) == NOP_EXPR
+ || TREE_CODE (arg0) == CONVERT_EXPR))
+ {
+ /* If we are widening one operand of an integer comparison,
+ see if the other operand is similarly being widened. Perhaps we
+ can do the comparison in the narrower type. */
+ tem = fold_widened_comparison (code, type, arg0, arg1);
+ if (tem)
+ return tem;
+
+ /* Or if we are changing signedness. */
+ tem = fold_sign_changed_comparison (code, type, arg0, arg1);
+ if (tem)
+ return tem;
+ }
+
+ /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
+ constant, we can simplify it. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && (TREE_CODE (arg0) == MIN_EXPR
+ || TREE_CODE (arg0) == MAX_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ {
+ tem = optimize_minmax_comparison (code, type, op0, op1);
+ if (tem)
+ return tem;
+ }
+
+ /* Simplify comparison of something with itself. (For IEEE
+ floating-point, we can only do some of these simplifications.) */
+ if (operand_equal_p (arg0, arg1, 0))
+ {
+ switch (code)
+ {
+ case EQ_EXPR:
+ if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+ || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ return constant_boolean_node (1, type);
+ break;
+
+ case GE_EXPR:
+ case LE_EXPR:
+ if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
+ || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ return constant_boolean_node (1, type);
+ return fold_build2 (EQ_EXPR, type, arg0, arg1);
+
+ case NE_EXPR:
+ /* For NE, we can only do this simplification if integer
+ or we don't honor IEEE floating point NaNs. */
+ if (FLOAT_TYPE_P (TREE_TYPE (arg0))
+ && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+ break;
+ /* ... fall through ... */
+ case GT_EXPR:
+ case LT_EXPR:
+ return constant_boolean_node (0, type);
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ /* If we are comparing an expression that just has comparisons
+ of two integer values, arithmetic expressions of those comparisons,
+ and constants, we can simplify it. There are only three cases
+ to check: the two values can either be equal, the first can be
+ greater, or the second can be greater. Fold the expression for
+ those three values. Since each value must be 0 or 1, we have
+ eight possibilities, each of which corresponds to the constant 0
+ or 1 or one of the six possible comparisons.
+
+ This handles common cases like (a > b) == 0 but also handles
+ expressions like ((x > y) - (y > x)) > 0, which supposedly
+ occur in macroized code. */
+
+ if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST)
+ {
+ tree cval1 = 0, cval2 = 0;
+ int save_p = 0;
+
+ if (twoval_comparison_p (arg0, &cval1, &cval2, &save_p)
+ /* Don't handle degenerate cases here; they should already
+ have been handled anyway. */
+ && cval1 != 0 && cval2 != 0
+ && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
+ && TREE_TYPE (cval1) == TREE_TYPE (cval2)
+ && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
+ && TYPE_MAX_VALUE (TREE_TYPE (cval1))
+ && TYPE_MAX_VALUE (TREE_TYPE (cval2))
+ && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
+ TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
+ {
+ tree maxval = TYPE_MAX_VALUE (TREE_TYPE (cval1));
+ tree minval = TYPE_MIN_VALUE (TREE_TYPE (cval1));
+
+ /* We can't just pass T to eval_subst in case cval1 or cval2
+ was the same as ARG1. */
+
+ tree high_result
+ = fold_build2 (code, type,
+ eval_subst (arg0, cval1, maxval,
+ cval2, minval),
+ arg1);
+ tree equal_result
+ = fold_build2 (code, type,
+ eval_subst (arg0, cval1, maxval,
+ cval2, maxval),
+ arg1);
+ tree low_result
+ = fold_build2 (code, type,
+ eval_subst (arg0, cval1, minval,
+ cval2, maxval),
+ arg1);
+
+ /* All three of these results should be 0 or 1. Confirm they are.
+ Then use those values to select the proper code to use. */
+
+ if (TREE_CODE (high_result) == INTEGER_CST
+ && TREE_CODE (equal_result) == INTEGER_CST
+ && TREE_CODE (low_result) == INTEGER_CST)
+ {
+ /* Make a 3-bit mask with the high-order bit being the
+ value for `>', the next for '=', and the low for '<'. */
+ switch ((integer_onep (high_result) * 4)
+ + (integer_onep (equal_result) * 2)
+ + integer_onep (low_result))
+ {
+ case 0:
+ /* Always false. */
+ return omit_one_operand (type, integer_zero_node, arg0);
+ case 1:
+ code = LT_EXPR;
+ break;
+ case 2:
+ code = EQ_EXPR;
+ break;
+ case 3:
+ code = LE_EXPR;
+ break;
+ case 4:
+ code = GT_EXPR;
+ break;
+ case 5:
+ code = NE_EXPR;
+ break;
+ case 6:
+ code = GE_EXPR;
+ break;
+ case 7:
+ /* Always true. */
+ return omit_one_operand (type, integer_one_node, arg0);
+ }
+
+ if (save_p)
+ return save_expr (build2 (code, type, cval1, cval2));
+ return fold_build2 (code, type, cval1, cval2);
+ }
+ }
+ }
+
+ /* 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));
+ }
+ }
+
+ /* 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))
+ {
+ tem = fold_div_compare (code, type, arg0, arg1);
+ if (tem != NULL_TREE)
+ return tem;
+ }
+
+ return NULL_TREE;
+}
+
+/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. Return the folded expression if folding is
successful. Otherwise, return NULL_TREE. */
tree
fold_binary (enum tree_code code, tree type, tree op0, tree op1)
{
- tree t1 = NULL_TREE;
- tree tem;
- tree arg0 = NULL_TREE, arg1 = NULL_TREE;
enum tree_code_class kind = TREE_CODE_CLASS (code);
+ tree arg0, arg1, tem;
+ tree t1 = NULL_TREE;
gcc_assert (IS_EXPR_CODE_CLASS (kind)
&& TREE_CODE_LENGTH (code) == 2
return omit_one_operand (type, t1, arg0);
}
+ /* Canonicalize (X & C1) | C2. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ {
+ unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi;
+ int width = TYPE_PRECISION (type);
+ hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1));
+ lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1));
+ hi2 = TREE_INT_CST_HIGH (arg1);
+ lo2 = TREE_INT_CST_LOW (arg1);
+
+ /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */
+ if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+ return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+
+ if (width > HOST_BITS_PER_WIDE_INT)
+ {
+ mhi = (unsigned HOST_WIDE_INT) -1
+ >> (2 * HOST_BITS_PER_WIDE_INT - width);
+ mlo = -1;
+ }
+ else
+ {
+ mhi = 0;
+ mlo = (unsigned HOST_WIDE_INT) -1
+ >> (HOST_BITS_PER_WIDE_INT - width);
+ }
+
+ /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */
+ if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+ return fold_build2 (BIT_IOR_EXPR, type,
+ TREE_OPERAND (arg0, 0), arg1);
+
+ /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2. */
+ hi1 &= mhi;
+ lo1 &= mlo;
+ if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1)
+ return fold_build2 (BIT_IOR_EXPR, type,
+ fold_build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 0),
+ build_int_cst_wide (type,
+ lo1 & ~lo2,
+ hi1 & ~hi2)),
+ arg1);
+ }
+
+ /* (X & Y) | Y is (X, Y). */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+ return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+ /* (X & Y) | X is (Y, X). */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+ return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+ /* X | (X & Y) is (Y, X). */
+ if (TREE_CODE (arg1) == BIT_AND_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
+ return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+ /* X | (Y & X) is (Y, X). */
+ if (TREE_CODE (arg1) == BIT_AND_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+ return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand (type, integer_zero_node, arg0);
+ /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2). */
+ if (TREE_CODE (arg0) == BIT_IOR_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ return fold_build2 (BIT_IOR_EXPR, type,
+ fold_build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 0), arg1),
+ fold_build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 1), arg1));
+
+ /* (X | Y) & Y is (X, Y). */
+ if (TREE_CODE (arg0) == BIT_IOR_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+ return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 0));
+ /* (X | Y) & X is (Y, X). */
+ if (TREE_CODE (arg0) == BIT_IOR_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+ return omit_one_operand (type, arg1, TREE_OPERAND (arg0, 1));
+ /* X & (X | Y) is (Y, X). */
+ if (TREE_CODE (arg1) == BIT_IOR_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 1)))
+ return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 1));
+ /* X & (Y | X) is (Y, X). */
+ if (TREE_CODE (arg1) == BIT_IOR_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
+ && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+ return omit_one_operand (type, arg0, TREE_OPERAND (arg1, 0));
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
if (INTEGRAL_TYPE_P (type)
&& operand_equal_p (arg1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
return omit_one_operand (type, arg1, arg0);
+ tem = fold_minmax (MIN_EXPR, type, arg0, arg1);
+ if (tem)
+ return tem;
goto associate;
case MAX_EXPR:
&& TYPE_MAX_VALUE (type)
&& operand_equal_p (arg1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
return omit_one_operand (type, arg1, arg0);
+ tem = fold_minmax (MAX_EXPR, type, arg0, arg1);
+ if (tem)
+ return tem;
goto associate;
case TRUTH_ANDIF_EXPR:
case EQ_EXPR:
case NE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- case LE_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, op1, op0);
+ tem = fold_comparison (code, type, op0, op1);
+ if (tem != NULL_TREE)
+ return tem;
- /* ~a != C becomes a != ~C where C is a constant. Likewise for ==. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR && TREE_CODE (arg1) == INTEGER_CST
- && (code == NE_EXPR || code == EQ_EXPR))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
- fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
- arg1));
-
/* 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)
&& code == EQ_EXPR)
return fold_build1 (TRUTH_NOT_EXPR, type, arg0);
+ /* ~a != C becomes a != ~C where C is a constant. Likewise for ==. */
+ if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST)
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+ fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1),
+ arg1));
+
/* If this is an equality comparison of the address of a non-weak
object against zero, then we know the result. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ADDR_EXPR
+ if (TREE_CODE (arg0) == ADDR_EXPR
&& VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
&& ! DECL_WEAK (TREE_OPERAND (arg0, 0))
&& integer_zerop (arg1))
/* If this is an equality comparison of the address of two non-weak,
unaliased symbols neither of which are extern (since we do not
have access to attributes for externs), then we know the result. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == ADDR_EXPR
+ if (TREE_CODE (arg0) == ADDR_EXPR
&& VAR_OR_FUNCTION_DECL_P (TREE_OPERAND (arg0, 0))
&& ! DECL_WEAK (TREE_OPERAND (arg0, 0))
&& ! lookup_attribute ("alias",
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 (TREE_CODE_CLASS (code) == tcc_comparison)
- {
- tree base0, offset0, base1, offset1;
-
- if (extract_array_ref (arg0, &base0, &offset0)
- && extract_array_ref (arg1, &base1, &offset1)
- && operand_equal_p (base0, base1, 0))
- {
- /* Handle no offsets on both sides specially. */
- if (offset0 == NULL_TREE
- && offset1 == NULL_TREE)
- return fold_build2 (code, type, integer_zero_node,
- integer_zero_node);
-
- if (!offset0 || !offset1
- || TREE_TYPE (offset0) == TREE_TYPE (offset1))
- {
- if (offset0 == NULL_TREE)
- offset0 = build_int_cst (TREE_TYPE (offset1), 0);
- if (offset1 == NULL_TREE)
- offset1 = build_int_cst (TREE_TYPE (offset0), 0);
- return fold_build2 (code, type, offset0, offset1);
- }
- }
- }
-
- /* 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)
+ /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
+ a MINUS_EXPR of a constant, we can convert it into a comparison with
+ a revised constant as long as no overflow occurs. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && (TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+ ? MINUS_EXPR : PLUS_EXPR,
+ arg1, TREE_OPERAND (arg0, 1), 0))
+ && ! TREE_CONSTANT_OVERFLOW (tem))
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+ /* Similarly for a NEGATE_EXPR. */
+ if (TREE_CODE (arg0) == NEGATE_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && 0 != (tem = negate_expr (arg1))
+ && TREE_CODE (tem) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (tem))
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
+
+ /* If we have X - Y == 0, we can convert that to X == Y and similarly
+ for !=. Don't do this for ordered comparisons due to overflow. */
+ if (TREE_CODE (arg0) == MINUS_EXPR
+ && integer_zerop (arg1))
+ return fold_build2 (code, type,
+ TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
+
+ /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
+ if (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
+ on machines that have only two-operand insns or on which a
+ constant cannot be the first operand. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_zerop (arg1))
+ {
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ if (TREE_CODE (arg00) == LSHIFT_EXPR
+ && integer_onep (TREE_OPERAND (arg00, 0)))
+ return
+ fold_build2 (code, type,
+ build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
+ arg01, TREE_OPERAND (arg00, 1)),
+ fold_convert (TREE_TYPE (arg0),
+ integer_one_node)),
+ arg1);
+ else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
+ && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
+ return
+ fold_build2 (code, type,
+ build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
+ arg00, TREE_OPERAND (arg01, 1)),
+ fold_convert (TREE_TYPE (arg0),
+ integer_one_node)),
+ arg1);
+ }
+
+ /* If this is an NE or EQ comparison of zero against the result of a
+ signed MOD operation whose second operand is a power of 2, make
+ the MOD operation unsigned since it is simpler and equivalent. */
+ if (integer_zerop (arg1)
+ && !TYPE_UNSIGNED (TREE_TYPE (arg0))
+ && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
+ || TREE_CODE (arg0) == CEIL_MOD_EXPR
+ || TREE_CODE (arg0) == FLOOR_MOD_EXPR
+ || TREE_CODE (arg0) == ROUND_MOD_EXPR)
+ && integer_pow2p (TREE_OPERAND (arg0, 1)))
+ {
+ tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
+ tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 0)),
+ fold_convert (newtype,
+ TREE_OPERAND (arg0, 1)));
+
+ return fold_build2 (code, type, newmod,
+ fold_convert (newtype, arg1));
+ }
+
+ /* Fold ((X >> C1) & C2) == 0 and ((X >> C1) & C2) != 0 where
+ C1 is a valid shift constant, and C2 is a power of two, i.e.
+ a single bit. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == RSHIFT_EXPR
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
+ == INTEGER_CST
+ && integer_pow2p (TREE_OPERAND (arg0, 1))
+ && integer_zerop (arg1))
+ {
+ tree itype = TREE_TYPE (arg0);
+ unsigned HOST_WIDE_INT prec = TYPE_PRECISION (itype);
+ tree arg001 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
+
+ /* Check for a valid shift count. */
+ if (TREE_INT_CST_HIGH (arg001) == 0
+ && TREE_INT_CST_LOW (arg001) < prec)
+ {
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ unsigned HOST_WIDE_INT log2 = tree_log2 (arg01);
+ /* If (C2 << C1) doesn't overflow, then ((X >> C1) & C2) != 0
+ can be rewritten as (X & (C2 << C1)) != 0. */
+ if ((log2 + TREE_INT_CST_LOW (arg01)) < prec)
+ {
+ tem = fold_build2 (LSHIFT_EXPR, itype, arg01, arg001);
+ tem = fold_build2 (BIT_AND_EXPR, itype, arg000, tem);
+ return fold_build2 (code, type, tem, arg1);
+ }
+ /* Otherwise, for signed (arithmetic) shifts,
+ ((X >> C1) & C2) != 0 is rewritten as X < 0, and
+ ((X >> C1) & C2) == 0 is rewritten as X >= 0. */
+ else if (!TYPE_UNSIGNED (itype))
+ return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+ arg000, build_int_cst (itype, 0));
+ /* Otherwise, of unsigned (logical) shifts,
+ ((X >> C1) & C2) != 0 is rewritten as (X,false), and
+ ((X >> C1) & C2) == 0 is rewritten as (X,true). */
+ else
+ return omit_one_operand (type,
+ code == EQ_EXPR ? integer_one_node
+ : integer_zero_node,
+ arg000);
+ }
+ }
+
+ /* If this is an NE comparison of zero with an AND of one, remove the
+ comparison since the AND will give the correct value. */
+ if (code == NE_EXPR
+ && integer_zerop (arg1)
+ && TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1)))
+ return fold_convert (type, arg0);
+
+ /* If we have (A & C) == C where C is a power of 2, convert this into
+ (A & C) != 0. Similarly for NE_EXPR. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_pow2p (TREE_OPERAND (arg0, 1))
+ && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+ return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ arg0, fold_convert (TREE_TYPE (arg0),
+ integer_zero_node));
+
+ /* 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;
+
+ /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
+ Similarly for NE_EXPR. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ {
+ tree notc = fold_build1 (BIT_NOT_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 1)),
+ TREE_OPERAND (arg0, 1));
+ tree dandnotc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ arg1, notc);
+ tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+ if (integer_nonzerop (dandnotc))
+ return omit_one_operand (type, rslt, arg0);
+ }
+
+ /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
+ Similarly for NE_EXPR. */
+ if (TREE_CODE (arg0) == BIT_IOR_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ {
+ tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
+ tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (arg0, 1), notd);
+ tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
+ if (integer_nonzerop (candnotd))
+ return omit_one_operand (type, rslt, arg0);
+ }
+
+ /* If this is a comparison of a field, we may be able to simplify it. */
+ if (((TREE_CODE (arg0) == COMPONENT_REF
+ && lang_hooks.can_use_bit_fields_p ())
+ || TREE_CODE (arg0) == BIT_FIELD_REF)
+ /* Handle the constant case even without -O
+ to make sure the warnings are given. */
+ && (optimize || TREE_CODE (arg1) == INTEGER_CST))
+ {
+ t1 = optimize_bit_field_compare (code, type, arg0, arg1);
+ if (t1)
+ return t1;
+ }
+
+ /* Optimize comparisons of strlen vs zero to a compare of the
+ first character of the string vs zero. To wit,
+ strlen(ptr) == 0 => *ptr == 0
+ strlen(ptr) != 0 => *ptr != 0
+ Other cases should reduce to one of these two (or a constant)
+ due to the return value of strlen being unsigned. */
+ if (TREE_CODE (arg0) == CALL_EXPR
+ && integer_zerop (arg1))
+ {
+ tree fndecl = get_callee_fndecl (arg0);
+ tree arglist;
+
+ if (fndecl
+ && 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))
+ {
+ tree iref = build_fold_indirect_ref (TREE_VALUE (arglist));
+ return fold_build2 (code, type, iref,
+ build_int_cst (TREE_TYPE (iref), 0));
+ }
+ }
+
+ /* Fold (X >> C) != 0 into X < 0 if C is one less than the width
+ of X. Similarly fold (X >> C) == 0 into X >= 0. */
+ if (TREE_CODE (arg0) == RSHIFT_EXPR
+ && integer_zerop (arg1)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ {
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree itype = TREE_TYPE (arg00);
+ if (TREE_INT_CST_HIGH (arg01) == 0
+ && TREE_INT_CST_LOW (arg01)
+ == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1))
+ {
+ if (TYPE_UNSIGNED (itype))
+ {
+ itype = lang_hooks.types.signed_type (itype);
+ arg00 = fold_convert (itype, arg00);
+ }
+ return fold_build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
+ type, arg00, build_int_cst (itype, 0));
+ }
+ }
+
+ /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */
+ if (integer_zerop (arg1)
+ && TREE_CODE (arg0) == BIT_XOR_EXPR)
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+
+ /* (X ^ Y) == Y becomes X == 0. We know that Y has no side-effects. */
+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+ build_int_cst (TREE_TYPE (arg1), 0));
+ /* Likewise (X ^ Y) == X becomes Y == 0. X has no side-effects. */
+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
+ && reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 1),
+ build_int_cst (TREE_TYPE (arg1), 0));
+
+ /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */
+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
+ fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg1),
+ TREE_OPERAND (arg0, 1), arg1));
+
+ if (integer_zerop (arg1)
+ && tree_expr_nonzero_p (arg0))
+ {
+ tree res = constant_boolean_node (code==NE_EXPR, type);
+ return omit_one_operand (type, res, arg0);
+ }
+ return NULL_TREE;
+
+ case LT_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ tem = fold_comparison (code, type, op0, op1);
+ if (tem != NULL_TREE)
+ return tem;
+
+ /* Transform comparisons of the form X +- C CMP X. */
+ if ((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))))
}
}
- /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1. */
- if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && !TYPE_UNSIGNED (TREE_TYPE (arg1))
- && !(flag_wrapv || flag_trapv))
- && (TREE_CODE (arg1) == INTEGER_CST
- && !TREE_OVERFLOW (arg1)))
- {
- tree const1 = TREE_OPERAND (arg0, 1);
- tree const2 = arg1;
- tree variable = TREE_OPERAND (arg0, 0);
- tree lhs;
- int lhs_add;
- lhs_add = TREE_CODE (arg0) != PLUS_EXPR;
-
- lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
- TREE_TYPE (arg1), const2, const1);
- if (TREE_CODE (lhs) == TREE_CODE (arg1)
- && (TREE_CODE (lhs) != INTEGER_CST
- || !TREE_OVERFLOW (lhs)))
- return fold_build2 (code, type, variable, lhs);
- }
-
- if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
- {
- 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);
-
- /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
- if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
- return fold_build2 (code, type, fold_convert (newtype, targ0),
- fold_convert (newtype, targ1));
-
- /* (-a) CMP (-b) -> b CMP a */
- if (TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == NEGATE_EXPR)
- return fold_build2 (code, type, TREE_OPERAND (arg1, 0),
- TREE_OPERAND (arg0, 0));
-
- if (TREE_CODE (arg1) == REAL_CST)
- {
- REAL_VALUE_TYPE cst;
- cst = TREE_REAL_CST (arg1);
-
- /* (-a) CMP CST -> a swap(CMP) (-CST) */
- if (TREE_CODE (arg0) == NEGATE_EXPR)
- return
- fold_build2 (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 0),
- build_real (TREE_TYPE (arg1),
- REAL_VALUE_NEGATE (cst)));
-
- /* IEEE doesn't distinguish +0 and -0 in comparisons. */
- /* a CMP (-0) -> a CMP 0 */
- if (REAL_VALUE_MINUS_ZERO (cst))
- return fold_build2 (code, type, arg0,
- build_real (TREE_TYPE (arg1), dconst0));
-
- /* x != NaN is always true, other ops are always false. */
- if (REAL_VALUE_ISNAN (cst)
- && ! HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg1))))
- {
- tem = (code == NE_EXPR) ? integer_one_node : integer_zero_node;
- return omit_one_operand (type, tem, arg0);
- }
-
- /* Fold comparisons against infinity. */
- if (REAL_VALUE_ISINF (cst))
- {
- tem = fold_inf_compare (code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
- }
-
- /* If this is a comparison of a real constant with a PLUS_EXPR
- or a MINUS_EXPR of a real constant, we can convert it into a
- comparison with a revised real constant as long as no overflow
- occurs when unsafe_math_optimizations are enabled. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == REAL_CST
- && (TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
- && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
- ? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1), 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
- /* Likewise, we can simplify a comparison of a real constant with
- a MINUS_EXPR whose first operand is also a real constant, i.e.
- (c1 - x) < c2 becomes x > c1-c2. */
- if (flag_unsafe_math_optimizations
- && TREE_CODE (arg1) == REAL_CST
- && TREE_CODE (arg0) == MINUS_EXPR
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST
- && 0 != (tem = const_binop (MINUS_EXPR, TREE_OPERAND (arg0, 0),
- arg1, 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold_build2 (swap_tree_comparison (code), type,
- TREE_OPERAND (arg0, 1), tem);
-
- /* Fold comparisons against built-in math functions. */
- if (TREE_CODE (arg1) == REAL_CST
- && flag_unsafe_math_optimizations
- && ! flag_errno_math)
- {
- enum built_in_function fcode = builtin_mathfn_code (arg0);
-
- if (fcode != END_BUILTINS)
- {
- tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
- if (tem != NULL_TREE)
- return tem;
- }
- }
- }
-
- /* Convert foo++ == CONST into ++foo == CONST + INCR. */
- if (TREE_CONSTANT (arg1)
- && (TREE_CODE (arg0) == POSTINCREMENT_EXPR
- || TREE_CODE (arg0) == POSTDECREMENT_EXPR)
- /* This optimization is invalid for ordered comparisons
- if CONST+INCR overflows or if foo+incr might overflow.
- This optimization is invalid for floating point due to rounding.
- For pointer types we assume overflow doesn't happen. */
- && (POINTER_TYPE_P (TREE_TYPE (arg0))
- || (INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- && (code == EQ_EXPR || code == NE_EXPR))))
- {
- tree varop, newconst;
-
- if (TREE_CODE (arg0) == POSTINCREMENT_EXPR)
- {
- newconst = fold_build2 (PLUS_EXPR, TREE_TYPE (arg0),
- arg1, TREE_OPERAND (arg0, 1));
- varop = build2 (PREINCREMENT_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- }
- else
- {
- newconst = fold_build2 (MINUS_EXPR, TREE_TYPE (arg0),
- arg1, TREE_OPERAND (arg0, 1));
- varop = build2 (PREDECREMENT_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg0, 1));
- }
-
-
- /* 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))
- && host_integerp (DECL_SIZE (TREE_OPERAND
- (TREE_OPERAND (varop, 0), 1)), 1))
- {
- tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
- 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);
- if (integer_zerop (folded_compare)
- || integer_onep (folded_compare))
- return omit_one_operand (type, folded_compare, varop);
-
- shift = build_int_cst (NULL_TREE,
- TYPE_PRECISION (TREE_TYPE (varop)) - size);
- 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),
- newconst, shift);
- }
-
- return fold_build2 (code, type, varop, newconst);
- }
-
/* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
This transformation affects the cases which are handled in later
optimizations involving comparisons with non-negative constants. */
&& TREE_CODE (arg0) != INTEGER_CST
&& tree_int_cst_sgn (arg1) > 0)
{
- switch (code)
+ if (code == GE_EXPR)
{
- case GE_EXPR:
arg1 = const_binop (MINUS_EXPR, arg1,
build_int_cst (TREE_TYPE (arg1), 1), 0);
return fold_build2 (GT_EXPR, type, arg0,
fold_convert (TREE_TYPE (arg0), arg1));
-
- case LT_EXPR:
+ }
+ if (code == LT_EXPR)
+ {
arg1 = const_binop (MINUS_EXPR, arg1,
build_int_cst (TREE_TYPE (arg1), 1), 0);
return fold_build2 (LE_EXPR, type, arg0,
fold_convert (TREE_TYPE (arg0), arg1));
-
- default:
- break;
}
}
return fold_build2 (EQ_EXPR, type, arg0, arg1);
default:
break;
- }
-
- else if (!in_gimple_form
- && 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)))
- {
- /* The following case also applies to X < signed_max+1
- and X >= signed_max+1 because previous transformations. */
- if (code == LE_EXPR || code == GT_EXPR)
- {
- tree st0, st1;
- st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
- st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
- return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
- type, fold_convert (st0, arg0),
- build_int_cst (st1, 0));
- }
- }
- }
- }
-
- /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
- a MINUS_EXPR of a constant, we can convert it into a comparison with
- a revised constant as long as no overflow occurs. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == PLUS_EXPR
- || TREE_CODE (arg0) == MINUS_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
- ? MINUS_EXPR : PLUS_EXPR,
- arg1, TREE_OPERAND (arg0, 1), 0))
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
- /* Similarly for a NEGATE_EXPR. */
- else if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == NEGATE_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = negate_expr (arg1))
- && TREE_CODE (tem) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (tem))
- return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);
-
- /* If we have X - Y == 0, we can convert that to X == Y and similarly
- for !=. Don't do this for ordered comparisons due to overflow. */
- else if ((code == NE_EXPR || code == EQ_EXPR)
- && integer_zerop (arg1) && TREE_CODE (arg0) == MINUS_EXPR)
- return fold_build2 (code, type,
- TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
-
- else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
- && (TREE_CODE (arg0) == NOP_EXPR
- || TREE_CODE (arg0) == CONVERT_EXPR))
- {
- /* If we are widening one operand of an integer comparison,
- see if the other operand is similarly being widened. Perhaps we
- can do the comparison in the narrower type. */
- tem = fold_widened_comparison (code, type, arg0, arg1);
- if (tem)
- return tem;
-
- /* Or if we are changing signedness. */
- tem = fold_sign_changed_comparison (code, type, arg0, arg1);
- if (tem)
- return tem;
- }
-
- /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
- constant, we can simplify it. */
- else if (TREE_CODE (arg1) == INTEGER_CST
- && (TREE_CODE (arg0) == MIN_EXPR
- || TREE_CODE (arg0) == MAX_EXPR)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tem = optimize_minmax_comparison (code, type, op0, op1);
- if (tem)
- return tem;
+ }
- return NULL_TREE;
- }
+ else if (!in_gimple_form
+ && 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)))
+ {
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ if (code == LE_EXPR || code == GT_EXPR)
+ {
+ tree st0, st1;
+ st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
+ st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
+ return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+ type, fold_convert (st0, arg0),
+ build_int_cst (st1, 0));
+ }
+ }
+ }
+ }
/* If we are comparing an ABS_EXPR with a constant, we can
convert all the cases into explicit comparisons, but they may
well not be faster than doing the ABS and one comparison.
But ABS (X) <= C is a range comparison, which becomes a subtraction
and a comparison, and is probably faster. */
- else if (code == LE_EXPR && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) == ABS_EXPR
- && ! TREE_SIDE_EFFECTS (arg0)
- && (0 != (tem = negate_expr (arg1)))
- && TREE_CODE (tem) == INTEGER_CST
- && ! TREE_CONSTANT_OVERFLOW (tem))
+ if (code == LE_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg0) == ABS_EXPR
+ && ! TREE_SIDE_EFFECTS (arg0)
+ && (0 != (tem = negate_expr (arg1)))
+ && TREE_CODE (tem) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (tem))
return fold_build2 (TRUTH_ANDIF_EXPR, type,
build2 (GE_EXPR, type,
TREE_OPERAND (arg0, 0), tem),
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))))
+ 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)))
+ 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
- on machines that have only two-operand insns or on which a
- constant cannot be the first operand. */
- if (integer_zerop (arg1) && (code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR)
- {
- tree arg00 = TREE_OPERAND (arg0, 0);
- tree arg01 = TREE_OPERAND (arg0, 1);
- if (TREE_CODE (arg00) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg00, 0)))
- return
- fold_build2 (code, type,
- build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg00),
- arg01, TREE_OPERAND (arg00, 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1);
- else if (TREE_CODE (TREE_OPERAND (arg0, 1)) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (TREE_OPERAND (arg0, 1), 0)))
- return
- fold_build2 (code, type,
- build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- build2 (RSHIFT_EXPR, TREE_TYPE (arg01),
- arg00, TREE_OPERAND (arg01, 1)),
- fold_convert (TREE_TYPE (arg0),
- integer_one_node)),
- arg1);
- }
-
- /* If this is an NE or EQ comparison of zero against the result of a
- signed MOD operation whose second operand is a power of 2, make
- the MOD operation unsigned since it is simpler and equivalent. */
- if ((code == NE_EXPR || code == EQ_EXPR)
- && integer_zerop (arg1)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg0) == TRUNC_MOD_EXPR
- || TREE_CODE (arg0) == CEIL_MOD_EXPR
- || TREE_CODE (arg0) == FLOOR_MOD_EXPR
- || TREE_CODE (arg0) == ROUND_MOD_EXPR)
- && integer_pow2p (TREE_OPERAND (arg0, 1)))
- {
- tree newtype = lang_hooks.types.unsigned_type (TREE_TYPE (arg0));
- tree newmod = fold_build2 (TREE_CODE (arg0), newtype,
- fold_convert (newtype,
- TREE_OPERAND (arg0, 0)),
- fold_convert (newtype,
- TREE_OPERAND (arg0, 1)));
-
- 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
- comparison since the AND will give the correct value. */
- if (code == NE_EXPR && integer_zerop (arg1)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_onep (TREE_OPERAND (arg0, 1)))
- return fold_convert (type, arg0);
-
- /* If we have (A & C) == C where C is a power of 2, convert this into
- (A & C) != 0. Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && integer_pow2p (TREE_OPERAND (arg0, 1))
- && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
- arg0, fold_convert (TREE_TYPE (arg0),
- integer_zero_node));
-
- /* 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;
-
- /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
- Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree notc = fold_build1 (BIT_NOT_EXPR,
- TREE_TYPE (TREE_OPERAND (arg0, 1)),
- TREE_OPERAND (arg0, 1));
- tree dandnotc = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- arg1, notc);
- tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
- if (integer_nonzerop (dandnotc))
- return omit_one_operand (type, rslt, arg0);
- }
-
- /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
- Similarly for NE_EXPR. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && TREE_CODE (arg0) == BIT_IOR_EXPR
- && TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
- {
- tree notd = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1);
- tree candnotd = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), notd);
- tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
- if (integer_nonzerop (candnotd))
- return omit_one_operand (type, rslt, arg0);
- }
-
/* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
and similarly for >= into !=. */
if ((code == LT_EXPR || code == GE_EXPR)
TREE_OPERAND (arg1, 1)),
build_int_cst (TREE_TYPE (arg0), 0));
- else if ((code == LT_EXPR || code == GE_EXPR)
- && TYPE_UNSIGNED (TREE_TYPE (arg0))
- && (TREE_CODE (arg1) == NOP_EXPR
- || TREE_CODE (arg1) == CONVERT_EXPR)
- && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
+ if ((code == LT_EXPR || code == GE_EXPR)
+ && TYPE_UNSIGNED (TREE_TYPE (arg0))
+ && (TREE_CODE (arg1) == NOP_EXPR
+ || TREE_CODE (arg1) == CONVERT_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
+ && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
return
build2 (code == LT_EXPR ? EQ_EXPR : NE_EXPR, type,
fold_convert (TREE_TYPE (arg0),
1))),
build_int_cst (TREE_TYPE (arg0), 0));
- /* Simplify comparison of something with itself. (For IEEE
- floating-point, we can only do some of these simplifications.) */
- if (operand_equal_p (arg0, arg1, 0))
- {
- switch (code)
- {
- case EQ_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
- return constant_boolean_node (1, type);
- break;
-
- case GE_EXPR:
- case LE_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
- return constant_boolean_node (1, type);
- return fold_build2 (EQ_EXPR, type, arg0, arg1);
-
- case NE_EXPR:
- /* For NE, we can only do this simplification if integer
- or we don't honor IEEE floating point NaNs. */
- if (FLOAT_TYPE_P (TREE_TYPE (arg0))
- && HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
- break;
- /* ... fall through ... */
- case GT_EXPR:
- case LT_EXPR:
- return constant_boolean_node (0, type);
- default:
- gcc_unreachable ();
- }
- }
-
- /* If we are comparing an expression that just has comparisons
- of two integer values, arithmetic expressions of those comparisons,
- and constants, we can simplify it. There are only three cases
- to check: the two values can either be equal, the first can be
- greater, or the second can be greater. Fold the expression for
- those three values. Since each value must be 0 or 1, we have
- eight possibilities, each of which corresponds to the constant 0
- or 1 or one of the six possible comparisons.
-
- This handles common cases like (a > b) == 0 but also handles
- expressions like ((x > y) - (y > x)) > 0, which supposedly
- occur in macroized code. */
-
- if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) != INTEGER_CST)
- {
- tree cval1 = 0, cval2 = 0;
- int save_p = 0;
-
- if (twoval_comparison_p (arg0, &cval1, &cval2, &save_p)
- /* Don't handle degenerate cases here; they should already
- have been handled anyway. */
- && cval1 != 0 && cval2 != 0
- && ! (TREE_CONSTANT (cval1) && TREE_CONSTANT (cval2))
- && TREE_TYPE (cval1) == TREE_TYPE (cval2)
- && INTEGRAL_TYPE_P (TREE_TYPE (cval1))
- && TYPE_MAX_VALUE (TREE_TYPE (cval1))
- && TYPE_MAX_VALUE (TREE_TYPE (cval2))
- && ! operand_equal_p (TYPE_MIN_VALUE (TREE_TYPE (cval1)),
- TYPE_MAX_VALUE (TREE_TYPE (cval2)), 0))
- {
- tree maxval = TYPE_MAX_VALUE (TREE_TYPE (cval1));
- tree minval = TYPE_MIN_VALUE (TREE_TYPE (cval1));
-
- /* We can't just pass T to eval_subst in case cval1 or cval2
- was the same as ARG1. */
-
- tree high_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, maxval,
- cval2, minval),
- arg1);
- tree equal_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, maxval,
- cval2, maxval),
- arg1);
- tree low_result
- = fold_build2 (code, type,
- eval_subst (arg0, cval1, minval,
- cval2, maxval),
- arg1);
-
- /* All three of these results should be 0 or 1. Confirm they
- are. Then use those values to select the proper code
- to use. */
-
- if ((integer_zerop (high_result)
- || integer_onep (high_result))
- && (integer_zerop (equal_result)
- || integer_onep (equal_result))
- && (integer_zerop (low_result)
- || integer_onep (low_result)))
- {
- /* Make a 3-bit mask with the high-order bit being the
- value for `>', the next for '=', and the low for '<'. */
- switch ((integer_onep (high_result) * 4)
- + (integer_onep (equal_result) * 2)
- + integer_onep (low_result))
- {
- case 0:
- /* Always false. */
- return omit_one_operand (type, integer_zero_node, arg0);
- case 1:
- code = LT_EXPR;
- break;
- case 2:
- code = EQ_EXPR;
- break;
- case 3:
- code = LE_EXPR;
- break;
- case 4:
- code = GT_EXPR;
- break;
- case 5:
- code = NE_EXPR;
- break;
- case 6:
- code = GE_EXPR;
- break;
- case 7:
- /* Always true. */
- return omit_one_operand (type, integer_one_node, arg0);
- }
-
- if (save_p)
- return save_expr (build2 (code, type, cval1, cval2));
- else
- return fold_build2 (code, type, cval1, cval2);
- }
- }
- }
-
- /* If this is a comparison of a field, we may be able to simplify it. */
- if (((TREE_CODE (arg0) == COMPONENT_REF
- && lang_hooks.can_use_bit_fields_p ())
- || TREE_CODE (arg0) == BIT_FIELD_REF)
- && (code == EQ_EXPR || code == NE_EXPR)
- /* Handle the constant case even without -O
- to make sure the warnings are given. */
- && (optimize || TREE_CODE (arg1) == INTEGER_CST))
- {
- t1 = optimize_bit_field_compare (code, type, arg0, arg1);
- if (t1)
- 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));
- }
- }
-
- /* Optimize comparisons of strlen vs zero to a compare of the
- first character of the string vs zero. To wit,
- strlen(ptr) == 0 => *ptr == 0
- strlen(ptr) != 0 => *ptr != 0
- Other cases should reduce to one of these two (or a constant)
- due to the return value of strlen being unsigned. */
- if ((code == EQ_EXPR || code == NE_EXPR)
- && integer_zerop (arg1)
- && TREE_CODE (arg0) == CALL_EXPR)
- {
- tree fndecl = get_callee_fndecl (arg0);
- tree arglist;
-
- if (fndecl
- && 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))
- {
- tree iref = build_fold_indirect_ref (TREE_VALUE (arglist));
- return fold_build2 (code, type, iref,
- build_int_cst (TREE_TYPE (iref), 0));
- }
- }
-
- /* 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;
- }
-
- if ((code == EQ_EXPR || code == NE_EXPR)
- && integer_zerop (arg1)
- && tree_expr_nonzero_p (arg0))
- {
- tree res = constant_boolean_node (code==NE_EXPR, type);
- return omit_one_operand (type, res, arg0);
- }
-
- t1 = fold_relational_const (code, type, arg0, arg1);
- return t1 == NULL_TREE ? NULL_TREE : t1;
+ return NULL_TREE;
case UNORDERED_EXPR:
case ORDERED_EXPR:
&& TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
+ /* Check for resolvable OBJ_TYPE_REF. The only sorts we can resolve
+ here are when we've propagated the address of a decl into the
+ object slot. */
+ if (TREE_CODE (op0) == OBJ_TYPE_REF
+ && lang_hooks.fold_obj_type_ref
+ && TREE_CODE (OBJ_TYPE_REF_OBJECT (op0)) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (OBJ_TYPE_REF_OBJECT (op0), 0)))
+ {
+ tree t;
+
+ /* ??? Caution: Broken ADDR_EXPR semantics means that
+ looking at the type of the operand of the addr_expr
+ can yield an array type. See silly exception in
+ check_pointer_types_r. */
+
+ t = TREE_TYPE (TREE_TYPE (OBJ_TYPE_REF_OBJECT (op0)));
+ t = lang_hooks.fold_obj_type_ref (op0, t);
+ if (t)
+ return fold_build3 (code, type, t, op1, op2);
+ }
return NULL_TREE;
case BIT_FIELD_REF:
{
void **slot;
enum tree_code code;
- char buf[sizeof (struct tree_function_decl)];
+ struct tree_function_decl buf;
int i, len;
recursive_label:
&& DECL_ASSEMBLER_NAME_SET_P (expr))
{
/* Allow DECL_ASSEMBLER_NAME to be modified. */
- memcpy (buf, expr, tree_size (expr));
- expr = (tree) buf;
+ memcpy ((char *) &buf, expr, tree_size (expr));
+ expr = (tree) &buf;
SET_DECL_ASSEMBLER_NAME (expr, NULL);
}
else if (TREE_CODE_CLASS (code) == tcc_type
|| TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr)))
{
/* Allow these fields to be modified. */
- memcpy (buf, expr, tree_size (expr));
- expr = (tree) buf;
+ memcpy ((char *) &buf, expr, tree_size (expr));
+ expr = (tree) &buf;
TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr) = 0;
TYPE_POINTER_TO (expr) = NULL;
TYPE_REFERENCE_TO (expr) = NULL;
switch (TREE_CODE (t))
{
+ case SSA_NAME:
+ /* Query VRP to see if it has recorded any information about
+ the range of this object. */
+ return ssa_name_nonnegative_p (t);
+
case ABS_EXPR:
/* We can't return 1 if flag_wrapv is set because
ABS_EXPR<INT_MIN> = INT_MIN. */
switch (TREE_CODE (t))
{
+ case SSA_NAME:
+ /* Query VRP to see if it has recorded any information about
+ the range of this object. */
+ return ssa_name_nonzero_p (t);
+
case ABS_EXPR:
return tree_expr_nonzero_p (TREE_OPERAND (t, 0));
tree inner_type = TREE_TYPE (TREE_OPERAND (t, 0));
tree outer_type = TREE_TYPE (t);
- return (TYPE_PRECISION (inner_type) >= TYPE_PRECISION (outer_type)
+ return (TYPE_PRECISION (outer_type) >= TYPE_PRECISION (inner_type)
&& tree_expr_nonzero_p (TREE_OPERAND (t, 0)));
}
break;
min_val = TYPE_MIN_VALUE (type_domain);
return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE);
}
+ /* *(foo *)&complexfoo => __real__ complexfoo */
+ else if (TREE_CODE (optype) == COMPLEX_TYPE
+ && type == TREE_TYPE (optype))
+ return fold_build1 (REALPART_EXPR, type, op);
}
+ /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+ if (TREE_CODE (sub) == PLUS_EXPR
+ && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+ {
+ tree op00 = TREE_OPERAND (sub, 0);
+ tree op01 = TREE_OPERAND (sub, 1);
+ tree op00type;
+
+ STRIP_NOPS (op00);
+ op00type = TREE_TYPE (op00);
+ if (TREE_CODE (op00) == ADDR_EXPR
+ && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
+ && type == TREE_TYPE (TREE_TYPE (op00type)))
+ {
+ tree size = TYPE_SIZE_UNIT (type);
+ if (tree_int_cst_equal (size, op01))
+ return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0));
+ }
+ }
+
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
&& type == TREE_TYPE (TREE_TYPE (subtype)))