From f84e7fd6cb5091fa4eba373782f2a87dd449521f Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 13 Nov 2014 13:58:59 +0000 Subject: [PATCH] match.pd: Add tcc_comparison... 2014-11-13 Richard Biener * match.pd: Add tcc_comparison, inverted_tcc_comparison and inverted_tcc_comparison_with_nans operator lists. Use tcc_comparison in the truth_valued_p predicate definition. Restrict logical_inverted_value with bit_xor to integral types. Build a boolean true for simplifying x |^ !x because of vector types. Implement patterns from forward_propagate_comparison * tree-ssa-forwprop.c (forward_propagate_comparison): Remove. (get_prop_dest_stmt): Likewise. (pass_forwprop::execute): Do not call it. * fold-const.c (fold_unary_loc): Remove the pattern here. * gcc.dg/tree-ssa/forwprop-28.c: Adjust. From-SVN: r217496 --- gcc/ChangeLog | 13 +++ gcc/fold-const.c | 12 -- gcc/match.pd | 54 ++++++++- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c | 7 +- gcc/tree-ssa-forwprop.c | 121 -------------------- 6 files changed, 74 insertions(+), 137 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9267d828c9c..0d2f4db5362 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2014-11-13 Richard Biener + + * match.pd: Add tcc_comparison, inverted_tcc_comparison + and inverted_tcc_comparison_with_nans operator lists. + Use tcc_comparison in the truth_valued_p predicate definition. + Restrict logical_inverted_value with bit_xor to integral types. + Build a boolean true for simplifying x |^ !x because of + vector types. Implement patterns from forward_propagate_comparison + * tree-ssa-forwprop.c (forward_propagate_comparison): Remove. + (get_prop_dest_stmt): Likewise. + (pass_forwprop::execute): Do not call it. + * fold-const.c (fold_unary_loc): Remove the pattern here. + 2014-11-13 Ilya Verbin Andrey Turetskiy diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a711be9c106..e51abee590c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7938,18 +7938,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) if (i == count) return build_vector (type, elements); } - else if (COMPARISON_CLASS_P (arg0) - && (VECTOR_TYPE_P (type) - || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))) - { - tree op_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); - enum tree_code subcode = invert_tree_comparison (TREE_CODE (arg0), - HONOR_NANS (TYPE_MODE (op_type))); - if (subcode != ERROR_MARK) - return build2_loc (loc, subcode, type, TREE_OPERAND (arg0, 0), - TREE_OPERAND (arg0, 1)); - } - return NULL_TREE; diff --git a/gcc/match.pd b/gcc/match.pd index 5a423201183..6231d4787f4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -31,6 +31,14 @@ along with GCC; see the file COPYING3. If not see CONSTANT_CLASS_P tree_expr_nonnegative_p) +/* Operator lists. */ +(define_operator_list tcc_comparison + lt le eq ne ge gt unordered ordered unlt unle ungt unge uneq ltgt) +(define_operator_list inverted_tcc_comparison + ge gt ne eq lt le ordered unordered ge gt le lt ltgt uneq) +(define_operator_list inverted_tcc_comparison_with_nans + unge ungt ne eq unlt unle ordered unordered ge gt le lt ltgt uneq) + /* Simplifications of operations with one constant operand and simplifications to constants or single values. */ @@ -172,7 +180,7 @@ along with GCC; see the file COPYING3. If not see (match truth_valued_p @0 (if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))) -(for op (lt le eq ne ge gt truth_and truth_andif truth_or truth_orif truth_xor) +(for op (tcc_comparison truth_and truth_andif truth_or truth_orif truth_xor) (match truth_valued_p (op @0 @1))) (match truth_valued_p @@ -187,7 +195,8 @@ along with GCC; see the file COPYING3. If not see (ne truth_valued_p@0 integer_onep) (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))))) (match (logical_inverted_value @0) - (bit_xor truth_valued_p@0 integer_onep)) + (bit_xor truth_valued_p@0 integer_onep) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))))) /* X & !X -> 0. */ (simplify @@ -197,7 +206,7 @@ along with GCC; see the file COPYING3. If not see (for op (bit_ior bit_xor) (simplify (op:c truth_valued_p@0 (logical_inverted_value @0)) - { build_one_cst (type); })) + { constant_boolean_node (true, type); })) (for bitop (bit_and bit_ior) rbitop (bit_ior bit_and) @@ -632,3 +641,42 @@ along with GCC; see the file COPYING3. If not see (simplify (cond (logical_inverted_value truth_valued_p@0) @1 @2) (cond @0 @2 @1)) + + +/* Simplifications of comparisons. */ + +/* We can simplify a logical negation of a comparison to the + inverted comparison. As we cannot compute an expression + operator using invert_tree_comparison we have to simulate + that with expression code iteration. */ +(for cmp (tcc_comparison) + icmp (inverted_tcc_comparison) + ncmp (inverted_tcc_comparison_with_nans) + /* Ideally we'd like to combine the following two patterns + and handle some more cases by using + (logical_inverted_value (cmp @0 @1)) + here but for that genmatch would need to "inline" that. + For now implement what forward_propagate_comparison did. */ + (simplify + (bit_not (cmp @0 @1)) + (if (VECTOR_TYPE_P (type) + || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)) + /* Comparison inversion may be impossible for trapping math, + invert_tree_comparison will tell us. But we can't use + a computed operator in the replacement tree thus we have + to play the trick below. */ + (with { enum tree_code ic = invert_tree_comparison + (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); } + (if (ic == icmp) + (icmp @0 @1)) + (if (ic == ncmp) + (ncmp @0 @1))))) + (simplify + (bit_xor (cmp @0 @1) integer_onep) + (if (INTEGRAL_TYPE_P (type)) + (with { enum tree_code ic = invert_tree_comparison + (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); } + (if (ic == icmp) + (icmp @0 @1)) + (if (ic == ncmp) + (ncmp @0 @1)))))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5376ce19432..279c1b4a574 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-11-13 Richard Biener + + * gcc.dg/tree-ssa/forwprop-28.c: Adjust. + 2014-11-12 Alexander Ivchenko * lib/target-supports.exp (error_h): New check. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c index 5c945fce41b..1824131086a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c @@ -79,6 +79,11 @@ test_8 (int code) oof (); } -/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 8 "forwprop1"} } */ +/* ??? This used to check for 8 times transforming the combined conditional + to a ordered compare. But the transform does not trigger if we transform + the negated code == 22 compare to code != 22 first. It turns out if + we do that we even generate better code on x86 at least. */ + +/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 4 "forwprop1"} } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index feb82539456..d42dcf891a9 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -233,38 +233,6 @@ fwprop_invalidate_lattice (tree name) } -/* Get the next statement we can propagate NAME's value into skipping - trivial copies. Returns the statement that is suitable as a - propagation destination or NULL_TREE if there is no such one. - This only returns destinations in a single-use chain. FINAL_NAME_P - if non-NULL is written to the ssa name that represents the use. */ - -static gimple -get_prop_dest_stmt (tree name, tree *final_name_p) -{ - use_operand_p use; - gimple use_stmt; - - do { - /* If name has multiple uses, bail out. */ - if (!single_imm_use (name, &use, &use_stmt)) - return NULL; - - /* If this is not a trivial copy, we found it. */ - if (!gimple_assign_ssa_name_copy_p (use_stmt) - || gimple_assign_rhs1 (use_stmt) != name) - break; - - /* Continue searching uses of the copy destination. */ - name = gimple_assign_lhs (use_stmt); - } while (1); - - if (final_name_p) - *final_name_p = name; - - return use_stmt; -} - /* Get the statement we can propagate from into NAME skipping trivial copies. Returns the statement which defines the propagation source or NULL_TREE if there is no such one. @@ -1060,90 +1028,6 @@ forward_propagate_addr_expr (tree name, tree rhs, bool parent_single_use_p) } -/* Forward propagate the comparison defined in *DEFGSI like - cond_1 = x CMP y to uses of the form - a_1 = (T')cond_1 - a_1 = !cond_1 - a_1 = cond_1 != 0 - Returns true if stmt is now unused. Advance DEFGSI to the next - statement. */ - -static bool -forward_propagate_comparison (gimple_stmt_iterator *defgsi) -{ - gimple stmt = gsi_stmt (*defgsi); - tree name = gimple_assign_lhs (stmt); - gimple use_stmt; - tree tmp = NULL_TREE; - gimple_stmt_iterator gsi; - enum tree_code code; - tree lhs; - - /* Don't propagate ssa names that occur in abnormal phis. */ - if ((TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt))) - || (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs2 (stmt)))) - goto bailout; - - /* Do not un-cse comparisons. But propagate through copies. */ - use_stmt = get_prop_dest_stmt (name, &name); - if (!use_stmt - || !is_gimple_assign (use_stmt)) - goto bailout; - - code = gimple_assign_rhs_code (use_stmt); - lhs = gimple_assign_lhs (use_stmt); - if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs))) - goto bailout; - - /* We can propagate the condition into a statement that - computes the logical negation of the comparison result. */ - if ((code == BIT_NOT_EXPR - && TYPE_PRECISION (TREE_TYPE (lhs)) == 1) - || (code == BIT_XOR_EXPR - && integer_onep (gimple_assign_rhs2 (use_stmt)))) - { - tree type = TREE_TYPE (gimple_assign_rhs1 (stmt)); - bool nans = HONOR_NANS (TYPE_MODE (type)); - enum tree_code inv_code; - inv_code = invert_tree_comparison (gimple_assign_rhs_code (stmt), nans); - if (inv_code == ERROR_MARK) - goto bailout; - - tmp = build2 (inv_code, TREE_TYPE (lhs), gimple_assign_rhs1 (stmt), - gimple_assign_rhs2 (stmt)); - } - else - goto bailout; - - gsi = gsi_for_stmt (use_stmt); - gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (tmp)); - use_stmt = gsi_stmt (gsi); - update_stmt (use_stmt); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " Replaced '"); - print_gimple_expr (dump_file, stmt, 0, dump_flags); - fprintf (dump_file, "' with '"); - print_gimple_expr (dump_file, use_stmt, 0, dump_flags); - fprintf (dump_file, "'\n"); - } - - /* When we remove stmt now the iterator defgsi goes off it's current - sequence, hence advance it now. */ - gsi_next (defgsi); - - /* Remove defining statements. */ - return remove_prop_source_from_use (name); - -bailout: - gsi_next (defgsi); - return false; -} - - /* Helper function for simplify_gimple_switch. Remove case labels that have values outside the range of the new type. */ @@ -2316,11 +2200,6 @@ pass_forwprop::execute (function *fun) else gsi_next (&gsi); } - else if (TREE_CODE_CLASS (code) == tcc_comparison) - { - if (forward_propagate_comparison (&gsi)) - cfg_changed = true; - } else gsi_next (&gsi); } -- 2.30.2