summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-13 13:58:59 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-13 13:58:59 +0000
commit9ec260f0908cc670f002f111cb0ac779eb57abf0 (patch)
treeb84b11303968c5b98e08de3b9e43e7f0e574316c
parent7e689f9a08deca05e237aa1885f52a743dac8c0a (diff)
2014-11-13 Richard Biener <rguenther@suse.de>
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217496 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/fold-const.c12
-rw-r--r--gcc/match.pd54
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c7
-rw-r--r--gcc/tree-ssa-forwprop.c121
6 files changed, 74 insertions, 137 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9267d828c9cc..0d2f4db5362e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2014-11-13 Richard Biener <rguenther@suse.de>
+
+ * 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 <ilya.verbin@intel.com>
Andrey Turetskiy <andrey.turetskiy@intel.com>
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index a711be9c1064..e51abee590c6 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 5a423201183f..6231d4787f43 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 5376ce194323..279c1b4a5749 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2014-11-13 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/forwprop-28.c: Adjust.
+
2014-11-12 Alexander Ivchenko <alexander.ivchenko@intel.com>
* 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 5c945fce41ba..1824131086ac 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 feb825394565..d42dcf891a94 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);
}