From patchwork Thu Jul 7 16:06:53 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai Tietz X-Patchwork-Id: 103686 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 16DF71007D1 for ; Fri, 8 Jul 2011 02:07:27 +1000 (EST) Received: (qmail 13745 invoked by alias); 7 Jul 2011 16:07:22 -0000 Received: (qmail 13725 invoked by uid 22791); 7 Jul 2011 16:07:18 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-qy0-f175.google.com (HELO mail-qy0-f175.google.com) (209.85.216.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 07 Jul 2011 16:06:55 +0000 Received: by qyk30 with SMTP id 30so2795109qyk.20 for ; Thu, 07 Jul 2011 09:06:54 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.66.31 with SMTP id l31mr717448qci.226.1310054814029; Thu, 07 Jul 2011 09:06:54 -0700 (PDT) Received: by 10.229.102.10 with HTTP; Thu, 7 Jul 2011 09:06:53 -0700 (PDT) Date: Thu, 7 Jul 2011 18:06:53 +0200 Message-ID: Subject: [patch tree-optimization]: [1 of 3]: Boolify compares & more From: Kai Tietz To: GCC Patches Cc: Richard Guenther X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * 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; }