This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch tree-optimization]: [1 of 3]: Boolify compares & more
- From: Kai Tietz <ktietz70 at googlemail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Guenther <richard dot guenther at gmail dot com>
- Date: Thu, 7 Jul 2011 18:06:53 +0200
- Subject: [patch tree-optimization]: [1 of 3]: Boolify compares & more
Hello,
This patch - first of series - adds to fold and some helper routines support
for one-bit precision bitwise folding and detection.
This patch is necessary for - next patch of series - boolification of
comparisons.
Bootstrapped and regression tested for all standard-languages (plus
Ada and Obj-C++) on host x86_64-pc-linux-gnu.
Ok for apply?
Regards,
Kai
ChangeLog
2011-07-07 Kai Tietz <ktietz@redhat.com>
* fold-const.c (fold_truth_not_expr): Handle
one bit precision bitwise operations.
(fold_range_test): Likewise.
(fold_truthop): Likewise.
(fold_binary_loc): Likewise.
(fold_truth_andor): Function replaces truth_andor
label.
(fold_ternary_loc): Use truth_value_type_p instead
of truth_value_p.
* gimple.c (canonicalize_cond_expr_cond): Likewise.
* gimplify.c (gimple_boolify): Likewise.
* tree-ssa-structalias.c (find_func_aliases): Likewise.
* tree-ssa-forwprop.c (truth_valued_ssa_name): Likewise.
* tree.h (truth_value_type_p): New function.
(truth_value_p): Implemented as macro via truth_value_type_p.
Index: gcc-head/gcc/fold-const.c
===================================================================
--- gcc-head.orig/gcc/fold-const.c
+++ gcc-head/gcc/fold-const.c
@@ -3074,20 +3074,35 @@ fold_truth_not_expr (location_t loc, tre
case INTEGER_CST:
return constant_boolean_node (integer_zerop (arg), type);
+ case BIT_AND_EXPR:
+ if (integer_onep (TREE_OPERAND (arg, 1)))
+ return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
+ if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+ return NULL_TREE;
+ /* fall through */
case TRUTH_AND_EXPR:
loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
- return build2_loc (loc, TRUTH_OR_EXPR, type,
+ return build2_loc (loc, (code == BIT_AND_EXPR ? BIT_IOR_EXPR
+ : TRUTH_OR_EXPR), type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+ case BIT_IOR_EXPR:
+ if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+ return NULL_TREE;
+ /* fall through. */
case TRUTH_OR_EXPR:
loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
- return build2_loc (loc, TRUTH_AND_EXPR, type,
+ return build2_loc (loc, (code == BIT_IOR_EXPR ? BIT_AND_EXPR
+ : TRUTH_AND_EXPR), type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-
+ case BIT_XOR_EXPR:
+ if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+ return NULL_TREE;
+ /* fall through. */
case TRUTH_XOR_EXPR:
/* Here we can invert either operand. We invert the first operand
unless the second operand is a TRUTH_NOT_EXPR in which case our
@@ -3095,10 +3110,14 @@ fold_truth_not_expr (location_t loc, tre
negation of the second operand. */
if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
- return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+ return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+ TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+ else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR
+ && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 1))) == 1)
+ return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
else
- return build2_loc (loc, TRUTH_XOR_EXPR, type,
+ return build2_loc (loc, code, type,
invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
TREE_OPERAND (arg, 1));
@@ -3116,6 +3135,11 @@ fold_truth_not_expr (location_t loc, tre
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
+
+ case BIT_NOT_EXPR:
+ if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+ return NULL_TREE;
+ /* fall through */
case TRUTH_NOT_EXPR:
return TREE_OPERAND (arg, 0);
@@ -3158,11 +3182,6 @@ fold_truth_not_expr (location_t loc, tre
return build1_loc (loc, TREE_CODE (arg), type,
invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));
- case BIT_AND_EXPR:
- if (!integer_onep (TREE_OPERAND (arg, 1)))
- return NULL_TREE;
- return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
-
case SAVE_EXPR:
return build1_loc (loc, TRUTH_NOT_EXPR, type, arg);
@@ -4800,7 +4819,7 @@ fold_range_test (location_t loc, enum tr
tree op0, tree op1)
{
int or_op = (code == TRUTH_ORIF_EXPR
- || code == TRUTH_OR_EXPR);
+ || code == TRUTH_OR_EXPR || code == BIT_IOR_EXPR);
int in0_p, in1_p, in_p;
tree low0, low1, low, high0, high1, high;
bool strict_overflow_p = false;
@@ -5099,8 +5118,9 @@ fold_truthop (location_t loc, enum tree_
}
}
- code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR)
- ? TRUTH_AND_EXPR : TRUTH_OR_EXPR);
+ if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR)
+ code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR)
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR);
/* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines
@@ -5115,7 +5135,7 @@ fold_truthop (location_t loc, enum tree_
&& simple_operand_p (rr_arg))
{
/* Convert (a != 0) || (b != 0) into (a | b) != 0. */
- if (code == TRUTH_OR_EXPR
+ if ((code == TRUTH_OR_EXPR || code == BIT_IOR_EXPR)
&& lcode == NE_EXPR && integer_zerop (lr_arg)
&& rcode == NE_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
@@ -5126,7 +5146,7 @@ fold_truthop (location_t loc, enum tree_
build_int_cst (TREE_TYPE (ll_arg), 0));
/* Convert (a == 0) && (b == 0) into (a | b) == 0. */
- if (code == TRUTH_AND_EXPR
+ if ((code == TRUTH_AND_EXPR || code == BIT_AND_EXPR)
&& lcode == EQ_EXPR && integer_zerop (lr_arg)
&& rcode == EQ_EXPR && integer_zerop (rr_arg)
&& TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
@@ -5190,7 +5210,8 @@ fold_truthop (location_t loc, enum tree_
fail. However, we can convert a one-bit comparison against zero into
the opposite comparison against that bit being set in the field. */
- wanted_code = (code == TRUTH_AND_EXPR ? EQ_EXPR : NE_EXPR);
+ wanted_code = ((code == TRUTH_AND_EXPR || code == BIT_AND_EXPR)
+ ? EQ_EXPR : NE_EXPR);
if (lcode != wanted_code)
{
if (l_const && integer_zerop (l_const) && integer_pow2p (ll_mask))
@@ -9324,6 +9345,105 @@ get_pointer_modulus_and_residue (tree ex
return 1;
}
+/* 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;
+ /* If code is BIT_AND_EXPR or BIT_IOR_EXPR, type precision has to be one. */
+ if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
+ && (!INTEGRAL_TYPE_P (type) || TYPE_PRECISION (type) != 1))
+ 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) == BIT_AND_EXPR
+ || TREE_CODE (arg0) == BIT_IOR_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
+ || TREE_CODE (arg0) == BIT_AND_EXPR)
+ && (code == TRUTH_AND_EXPR
+ || code == TRUTH_OR_EXPR
+ || code == BIT_IOR_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. LOC is the location of the resulting expression.
@@ -9424,21 +9544,42 @@ fold_binary_loc (location_t loc,
if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
|| code == EQ_EXPR || code == NE_EXPR)
- && ((truth_value_p (TREE_CODE (arg0))
- && (truth_value_p (TREE_CODE (arg1))
+ && (!INTEGRAL_TYPE_P (type) || TYPE_PRECISION (type) != 1)
+ && ((truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+ && (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
|| (TREE_CODE (arg1) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg1, 1)))))
- || (truth_value_p (TREE_CODE (arg1))
- && (truth_value_p (TREE_CODE (arg0))
+ || (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+ && (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
|| (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)))))))
{
tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR
- : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
- : TRUTH_XOR_EXPR,
- boolean_type_node,
- fold_convert_loc (loc, boolean_type_node, arg0),
- fold_convert_loc (loc, boolean_type_node, arg1));
+ : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+ : TRUTH_XOR_EXPR,
+ boolean_type_node,
+ fold_convert_loc (loc, boolean_type_node, arg0),
+ fold_convert_loc (loc, boolean_type_node, arg1));
+
+ if (code == EQ_EXPR)
+ tem = invert_truthvalue_loc (loc, tem);
+
+ return fold_convert_loc (loc, type, tem);
+ }
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && ((truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+ && (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+ || (TREE_CODE (arg1) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg1, 1)))))
+ || (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+ && (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+ || (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1)))))))
+ {
+ tem = fold_build2_loc (loc, BIT_XOR_EXPR,
+ boolean_type_node,
+ fold_convert_loc (loc, boolean_type_node, arg0),
+ fold_convert_loc (loc, boolean_type_node, arg1));
if (code == EQ_EXPR)
tem = invert_truthvalue_loc (loc, tem);
@@ -10597,6 +10738,57 @@ fold_binary_loc (location_t loc,
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+ if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+ {
+ /* If either arg is constant zero, drop it. */
+ if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+ if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+ /* If second arg is constant true, result is true, but we must
+ evaluate first arg. */
+ if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
+ return omit_one_operand_loc (loc, type, arg1, arg0);
+ if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
+ return omit_one_operand_loc (loc, type, arg0, arg1);
+
+ /* !X | X is always true. */
+ if ((TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ || TREE_CODE (arg0) == BIT_NOT_EXPR)
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg1);
+ /* X | !X is always true. */
+ if ((TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ || TREE_CODE (arg1) == BIT_NOT_EXPR)
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+
+ /* (X & !Y) | (!X & Y) is X ^ Y */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (arg1) == BIT_AND_EXPR)
+ {
+ tree a0, a1, l0, l1, n0, n1;
+
+ a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+ a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+ l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+ l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+ n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
+ n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
+
+ if ((operand_equal_p (n0, a0, 0)
+ && operand_equal_p (n1, a1, 0))
+ || (operand_equal_p (n0, a1, 0)
+ && operand_equal_p (n1, a0, 0)))
+ return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
+ }
+ tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+ if (tem)
+ return tem;
+ }
+
/* ~X | X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
@@ -10758,6 +10950,24 @@ fold_binary_loc (location_t loc,
if (operand_equal_p (arg0, arg1, 0))
return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
+ if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+ {
+ /* If the second arg is constant true, this is a logical inversion. */
+ if (integer_onep (arg1))
+ {
+ tem = invert_truthvalue_loc (loc, arg0);
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ }
+ /* !X ^ X is always true. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg1);
+ /* X ^ !X is always true. */
+ if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+ }
+
/* ~X ^ X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
@@ -10918,6 +11128,61 @@ fold_binary_loc (location_t loc,
return omit_one_operand_loc (loc, type, arg1, arg0);
if (operand_equal_p (arg0, arg1, 0))
return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+ /* Note that the operands of this must be ints
+ and their values must be 0 or 1.
+ ("true" is a fixed value perhaps depending on the language.) */
+ /* If first arg is constant zero, return it. */
+ if (integer_zerop (arg0))
+ return fold_convert_loc (loc, type, arg0);
+
+ if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+ {
+ /* If either arg is constant true, drop it. */
+ if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+ if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
+ /* Preserve sequence points. */
+ && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
+ return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+ /* If second arg is constant zero, result is zero, but first arg
+ must be evaluated. */
+ if (integer_zerop (arg1))
+ return omit_one_operand_loc (loc, type, arg1, arg0);
+ /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
+ case will be handled here. */
+ if (integer_zerop (arg0))
+ return omit_one_operand_loc (loc, type, arg0, arg1);
+
+ /* !X && X is always false. */
+ if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+ && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
+ /* X & !X is always false. */
+ if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+ && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
+
+ /* A < X & A + 1 > Y ==> A < X & A >= Y. Normally A + 1 > Y
+ means A >= Y & A != MAX, but in this case we know that
+ A < X <= MAX. */
+
+ if (!TREE_SIDE_EFFECTS (arg0)
+ && !TREE_SIDE_EFFECTS (arg1))
+ {
+ tem = fold_to_nonsharp_ineq_using_bound (loc, arg0, arg1);
+ if (tem && !operand_equal_p (tem, arg0, 0))
+ return fold_build2_loc (loc, code, type, tem, arg1);
+
+ tem = fold_to_nonsharp_ineq_using_bound (loc, arg1, arg0);
+ if (tem && !operand_equal_p (tem, arg1, 0))
+ return fold_build2_loc (loc, code, type, arg0, tem);
+ }
+
+ tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+ if (tem)
+ return tem;
+
+ }
/* ~X & X, (X == 0) & X, and !X & X are always zero. */
if ((TREE_CODE (arg0) == BIT_NOT_EXPR
@@ -12006,86 +12271,11 @@ fold_binary_loc (location_t loc,
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;
+ tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+ if (tem)
+ return tem;
return NULL_TREE;
-
case TRUTH_ORIF_EXPR:
/* Note that the operands of this must be ints
and their values must be 0 or true.
@@ -12140,7 +12330,11 @@ fold_binary_loc (location_t loc,
&& operand_equal_p (n1, a0, 0)))
return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
}
- goto truth_andor;
+ tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+ if (tem)
+ return tem;
+
+ return NULL_TREE;
case TRUTH_XOR_EXPR:
/* If the second arg is constant zero, drop it. */
@@ -13401,7 +13595,7 @@ fold_ternary_loc (location_t loc, enum t
/* If the second operand is simpler than the third, swap them
since that produces better jump optimization results. */
- if (truth_value_p (TREE_CODE (arg0))
+ if (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
&& tree_swap_operands_p (op1, op2, false))
{
location_t loc0 = expr_location_or (arg0, loc);
@@ -13427,7 +13621,7 @@ fold_ternary_loc (location_t loc, enum t
over COND_EXPR in cases such as floating point comparisons. */
if (integer_zerop (op1)
&& integer_onep (op2)
- && truth_value_p (TREE_CODE (arg0)))
+ && truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0)))
return pedantic_non_lvalue_loc (loc,
fold_convert_loc (loc, type,
invert_truthvalue_loc (loc,
Index: gcc-head/gcc/gimple.c
===================================================================
--- gcc-head.orig/gcc/gimple.c
+++ gcc-head/gcc/gimple.c
@@ -3160,7 +3160,8 @@ canonicalize_cond_expr_cond (tree t)
{
/* Strip conversions around boolean operations. */
if (CONVERT_EXPR_P (t)
- && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0))))
+ && truth_value_type_p (TREE_CODE (TREE_OPERAND (t, 0)),
+ TREE_TYPE (TREE_OPERAND (t, 0))))
t = TREE_OPERAND (t, 0);
/* For !x use x == 0. */
Index: gcc-head/gcc/gimplify.c
===================================================================
--- gcc-head.orig/gcc/gimplify.c
+++ gcc-head/gcc/gimplify.c
@@ -2837,7 +2837,7 @@ gimple_boolify (tree expr)
if (TREE_CODE (arg) == NOP_EXPR
&& TREE_TYPE (arg) == TREE_TYPE (call))
arg = TREE_OPERAND (arg, 0);
- if (truth_value_p (TREE_CODE (arg)))
+ if (truth_value_type_p (TREE_CODE (arg), TREE_TYPE (arg)))
{
arg = gimple_boolify (arg);
CALL_EXPR_ARG (call, 0)
Index: gcc-head/gcc/tree-ssa-structalias.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-structalias.c
+++ gcc-head/gcc/tree-ssa-structalias.c
@@ -4416,7 +4416,8 @@ find_func_aliases (gimple origt)
&& !POINTER_TYPE_P (TREE_TYPE (rhsop))))
|| gimple_assign_single_p (t))
get_constraint_for_rhs (rhsop, &rhsc);
- else if (truth_value_p (code))
+ else if (truth_value_type_p (code,
+ TREE_TYPE (lhsop)))
/* Truth value results are not pointer (parts). Or at least
very very unreasonable obfuscation of a part. */
;
Index: gcc-head/gcc/tree.h
===================================================================
--- gcc-head.orig/gcc/tree.h
+++ gcc-head/gcc/tree.h
@@ -5309,13 +5309,22 @@ extern tree combine_comparisons (locatio
extern void debug_fold_checksum (const_tree);
/* Return nonzero if CODE is a tree code that represents a truth value. */
+#define truth_value_p(CODE) truth_value_type_p ((CODE), NULL_TREE)
+
+/* Return nonzero if CODE is a tree code that represents a truth value.
+ If TYPE is an integral type, unsigned, and has precision of one, then
+ additionally return for bitwise-binary and bitwise-invert nonzero. */
static inline bool
-truth_value_p (enum tree_code code)
+truth_value_type_p (enum tree_code code, tree type)
{
return (TREE_CODE_CLASS (code) == tcc_comparison
|| code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
- || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
+ || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR
+ || ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
+ || code == BIT_XOR_EXPR || code == BIT_NOT_EXPR)
+ && type && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) == 1 && TYPE_UNSIGNED (type)));
}
Index: gcc-head/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-forwprop.c
+++ gcc-head/gcc/tree-ssa-forwprop.c
@@ -1668,7 +1668,7 @@ truth_valued_ssa_name (tree name)
return true;
def = SSA_NAME_DEF_STMT (name);
if (is_gimple_assign (def))
- return truth_value_p (gimple_assign_rhs_code (def));
+ return truth_value_type_p (gimple_assign_rhs_code (def), type);
return false;
}