From e8e8c74b492f3e981e2c6dc8a87a896c2fb338e0 Mon Sep 17 00:00:00 2001 From: Kai Tietz Date: Fri, 8 Jul 2011 15:22:52 +0200 Subject: [PATCH] fold-const.c (fold_truth_andor): Factored out truth_andor label from fold_binary as function. 2011-07-08 Kai Tietz * fold-const.c (fold_truth_andor): Factored out truth_andor label from fold_binary as function. (fold_binary_loc): Replace truth_andor lable by function fold_truth_andor. From-SVN: r176043 --- gcc/ChangeLog | 7 ++ gcc/fold-const.c | 178 ++++++++++++++++++++++++++--------------------- 2 files changed, 107 insertions(+), 78 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8112a8cce28..3d1c284dbf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-07-08 Kai Tietz + + * fold-const.c (fold_truth_andor): Factored out truth_andor + label from fold_binary as function. + (fold_binary_loc): Replace truth_andor lable + by function fold_truth_andor. + 2011-07-08 Kirill Yukhin PR middle-end/49519 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 44a8b6feaaa..1b5683d6e7a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8211,6 +8211,97 @@ fold_unary_ignore_overflow_loc (location_t loc, enum tree_code code, 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, @@ -11953,83 +12044,9 @@ 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; + if ((tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1)) + != NULL_TREE) + return tem; return NULL_TREE; @@ -12087,7 +12104,12 @@ 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; + + 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. */ -- 2.30.2