if (arg0)
{
if (CONVERT_EXPR_CODE_P (code)
- || code == FLOAT_EXPR || code == ABS_EXPR)
+ || code == FLOAT_EXPR || code == ABS_EXPR || code == NEGATE_EXPR)
{
/* Don't use STRIP_NOPS, because signedness of argument type
matters. */
return res;
}
+/* Fold a binary bitwise/truth expression of code CODE and type TYPE with
+ operands OP0 and OP1. LOC is the location of the resulting expression.
+ ARG0 and ARG1 are the NOP_STRIPed results of OP0 and OP1.
+ Return the folded expression if folding is successful. Otherwise,
+ return NULL_TREE. */
+static tree
+fold_truth_andor (location_t loc, enum tree_code code, tree type,
+ tree arg0, tree arg1, tree op0, tree op1)
+{
+ tree tem;
+
+ /* We only do these simplifications if we are optimizing. */
+ if (!optimize)
+ return NULL_TREE;
+
+ /* Check for things like (A || B) && (A || C). We can convert this
+ to A || (B && C). Note that either operator can be any of the four
+ truth and/or operations and the transformation will still be
+ valid. Also note that we only care about order for the
+ ANDIF and ORIF operators. If B contains side effects, this
+ might change the truth-value of A. */
+ if (TREE_CODE (arg0) == TREE_CODE (arg1)
+ && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
+ || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
+ || TREE_CODE (arg0) == TRUTH_AND_EXPR
+ || TREE_CODE (arg0) == TRUTH_OR_EXPR)
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
+ {
+ tree a00 = TREE_OPERAND (arg0, 0);
+ tree a01 = TREE_OPERAND (arg0, 1);
+ tree a10 = TREE_OPERAND (arg1, 0);
+ tree a11 = TREE_OPERAND (arg1, 1);
+ int commutative = ((TREE_CODE (arg0) == TRUTH_OR_EXPR
+ || TREE_CODE (arg0) == TRUTH_AND_EXPR)
+ && (code == TRUTH_AND_EXPR
+ || code == TRUTH_OR_EXPR));
+
+ if (operand_equal_p (a00, a10, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+ fold_build2_loc (loc, code, type, a01, a11));
+ else if (commutative && operand_equal_p (a00, a11, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+ fold_build2_loc (loc, code, type, a01, a10));
+ else if (commutative && operand_equal_p (a01, a10, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
+ fold_build2_loc (loc, code, type, a00, a11));
+
+ /* This case if tricky because we must either have commutative
+ operators or else A10 must not have side-effects. */
+
+ else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
+ && operand_equal_p (a01, a11, 0))
+ return fold_build2_loc (loc, TREE_CODE (arg0), type,
+ fold_build2_loc (loc, code, type, a00, a10),
+ a01);
+ }
+
+ /* See if we can build a range comparison. */
+ if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
+ return tem;
+
+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
+ {
+ tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
+ if (tem)
+ return fold_build2_loc (loc, code, type, tem, arg1);
+ }
+
+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
+ {
+ tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
+ if (tem)
+ return fold_build2_loc (loc, code, type, arg0, tem);
+ }
+
+ /* Check for the possibility of merging component references. If our
+ lhs is another similar operation, try to merge its rhs with our
+ rhs. Then try to merge our lhs and rhs. */
+ if (TREE_CODE (arg0) == code
+ && 0 != (tem = fold_truthop (loc, code, type,
+ TREE_OPERAND (arg0, 1), arg1)))
+ return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
+
+ if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
+ return tem;
+
+ return NULL_TREE;
+}
+
/* 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,
fold_convert_loc (loc, sizetype,
arg0)));
- /* index +p PTR -> PTR +p index */
- if (POINTER_TYPE_P (TREE_TYPE (arg1))
- && INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
- return fold_build2_loc (loc, POINTER_PLUS_EXPR, type,
- fold_convert_loc (loc, type, arg1),
- fold_convert_loc (loc, sizetype, arg0));
-
/* (PTR +p B) +p A -> PTR +p (B + A) */
if (TREE_CODE (arg0) == POINTER_PLUS_EXPR)
{
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
- /* ~X & X is always zero. */
- if (TREE_CODE (arg0) == BIT_NOT_EXPR
+ /* ~X & X, (X == 0) & X, and !X & X are always zero. */
+ if ((TREE_CODE (arg0) == BIT_NOT_EXPR
+ || TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ || (TREE_CODE (arg0) == EQ_EXPR
+ && integer_zerop (TREE_OPERAND (arg0, 1))))
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
- /* X & ~X is always zero. */
- if (TREE_CODE (arg1) == BIT_NOT_EXPR
+ /* X & ~X , X & (X == 0), and X & !X are always zero. */
+ if ((TREE_CODE (arg1) == BIT_NOT_EXPR
+ || TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ || (TREE_CODE (arg1) == EQ_EXPR
+ && integer_zerop (TREE_OPERAND (arg1, 1))))
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
build_int_cst (TREE_TYPE (tem), 1)),
build_int_cst (TREE_TYPE (tem), 0));
}
+ /* Fold !X & 1 as X == 0. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && integer_onep (arg1))
+ {
+ tem = TREE_OPERAND (arg0, 0);
+ return fold_build2_loc (loc, EQ_EXPR, type, tem,
+ build_int_cst (TREE_TYPE (tem), 0));
+ }
/* Fold (X ^ Y) & Y as ~X & Y. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
return fold_build2_loc (loc, code, type, arg0, tem);
}
- truth_andor:
- /* We only do these simplifications if we are optimizing. */
- if (!optimize)
- return NULL_TREE;
-
- /* Check for things like (A || B) && (A || C). We can convert this
- to A || (B && C). Note that either operator can be any of the four
- truth and/or operations and the transformation will still be
- valid. Also note that we only care about order for the
- ANDIF and ORIF operators. If B contains side effects, this
- might change the truth-value of A. */
- if (TREE_CODE (arg0) == TREE_CODE (arg1)
- && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
- || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
- || TREE_CODE (arg0) == TRUTH_AND_EXPR
- || TREE_CODE (arg0) == TRUTH_OR_EXPR)
- && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
- {
- tree a00 = TREE_OPERAND (arg0, 0);
- tree a01 = TREE_OPERAND (arg0, 1);
- tree a10 = TREE_OPERAND (arg1, 0);
- tree a11 = TREE_OPERAND (arg1, 1);
- int commutative = ((TREE_CODE (arg0) == TRUTH_OR_EXPR
- || TREE_CODE (arg0) == TRUTH_AND_EXPR)
- && (code == TRUTH_AND_EXPR
- || code == TRUTH_OR_EXPR));
-
- if (operand_equal_p (a00, a10, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
- fold_build2_loc (loc, code, type, a01, a11));
- else if (commutative && operand_equal_p (a00, a11, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
- fold_build2_loc (loc, code, type, a01, a10));
- else if (commutative && operand_equal_p (a01, a10, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
- fold_build2_loc (loc, code, type, a00, a11));
-
- /* This case if tricky because we must either have commutative
- operators or else A10 must not have side-effects. */
-
- else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
- && operand_equal_p (a01, a11, 0))
- return fold_build2_loc (loc, TREE_CODE (arg0), type,
- fold_build2_loc (loc, code, type, a00, a10),
- a01);
- }
-
- /* See if we can build a range comparison. */
- if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
- return tem;
-
- if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
- || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
- {
- tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
- if (tem)
- return fold_build2_loc (loc, code, type, tem, arg1);
- }
-
- if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
- || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
- {
- tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
- if (tem)
- return fold_build2_loc (loc, code, type, arg0, tem);
- }
-
- /* Check for the possibility of merging component references. If our
- lhs is another similar operation, try to merge its rhs with our
- rhs. Then try to merge our lhs and rhs. */
- if (TREE_CODE (arg0) == code
- && 0 != (tem = fold_truthop (loc, code, type,
- TREE_OPERAND (arg0, 1), arg1)))
- return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
-
- if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
- return tem;
+ if ((tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1))
+ != NULL_TREE)
+ return tem;
return NULL_TREE;
&& operand_equal_p (n1, a0, 0)))
return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
}
- goto truth_andor;
+
+ if ((tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1))
+ != NULL_TREE)
+ return tem;
+
+ return NULL_TREE;
case TRUTH_XOR_EXPR:
/* If the second arg is constant zero, drop it. */