DOM is using its simplify_binary_operation method to derive things
that ranger can do better.  Remove the function and let ranger do its
thing.

I added some functionality tests to make sure we don't mysteriously
stop handling cases simplify_binary_operation did.  Although that's
unlikely as ranger is pretty mature by now, and surely a regression
would pop up ;-).

Tested on ppc64le Linux.

OK for trunk?

gcc/ChangeLog:

        * tree-ssa-dom.cc (dom_opt_dom_walker::const_or_copy_of_stmt): New.
        (dom_opt_dom_walker::eliminate_redundant_computations): Ask it on
        a lookup miss.
        * tree-ssa-scopedtables.cc (simplify_binary_operation): Remove.
        (lookup_avail_expr): Do not call it.
        * tree-ssa-scopedtables.h (simplify_binary_operation): Remove.

gcc/testsuite/ChangeLog:

        * gcc.dg/tree-ssa/ssa-dom-simplify-2.c: New test.
---
 .../gcc.dg/tree-ssa/ssa-dom-simplify-2.c      | 100 ++++++++++++
 gcc/tree-ssa-dom.cc                           |  32 ++++
 gcc/tree-ssa-scopedtables.cc                  | 154 +-----------------
 gcc/tree-ssa-scopedtables.h                   |   5 -
 4 files changed, 133 insertions(+), 158 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-2.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-2.c
new file mode 100644
index 00000000000..b0985de9d56
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-simplify-2.c
@@ -0,0 +1,100 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fno-tree-vrp -fdump-tree-dom2" } */
+
+/* x <= 5 and y >= 10 where x < y is computed, so it is 1.  */
+
+int __GIMPLE (ssa,startwith("dom"))
+by_range_cmp (int x, int y)
+{
+  _Bool b;
+  int r;
+
+  __BB(2):
+  if (x_1(D) > 5)
+    goto __BB5;
+  else
+    goto __BB3;
+
+  __BB(3):
+  if (y_2(D) < 10)
+    goto __BB5;
+  else
+    goto __BB4;
+
+  __BB(4):
+  b_3 = x_1(D) < y_2(D);
+  r_4 = (int) b_3;
+  return r_4;
+
+  __BB(5):
+  return 0;
+}
+
+/* 1 <= x <= 3 and 4 <= y <= 8 where x / y is computed, so it is 0.  */
+
+int __GIMPLE (ssa,startwith("dom"))
+by_range_div (int x, int y)
+{
+  int q;
+
+  __BB(2):
+  if (x_1(D) > 3)
+    goto __BB7;
+  else
+    goto __BB3;
+
+  __BB(3):
+  if (x_1(D) < 1)
+    goto __BB7;
+  else
+    goto __BB4;
+
+  __BB(4):
+  if (y_2(D) > 8)
+    goto __BB7;
+  else
+    goto __BB5;
+
+  __BB(5):
+  if (y_2(D) < 4)
+    goto __BB7;
+  else
+    goto __BB6;
+
+  __BB(6):
+  q_3 = x_1(D) / y_2(D);
+  return q_3;
+
+  __BB(7):
+  return 7;
+}
+
+/* x == y where x & y and x - y are computed, so they are x and 0.  */
+
+int __GIMPLE (ssa,startwith("dom"))
+by_relation (int x, int y)
+{
+  int t;
+  int d;
+  int r;
+
+  __BB(2):
+  if (x_1(D) == y_2(D))
+    goto __BB3;
+  else
+    goto __BB4;
+
+  __BB(3):
+  t_3 = x_1(D) & y_2(D);
+  d_4 = x_1(D) - y_2(D);
+  r_5 = t_3 + d_4;
+  return r_5;
+
+  __BB(4):
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "x_1\\(D\\) < y_2\\(D\\)" "dom2" } } */
+/* { dg-final { scan-tree-dump-not "x_1\\(D\\) / y_2\\(D\\)" "dom2" } } */
+/* { dg-final { scan-tree-dump-not "x_1\\(D\\) & y_2\\(D\\)" "dom2" } } */
+/* { dg-final { scan-tree-dump-not "x_1\\(D\\) - y_2\\(D\\)" "dom2" } } */
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 7ff6b912be6..519661973ec 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -822,6 +822,7 @@ private:
   void record_equivalences_from_incoming_edge (basic_block);
   void eliminate_redundant_computations (gimple_stmt_iterator *);
   void record_equivalences_from_stmt (gimple *, int);
+  tree const_or_copy_of_stmt (gimple *);
 
   jump_threader *m_threader;
   gimple_ranger *m_ranger;
@@ -1789,6 +1790,33 @@ dom_opt_dom_walker::after_dom_children (basic_block bb)
   m_const_and_copies->pop_to_marker ();
 }
 
