X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffold-const.c;h=9640264954a2e75063e4107543f674194d5ab7c8;hb=a27e10150254628bfb2259797135345eebb3f82a;hp=ebb1d34d5f4cd7aa210ffdc218b1421a8d436ac8;hpb=76288c9ae6793fae67779f28de294d908a0fb917;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/fold-const.c b/gcc/fold-const.c index ebb1d34d5f4..9640264954a 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7561,7 +7561,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) 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. */ @@ -7660,15 +7660,19 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) if (COMPARISON_CLASS_P (op0)) { /* If we have (type) (a CMP b) and type is an integral type, return - new expression involving the new type. */ + new expression involving the new type. Canonicalize + (type) (a CMP b) to (a CMP b) ? (type) true : (type) false for + non-integral type. + Do not fold the result as that would not simplify further, also + folding again results in recursions. */ if (INTEGRAL_TYPE_P (type)) - return fold_build2_loc (loc, TREE_CODE (op0), type, - TREE_OPERAND (op0, 0), - TREE_OPERAND (op0, 1)); + return build2_loc (loc, TREE_CODE (op0), type, + TREE_OPERAND (op0, 0), + TREE_OPERAND (op0, 1)); else - return fold_build3_loc (loc, COND_EXPR, type, op0, - fold_convert (type, boolean_true_node), - fold_convert (type, boolean_false_node)); + return build3_loc (loc, COND_EXPR, type, op0, + fold_convert (type, boolean_true_node), + fold_convert (type, boolean_false_node)); } /* Handle cases of two conversions in a row. */ @@ -8207,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, @@ -9480,13 +9575,6 @@ fold_binary_loc (location_t loc, 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) { @@ -10515,7 +10603,8 @@ fold_binary_loc (location_t loc, } /* Optimize x*x as pow(x,2.0), which is expanded as x*x. */ - if (optimize_function_for_speed_p (cfun) + if (!in_gimple_form + && optimize_function_for_speed_p (cfun) && operand_equal_p (arg0, arg1, 0)) { tree powfn = mathfn_built_in (type, BUILT_IN_POW); @@ -10861,13 +10950,19 @@ fold_binary_loc (location_t loc, 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); @@ -10928,6 +11023,14 @@ fold_binary_loc (location_t loc, 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 @@ -11934,83 +12037,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; @@ -12068,7 +12097,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. */ @@ -12352,14 +12386,6 @@ fold_binary_loc (location_t loc, } } - /* 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_loc (loc, 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