diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index dfb31a02078..9974b491626 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5789,6 +5789,12 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return NULL_TREE; } +static tree +do_valueize (tree t) +{ + return t; +} + /* Try to simplify the AND of two comparisons, specified by (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively. If this can be simplified to a single expression (without requiring @@ -5800,11 +5806,39 @@ tree maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { - tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); + tree t1 = fold_build2 (code1, boolean_type_node, op1a, op1b); + tree t2 = fold_build2 (code2, boolean_type_node, op2a, op2b); + + tree new_lhs1 = make_ssa_name (TREE_TYPE (t1)); + tree new_lhs2 = make_ssa_name (TREE_TYPE (t2)); + + gassign *gassign1 = gimple_build_assign (new_lhs1, t1); + gassign *gassign2 = gimple_build_assign (new_lhs2, t2); + + tree t = gimple_simplify (TRUTH_AND_EXPR, boolean_type_node, + gimple_assign_lhs (gassign1), + gimple_assign_lhs (gassign2), NULL, do_valueize); + + if (!t) + { + t = gimple_simplify (TRUTH_AND_EXPR, boolean_type_node, + gimple_assign_lhs (gassign2), + gimple_assign_lhs (gassign1), NULL, do_valueize); + } + if (t) - return t; - else - return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); + { + gimple *def = SSA_NAME_DEF_STMT (t); + + if (!is_gimple_assign (def) + || TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison) + return NULL_TREE; + + return fold_build2 (gimple_assign_rhs_code (def), boolean_type_node, + gimple_assign_rhs1 (def), gimple_assign_rhs2 (def)); + } + + return NULL_TREE; } /* Helper function for or_comparisons_1: try to simplify the OR of the diff --git a/gcc/match.pd b/gcc/match.pd index f8e35e96d22..21a147d0ff1 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1859,6 +1859,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { wide_int_to_tree (type, (wi::to_wide (@1) & (bitpos / BITS_PER_UNIT))); })))) +/* x > y && x != XXX_MIN --> x > y */ +(for and (truth_and bit_and) + (simplify + (and:c (gt:c@3 @0 @1) (ne @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))) + @3))) + +/* x > y && x == XXX_MIN --> false */ +(for and (truth_and bit_and) + (simplify + (and:c (gt:c @0 @1) (eq @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))) + { boolean_false_node; }))) + +/* x <= y && x == XXX_MIN --> x == XXX_MIN */ +(for and (truth_and bit_and) + (simplify + (and:c (le:c @0 @1) (eq@3 @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))) + @3))) + +/* x < y && x != XXX_MAX --> x < y */ +(for and (truth_and bit_and) + (simplify + (and:c (lt:c@3 @0 @1) (ne @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))) + @3))) + +/* x < y && x == XXX_MAX --> false */ +(for and (truth_and bit_and) + (simplify + (and:c (lt:c @0 @1) (eq @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))) + { boolean_false_node; }))) + +/* x >= y && x == XXX_MAX --> x == XXX_MAX */ +(for and (truth_and bit_and) + (simplify + (and:c (ge:c @0 @1) (eq@3 @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))) + @3))) + +/* x > y || x != XXX_MIN --> x != XXX_MIN */ +(for or (truth_or bit_ior) + (simplify + (or:c (gt:c @0 @1) (ne@3 @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))) + @3))) + +/* x <= y || x != XXX_MIN --> true */ +(for or (truth_or bit_ior) + (simplify + (or:c (le:c @0 @1) (ne @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))) + { boolean_true_node; }))) + +/* x <= y || x == XXX_MIN --> x <= y */ +(for or (truth_or bit_ior) + (simplify + (or:c (le:c@3 @0 @1) (eq @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))) + @3))) + +/* x < y || x != XXX_MAX --> x != XXX_MAX */ +(for or (truth_or bit_ior) + (simplify + (or:c (lt:c @0 @1) (ne@3 @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))) + @3))) + +/* x >= y || x != XXX_MAX --> true */ +(for or (truth_or bit_ior) + (simplify + (or:c (ge:c @0 @1) (ne @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))) + { boolean_true_node; }))) + +/* x >= y || x == XXX_MAX --> x >= y */ +(for or (truth_or bit_ior) + (simplify + (or:c (ge:c@3 @0 @1) (eq @0 INTEGER_CST@2)) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)) + && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))) + @3))) /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type))