+/* Return the constant STMT computes, and barring that, an operand its
+   result is equivalent to.  NULL if neither.  */
+
+tree
+dom_opt_dom_walker::const_or_copy_of_stmt (gimple *stmt)
+{
+  if (tree val = m_ranger->value_of_stmt (stmt))
+    return val;
+
+  /* We could remove this gate, but we'd end up with tons of useless
+     replacements (casts, copies, etc).  Best to keep it to binops, which is
+     what the original code did.  */
+  if (!is_gimple_assign (stmt)
+      || gimple_assign_rhs_class (stmt) != GIMPLE_BINARY_RHS)
+    return NULL_TREE;
+
+  tree lhs = gimple_assign_lhs (stmt);
+  tree rhs1 = gimple_assign_rhs1 (stmt);
+  tree rhs2 = gimple_assign_rhs2 (stmt);
+  if (m_ranger->relation ().query (stmt, lhs, rhs1) == VREL_EQ)
+    return rhs1;
+  if (m_ranger->relation ().query (stmt, lhs, rhs2) == VREL_EQ)
+    return rhs2;
+
+  return NULL_TREE;
+}
+
 /* Search for redundant computations in STMT.  If any are found, then
    replace them with the variable holding the result of the computation.
 
@@ -1824,6 +1852,10 @@ dom_opt_dom_walker::eliminate_redundant_computations 
(gimple_stmt_iterator *gsi)
   /* Check if the expression has been computed before.  */
   cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, insert, true);
 
+  /* Otherwise, ask the ranger.  */
+  if (!cached_lhs)
+    cached_lhs = const_or_copy_of_stmt (stmt);
+
   opt_stats.num_exprs_considered++;
 
   /* Get the type of the expression we are trying to optimize.  */
diff --git a/gcc/tree-ssa-scopedtables.cc b/gcc/tree-ssa-scopedtables.cc
index 242d3f0e7cc..35ce7586d8b 100644
--- a/gcc/tree-ssa-scopedtables.cc
+++ b/gcc/tree-ssa-scopedtables.cc
@@ -108,153 +108,6 @@ vuse_eq (ao_ref *, tree vuse1, void *data)
   return NULL;
 }
 
