[Well, since we can't get rid of DOM yet, why don't we clean it up and
remove stuff we can clearly do better with ranges. Maybe we can
reduce it to a bare minimum ;-).]
We now have all the pieces to do what test_for_singularity does, but
with ranges. Remove the function and use simplify_using_ranges
instead.
This makes DOM a tiny bit smarter, since simplify_using_ranges is far
more capable than the ad-hoc stuff we did. As much as I hate making
it smarter, it's all in the interest of nuking it :).
Tested on ppc64le Linux.
OK for trunk?
gcc/ChangeLog:
* tree-ssa-dom.cc (dom_opt_dom_walker::m_dummy_cond): Remove.
(dom_opt_dom_walker::test_for_singularity): Remove.
(dom_opt_dom_walker::fold_cond): Remove.
(dom_opt_dom_walker::simplify_stmt): New.
(dom_opt_dom_walker::optimize_stmt): Call it in place of
test_for_singularity and fold_cond.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/predcom-7.c: Add -fno-tree-dominator-opts.
* gcc.dg/tree-ssa/ssa-dom-simplify-3.c: New test.
---
gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c | 5 +-
.../gcc.dg/tree-ssa/ssa-dom-simplify-3.c | 91 ++++++++++
gcc/tree-ssa-dom.cc | 169 ++++--------------
3 files changed, 127 insertions(+), 138 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-3.c
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
index 99939767562..0a1bc5b3a2b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-7.c
@@ -1,5 +1,8 @@
/* { dg-do run } */
-/* { dg-options "-O3 -fdump-tree-pcom-details-blocks" } */
+/* { dg-options "-O3 -fdump-tree-pcom-details-blocks -fno-tree-dominator-opts"
} */
+/* DOM folds the exit test to c + 1 == 1 from c's range, which leaves c a
+ two-valued PHI rather than an induction variable and predcom nothing to
+ do; keep it out of the way. */
int b, f, d[5][2];
unsigned int c;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-3.c
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-3.c
new file mode 100644
index 00000000000..89d545e621d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-3.c
@@ -0,0 +1,91 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fno-tree-vrp -fdump-tree-dom2" } */
+
+void frob (void);
+
+/* x <= 4 at the last test, so x > 3 holds for x == 4 only. */
+
+void __GIMPLE (ssa,startwith("dom"))
+by_range (int x)
+{
+ __BB(2):
+ if (x_1(D) > 5)
+ goto __BB6;
+ else
+ goto __BB3;
+
+ __BB(3):
+ if (x_1(D) == 5)
+ goto __BB6;
+ else
+ goto __BB4;
+
+ __BB(4):
+ if (x_1(D) > 3)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ __BB(5):
+ frob ();
+ goto __BB6;
+
+ __BB(6):
+ return;
+}
+
+/* i <= j at the second test, so i >= j holds for i == j only. */
+
+void __GIMPLE (ssa,startwith("dom"))
+by_relation (int i, int j)
+{
+ __BB(2):
+ if (i_1(D) <= j_2(D))
+ goto __BB3;
+ else
+ goto __BB5;
+
+ __BB(3):
+ if (i_1(D) >= j_2(D))
+ goto __BB4;
+ else
+ goto __BB5;
+
+ __BB(4):
+ frob ();
+ goto __BB5;
+
+ __BB(5):
+ return;
+}
+
+/* a <= 10 and b >= 20 where the MIN is computed, so it is a. */
+
+int __GIMPLE (ssa,startwith("dom"))
+by_range_min (int a, int b)
+{
+ int m;
+
+ __BB(2):
+ if (a_1(D) > 10)
+ goto __BB5;
+ else
+ goto __BB3;
+
+ __BB(3):
+ if (b_2(D) < 20)
+ goto __BB5;
+ else
+ goto __BB4;
+
+ __BB(4):
+ m_3 = __MIN (a_1(D), b_2(D));
+ return m_3;
+
+ __BB(5):
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "if \\(x_1\\(D\\) == 4\\)" "dom2" } } */
+/* { dg-final { scan-tree-dump "if \\(i_1\\(D\\) == j_2\\(D\\)\\)" "dom2" } }
*/
+/* { dg-final { scan-tree-dump-not "MIN_EXPR" "dom2" } } */
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 7fded792a3c..490eddc37c3 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -805,8 +805,6 @@ public:
{
m_ranger = ranger;
m_state = state;
- m_dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node,
- integer_zero_node, NULL, NULL);
m_const_and_copies = const_and_copies;
m_avail_exprs_stack = avail_exprs_stack;
m_threader = threader;
@@ -821,9 +819,6 @@ private:
class const_and_copies *m_const_and_copies;
class avail_exprs_stack *m_avail_exprs_stack;
- /* Dummy condition to avoid creating lots of throw away statements. */
- gcond *m_dummy_cond;
-
/* Optimize a single statement within a basic block using the
various tables maintained by DOM. Returns the taken edge if
the statement is a conditional with a statically determined
@@ -832,8 +827,7 @@ private:
void set_global_ranges_from_unreachable_edges (basic_block);
- void test_for_singularity (gimple *, avail_exprs_stack *);
- edge fold_cond (gcond *cond);
+ void simplify_stmt (gimple_stmt_iterator *);
jump_threader *m_threader;
gimple_ranger *m_ranger;
@@ -2097,6 +2091,34 @@ cprop_operand (gimple *stmt, use_operand_p op_p,
range_query *query)
}
}
+/* Attempt to simplify the statement in GSI with range info. */
+
+void
+dom_opt_dom_walker::simplify_stmt (gimple_stmt_iterator *gsi)
+{
+ gimple *stmt = gsi_stmt (*gsi);
+
+ /* Avoid switches as touching those could remove edges mid-walk. */
+ if (gimple_code (stmt) == GIMPLE_SWITCH)
+ return;
+
+ gimple_stmt_iterator i = *gsi;
+ gsi_prev (&i);
+ gimple *before = gsi_end_p (i) ? NULL : gsi_stmt (i);
+ simplify_using_ranges simplify (m_ranger);
+ if (!simplify.simplify (gsi))
+ return;
+
+ stmt = gsi_stmt (*gsi);
+ gimple_set_modified (stmt, true);
+
+ /* Our main loop will go back over the statements inserted in front of STMT,
+ so mark those as visited to avoid looking at them again. */
+ i = *gsi;
+ for (gsi_prev (&i); !gsi_end_p (i) && gsi_stmt (i) != before; gsi_prev (&i))
+ gimple_set_visited (gsi_stmt (i), true);
+}
+
/* CONST_AND_COPIES is a table which maps an SSA_NAME to the current
known value for that SSA_NAME (or NULL if no value is known).
@@ -2130,99 +2152,6 @@ cprop_into_stmt (gimple *stmt, range_query *query)
}
}
-/* If STMT contains a relational test, try to convert it into an
- equality test if there is only a single value which can ever
- make the test true.
-
- For example, if the expression hash table contains:
-
- TRUE = (i <= 1)
-
- And we have a test within statement of i >= 1, then we can safely
- rewrite the test as i == 1 since there only a single value where
- the test is true.
-
- This is similar to code in VRP. */
-
-void
-dom_opt_dom_walker::test_for_singularity (gimple *stmt,
- avail_exprs_stack *avail_exprs_stack)
-{
- /* We want to support gimple conditionals as well as assignments
- where the RHS contains a conditional. */
- if (is_gimple_assign (stmt) || gimple_code (stmt) == GIMPLE_COND)
- {
- enum tree_code code = ERROR_MARK;
- tree lhs, rhs;
-
- /* Extract the condition of interest from both forms we support. */
- if (is_gimple_assign (stmt))
- {
- code = gimple_assign_rhs_code (stmt);
- lhs = gimple_assign_rhs1 (stmt);
- rhs = gimple_assign_rhs2 (stmt);
- }
- else if (gimple_code (stmt) == GIMPLE_COND)
- {
- code = gimple_cond_code (as_a <gcond *> (stmt));
- lhs = gimple_cond_lhs (as_a <gcond *> (stmt));
- rhs = gimple_cond_rhs (as_a <gcond *> (stmt));
- }
-
- /* We're looking for a relational test using LE/GE. Also note we can
- canonicalize LT/GT tests against constants into LE/GT tests. */
- if (code == LE_EXPR || code == GE_EXPR
- || ((code == LT_EXPR || code == GT_EXPR)
- && TREE_CODE (rhs) == INTEGER_CST))
- {
- /* For LT_EXPR and GT_EXPR, canonicalize to LE_EXPR and GE_EXPR. */
- if (code == LT_EXPR)
- rhs = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs),
- rhs, build_int_cst (TREE_TYPE (rhs), 1));
-
- if (code == GT_EXPR)
- rhs = fold_build2 (PLUS_EXPR, TREE_TYPE (rhs),
- rhs, build_int_cst (TREE_TYPE (rhs), 1));
-
- /* Determine the code we want to check for in the hash table. */
- enum tree_code test_code;
- if (code == GE_EXPR || code == GT_EXPR)
- test_code = LE_EXPR;
- else
- test_code = GE_EXPR;
-
- /* Update the dummy statement so we can query the hash tables. */
- gimple_cond_set_code (m_dummy_cond, test_code);
- gimple_cond_set_lhs (m_dummy_cond, lhs);
- gimple_cond_set_rhs (m_dummy_cond, rhs);
- tree cached_lhs
- = avail_exprs_stack->lookup_avail_expr (m_dummy_cond,
- false, false);
-
- /* If the lookup returned 1 (true), then the expression we
- queried was in the hash table. As a result there is only
- one value that makes the original conditional true. Update
- STMT accordingly. */
- if (cached_lhs && integer_onep (cached_lhs))
- {
- if (is_gimple_assign (stmt))
- {
- gimple_assign_set_rhs_code (stmt, EQ_EXPR);
- gimple_assign_set_rhs2 (stmt, rhs);
- gimple_set_modified (stmt, true);
- }
- else
- {
- gimple_set_modified (stmt, true);
- gimple_cond_set_code (as_a <gcond *> (stmt), EQ_EXPR);
- gimple_cond_set_rhs (as_a <gcond *> (stmt), rhs);
- gimple_set_modified (stmt, true);
- }
- }
- }
- }
-}
-
/* If STMT is a comparison of two uniform vectors reduce it to a comparison
of scalar objects, otherwise leave STMT unchanged. */
@@ -2283,24 +2212,6 @@ reduce_vector_comparison_to_scalar_comparison (gimple
*stmt)
}
}
-/* If possible, rewrite the conditional as TRUE or FALSE, and return
- the taken edge. Otherwise, return NULL. */
-
-edge
-dom_opt_dom_walker::fold_cond (gcond *cond)
-{
- simplify_using_ranges simplify (m_ranger);
- if (simplify.fold_cond (cond))
- {
- basic_block bb = gimple_bb (cond);
- if (gimple_cond_true_p (cond))
- return find_taken_edge (bb, boolean_true_node);
- if (gimple_cond_false_p (cond))
- return find_taken_edge (bb, boolean_false_node);
- }
- return NULL;
-}
-
/* Optimize the statement in block BB pointed to by iterator SI.
We try to perform some simplistic global redundancy elimination and
@@ -2437,24 +2348,6 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb,
gimple_stmt_iterator *si,
integer_zero_node));
gimple_set_modified (stmt, true);
}
- else if (TREE_CODE (lhs) == SSA_NAME)
- {
- /* Exploiting EVRP data is not yet fully integrated into DOM
- but we need to do something for this case to avoid regressing
- udr4.f90 and new1.C which have unexecutable blocks with
- undefined behavior that get diagnosed if they're left in the
- IL because we've attached range information to new
- SSA_NAMES. */
- update_stmt_if_modified (stmt);
- edge taken_edge = fold_cond (as_a <gcond *> (stmt));
- if (taken_edge)
- {
- gimple_set_modified (stmt, true);
- update_stmt (stmt);
- cfg_altered = true;
- return taken_edge;
- }
- }
}
update_stmt_if_modified (stmt);
@@ -2509,7 +2402,9 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb,
gimple_stmt_iterator *si,
/* If this statement was not redundant, we may still be able to simplify
it, which may in turn allow other part of DOM or other passes to do
a better job. */
- test_for_singularity (stmt, m_avail_exprs_stack);
+ if (!gimple_modified_p (stmt))
+ simplify_stmt (si);
+ stmt = gsi_stmt (*si);
}
/* Record any additional equivalences created by this statement. */
--
2.53.0