[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

Reply via email to