-/* We looked for STMT in the hash table, but did not find it.
-
-   If STMT is an assignment from a binary operator, we may know something
-   about the operands relationship to each other which would allow
-   us to derive a constant value for the RHS of STMT.  */
-
-tree
-avail_exprs_stack::simplify_binary_operation (gimple *stmt,
-                                             class expr_hash_elt element)
-{
-  if (is_gimple_assign (stmt))
-    {
-      struct hashable_expr *expr = element.expr ();
-      if (expr->kind == EXPR_BINARY)
-       {
-         enum tree_code code = expr->ops.binary.op;
-
-         switch (code)
-           {
-           /* For these cases, if we know some relationships
-              between the operands, then we can simplify.  */
-           case MIN_EXPR:
-           case MAX_EXPR:
-             {
-               /* Build a simple equality expr and query the hash table
-                  for it.  */
-               struct hashable_expr expr;
-               expr.type = boolean_type_node;
-               expr.kind = EXPR_BINARY;
-               expr.ops.binary.op = LE_EXPR;
-               tree rhs1 = gimple_assign_rhs1 (stmt);
-               tree rhs2 = gimple_assign_rhs2 (stmt);
-               if (tree_swap_operands_p (rhs1, rhs2))
-                 std::swap (rhs1, rhs2);
-               expr.ops.binary.opnd0 = rhs1;
-               expr.ops.binary.opnd1 = rhs2;
-               class expr_hash_elt element2 (&expr, NULL_TREE);
-               expr_hash_elt **slot
-                 = m_avail_exprs->find_slot (&element2, NO_INSERT);
-
-               /* If the query was successful and returned a nonzero
-                  result, then we know the result of the MIN/MAX, even
-                  though it is not a constant value.  */
-               if (slot && *slot && integer_onep ((*slot)->lhs ()))
-                 return code == MIN_EXPR ? rhs1 : rhs2;
-
-               /* Try again, this time with GE_EXPR.  */
-               expr.ops.binary.op = GE_EXPR;
-               class expr_hash_elt element3 (&expr, NULL_TREE);
-               slot = m_avail_exprs->find_slot (&element3, NO_INSERT);
-
-               /* If the query was successful and returned a nonzero
-                  result, then we know the result of the MIN/MAX, even
-                  though it is not a constant value.  */
-               if (slot && *slot && integer_onep ((*slot)->lhs ()))
-                 return code == MIN_EXPR ? rhs2 : rhs1;
-
-               break;
-             }
-
-           /* For these cases, if we know the operands
-              are equal, then we know the result.  */
-           case BIT_IOR_EXPR:
-           case BIT_AND_EXPR:
-           case BIT_XOR_EXPR:
-           case MINUS_EXPR:
-           case TRUNC_DIV_EXPR:
-           case CEIL_DIV_EXPR:
-           case FLOOR_DIV_EXPR:
-           case ROUND_DIV_EXPR:
-           case EXACT_DIV_EXPR:
-           case TRUNC_MOD_EXPR:
-           case CEIL_MOD_EXPR:
-           case FLOOR_MOD_EXPR:
-           case ROUND_MOD_EXPR:
-             {
-               /* Build a simple equality expr and query the hash table
-                  for it.  */
-               struct hashable_expr expr;
-               expr.type = boolean_type_node;
-               expr.kind = EXPR_BINARY;
-               expr.ops.binary.op = EQ_EXPR;
-               tree rhs1 = gimple_assign_rhs1 (stmt);
-               tree rhs2 = gimple_assign_rhs2 (stmt);
-               if (tree_swap_operands_p (rhs1, rhs2))
-                 std::swap (rhs1, rhs2);
-               expr.ops.binary.opnd0 = rhs1;
-               expr.ops.binary.opnd1 = rhs2;
-               class expr_hash_elt element2 (&expr, NULL_TREE);
-               expr_hash_elt **slot
-                 = m_avail_exprs->find_slot (&element2, NO_INSERT);
-               tree result_type = TREE_TYPE (gimple_assign_lhs (stmt));
-
-               /* If the query was successful and returned a nonzero
-                  result, then we know that the operands of the binary
-                  expression are the same.  In many cases this allows
-                  us to compute a constant result of the expression
-                  at compile time, even if we do not know the exact
-                  values of the operands.  */
-               if (slot && *slot && integer_onep ((*slot)->lhs ()))
-                 {
-                   switch (code)
-                     {
-                     case BIT_IOR_EXPR:
-                     case BIT_AND_EXPR:
-                       return gimple_assign_rhs1 (stmt);
-
-                     case MINUS_EXPR:
-                       /* This is unsafe for certain floats even in non-IEEE
-                          formats.  In IEEE, it is unsafe because it does
-                          wrong for NaNs.  */
-                       if (FLOAT_TYPE_P (result_type)
-                           && HONOR_NANS (result_type))
-                         break;
-                       /* FALLTHRU */
-                     case BIT_XOR_EXPR:
-                     case TRUNC_MOD_EXPR:
-                     case CEIL_MOD_EXPR:
-                     case FLOOR_MOD_EXPR:
-                     case ROUND_MOD_EXPR:
-                       return build_zero_cst (result_type);
-
-                     case TRUNC_DIV_EXPR:
-                     case CEIL_DIV_EXPR:
-                     case FLOOR_DIV_EXPR:
-                     case ROUND_DIV_EXPR:
-                     case EXACT_DIV_EXPR:
-                       /* Avoid _Fract types where we can't build 1.  */
-                       if (ALL_FRACT_MODE_P (TYPE_MODE (result_type)))
-                         break;
-                       return build_one_cst (result_type);
-
-                     default:
-                       gcc_unreachable ();
-                     }
-                 }
-               break;
-             }
-
-           default:
-             break;
-           }
-       }
-    }
-  return NULL_TREE;
-}
-
 /* Search for an existing instance of STMT in the AVAIL_EXPRS_STACK table.
    If found, return its LHS. Otherwise insert STMT in the table and
    return NULL_TREE.
@@ -313,13 +166,8 @@ avail_exprs_stack::lookup_avail_expr (gimple *stmt, bool 
insert, bool tbaa_p,
       class expr_hash_elt *element2 = new expr_hash_elt (element);
       *slot = element2;
 
-      /* If we did not find the expression in the hash table, we may still
-        be able to produce a result for some expressions.  */
-      tree retval = avail_exprs_stack::simplify_binary_operation (stmt,
-                                                                 element);
-
       record_expr (element2, NULL, '2');
-      return retval;
+      return NULL_TREE;
     }
 
   /* If we found a redundant memory operation do an alias walk to
diff --git a/gcc/tree-ssa-scopedtables.h b/gcc/tree-ssa-scopedtables.h
index 0028b705145..c7989b2c88e 100644
--- a/gcc/tree-ssa-scopedtables.h
+++ b/gcc/tree-ssa-scopedtables.h
@@ -156,11 +156,6 @@ class avail_exprs_stack
   vec<std::pair<expr_hash_elt_t, expr_hash_elt_t> > m_stack;
   hash_table<expr_elt_hasher> *m_avail_exprs;
 
-  /* For some assignments where the RHS is a binary operator, if we know
-     a equality relationship between the operands, we may be able to compute
-     a result, even if we don't know the exact value of the operands.  */
-  tree simplify_binary_operation (gimple *, class expr_hash_elt);
-
   /* We do not allow copying this object or initializing one
      from another.  */
   avail_exprs_stack& operator= (const avail_exprs_stack&);
-- 
2.53.0

Reply via email to