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