aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dom.c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
committerIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
commite252b51ccde010cbd2a146485d8045103cd99533 (patch)
treee060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/tree-ssa-dom.c
parentf10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff)
parent104c05c5284b7822d770ee51a7d91946c7e56d50 (diff)
downloadgcc-e252b51ccde010cbd2a146485d8045103cd99533.zip
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r--gcc/tree-ssa-dom.c257
1 files changed, 143 insertions, 114 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 81abf35..49d8f96 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -585,19 +585,52 @@ record_edge_info (basic_block bb)
}
}
+class dom_jump_threader_simplifier : public jump_threader_simplifier
+{
+public:
+ dom_jump_threader_simplifier (vr_values *v,
+ avail_exprs_stack *avails)
+ : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
+
+private:
+ tree simplify (gimple *, gimple *, basic_block, jt_state *) override;
+ avail_exprs_stack *m_avail_exprs_stack;
+};
+
+tree
+dom_jump_threader_simplifier::simplify (gimple *stmt,
+ gimple *within_stmt,
+ basic_block bb,
+ jt_state *state)
+{
+ /* First see if the conditional is in the hash table. */
+ tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt,
+ false, true);
+ if (cached_lhs)
+ return cached_lhs;
+
+ return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
+}
class dom_opt_dom_walker : public dom_walker
{
public:
dom_opt_dom_walker (cdi_direction direction,
- class const_and_copies *const_and_copies,
- class avail_exprs_stack *avail_exprs_stack,
- gcond *dummy_cond)
- : dom_walker (direction, REACHABLE_BLOCKS),
- m_const_and_copies (const_and_copies),
- m_avail_exprs_stack (avail_exprs_stack),
- evrp_range_analyzer (true),
- m_dummy_cond (dummy_cond) { }
+ jump_threader *threader,
+ jt_state *state,
+ evrp_range_analyzer *analyzer,
+ const_and_copies *const_and_copies,
+ avail_exprs_stack *avail_exprs_stack)
+ : dom_walker (direction, REACHABLE_BLOCKS)
+ {
+ m_evrp_range_analyzer = analyzer;
+ 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;
+ }
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
@@ -608,9 +641,6 @@ private:
class const_and_copies *m_const_and_copies;
class avail_exprs_stack *m_avail_exprs_stack;
- /* VRP data. */
- class evrp_range_analyzer evrp_range_analyzer;
-
/* Dummy condition to avoid creating lots of throw away statements. */
gcond *m_dummy_cond;
@@ -619,6 +649,13 @@ private:
the statement is a conditional with a statically determined
value. */
edge optimize_stmt (basic_block, gimple_stmt_iterator *, bool *);
+
+
+ void test_for_singularity (gimple *, avail_exprs_stack *);
+
+ jump_threader *m_threader;
+ evrp_range_analyzer *m_evrp_range_analyzer;
+ jt_state *m_state;
};
/* Jump threading, redundancy elimination and const/copy propagation.
@@ -695,10 +732,8 @@ pass_dominator::execute (function *fun)
gcc.dg/tree-ssa/pr21417.c can't be threaded if loop preheader is
missing. We should improve jump threading in future then
LOOPS_HAVE_PREHEADERS won't be needed here. */
- loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
-
- /* Initialize the value-handle array. */
- threadedge_initialize_values ();
+ loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES
+ | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
/* We need accurate information regarding back edges in the CFG
for jump threading; this may include back edges that are not part of
@@ -715,12 +750,17 @@ pass_dominator::execute (function *fun)
FOR_EACH_BB_FN (bb, fun)
record_edge_info (bb);
- gcond *dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node,
- integer_zero_node, NULL, NULL);
-
/* Recursively walk the dominator tree optimizing statements. */
- dom_opt_dom_walker walker (CDI_DOMINATORS, const_and_copies,
- avail_exprs_stack, dummy_cond);
+ evrp_range_analyzer analyzer (true);
+ dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack);
+ jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
+ jump_threader threader (&simplifier, &state);
+ dom_opt_dom_walker walker (CDI_DOMINATORS,
+ &threader,
+ &state,
+ &analyzer,
+ const_and_copies,
+ avail_exprs_stack);
walker.walk (fun->cfg->x_entry_block_ptr);
/* Look for blocks where we cleared EDGE_EXECUTABLE on an outgoing
@@ -749,7 +789,7 @@ pass_dominator::execute (function *fun)
containing any edge leaving BB. */
if (found)
FOR_EACH_EDGE (e, ei, bb->succs)
- remove_jump_threads_including (e);
+ threader.remove_jump_threads_including (e);
}
}
@@ -773,7 +813,7 @@ pass_dominator::execute (function *fun)
free_all_edge_infos ();
/* Thread jumps, creating duplicate blocks as needed. */
- cfg_altered |= thread_through_all_blocks (may_peel_loop_headers_p);
+ cfg_altered |= threader.thread_through_all_blocks (may_peel_loop_headers_p);
if (cfg_altered)
free_dominance_info (CDI_DOMINATORS);
@@ -849,9 +889,6 @@ pass_dominator::execute (function *fun)
delete avail_exprs_stack;
delete const_and_copies;
- /* Free the value-handle array. */
- threadedge_finalize_values ();
-
return 0;
}
@@ -863,72 +900,6 @@ make_pass_dominator (gcc::context *ctxt)
return new pass_dominator (ctxt);
}
-/* A hack until we remove threading from tree-vrp.c and bring the
- simplification routine into the dom_opt_dom_walker class. */
-static class vr_values *x_vr_values;
-
-/* A trivial wrapper so that we can present the generic jump
- threading code with a simple API for simplifying statements.
-
- ?? This should be cleaned up. There's a virtually identical copy
- of this function in tree-vrp.c. */
-
-static tree
-simplify_stmt_for_jump_threading (gimple *stmt,
- gimple *within_stmt ATTRIBUTE_UNUSED,
- class avail_exprs_stack *avail_exprs_stack,
- basic_block bb ATTRIBUTE_UNUSED)
-{
- /* First query our hash table to see if the expression is available
- there. A non-NULL return value will be either a constant or another
- SSA_NAME. */
- tree cached_lhs = avail_exprs_stack->lookup_avail_expr (stmt, false, true);
- if (cached_lhs)
- return cached_lhs;
-
- /* If the hash table query failed, query VRP information. This is
- essentially the same as tree-vrp's simplification routine. The
- copy in tree-vrp is scheduled for removal in gcc-9. */
- if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
- {
- simplify_using_ranges simplifier (x_vr_values);
- return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- within_stmt);
- }
-
- if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
- {
- tree op = gimple_switch_index (switch_stmt);
- if (TREE_CODE (op) != SSA_NAME)
- return NULL_TREE;
-
- const value_range_equiv *vr = x_vr_values->get_value_range (op);
- return find_case_label_range (switch_stmt, vr);
- }
-
- if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
- {
- tree lhs = gimple_assign_lhs (assign_stmt);
- if (TREE_CODE (lhs) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || POINTER_TYPE_P (TREE_TYPE (lhs)))
- && stmt_interesting_for_vrp (stmt))
- {
- edge dummy_e;
- tree dummy_tree;
- value_range_equiv new_vr;
- x_vr_values->extract_range_from_stmt (stmt, &dummy_e,
- &dummy_tree, &new_vr);
- tree singleton;
- if (new_vr.singleton_p (&singleton))
- return singleton;
- }
- }
- return NULL;
-}
-
/* Valueize hook for gimple_fold_stmt_to_constant_1. */
static tree
@@ -1417,7 +1388,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index);
- evrp_range_analyzer.enter (bb);
+ m_evrp_range_analyzer->enter (bb);
/* Push a marker on the stacks of local information so that we know how
far to unwind when we finalize this block. */
@@ -1454,8 +1425,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
continue;
}
- /* Compute range information and optimize the stmt. */
- evrp_range_analyzer.record_ranges_from_stmt (gsi_stmt (gsi), false);
+ m_state->record_ranges_from_stmt (gsi_stmt (gsi), false);
bool removed_p = false;
taken_edge = this->optimize_stmt (bb, &gsi, &removed_p);
if (!removed_p)
@@ -1500,17 +1470,10 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
void
dom_opt_dom_walker::after_dom_children (basic_block bb)
{
- x_vr_values = &evrp_range_analyzer;
- thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
- m_avail_exprs_stack,
- &evrp_range_analyzer,
- simplify_stmt_for_jump_threading);
- x_vr_values = NULL;
-
- /* These remove expressions local to BB from the tables. */
+ m_threader->thread_outgoing_edges (bb);
m_avail_exprs_stack->pop_to_marker ();
m_const_and_copies->pop_to_marker ();
- evrp_range_analyzer.leave (bb);
+ m_evrp_range_analyzer->leave (bb);
}
/* Search for redundant computations in STMT. If any are found, then
@@ -1849,9 +1812,9 @@ cprop_into_stmt (gimple *stmt, vr_values *vr_values)
This is similar to code in VRP. */
-static void
-test_for_singularity (gimple *stmt, gcond *dummy_cond,
- avail_exprs_stack *avail_exprs_stack)
+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. */
@@ -1897,11 +1860,12 @@ test_for_singularity (gimple *stmt, gcond *dummy_cond,
test_code = GE_EXPR;
/* Update the dummy statement so we can query the hash tables. */
- gimple_cond_set_code (dummy_cond, test_code);
- gimple_cond_set_lhs (dummy_cond, lhs);
- gimple_cond_set_rhs (dummy_cond, rhs);
+ 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 (dummy_cond, false, false);
+ = 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
@@ -1927,6 +1891,66 @@ test_for_singularity (gimple *stmt, gcond *dummy_cond,
}
}
+/* If STMT is a comparison of two uniform vectors reduce it to a comparison
+ of scalar objects, otherwise leave STMT unchanged. */
+
+static void
+reduce_vector_comparison_to_scalar_comparison (gimple *stmt)
+{
+ if (gimple_code (stmt) == GIMPLE_COND)
+ {
+ tree lhs = gimple_cond_lhs (stmt);
+ tree rhs = gimple_cond_rhs (stmt);
+
+ /* We may have a vector comparison where both arms are uniform
+ vectors. If so, we can simplify the vector comparison down
+ to a scalar comparison. */
+ if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE)
+ {
+ /* If either operand is an SSA_NAME, then look back to its
+ defining statement to try and get at a suitable source. */
+ if (TREE_CODE (rhs) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
+ if (gimple_assign_single_p (def_stmt))
+ rhs = gimple_assign_rhs1 (def_stmt);
+ }
+
+ if (TREE_CODE (lhs) == SSA_NAME)
+ {
+ gimple *def_stmt = SSA_NAME_DEF_STMT (lhs);
+ if (gimple_assign_single_p (def_stmt))
+ lhs = gimple_assign_rhs1 (def_stmt);
+ }
+
+ /* Now see if they are both uniform vectors and if so replace
+ the vector comparison with a scalar comparison. */
+ tree rhs_elem = rhs ? uniform_vector_p (rhs) : NULL_TREE;
+ tree lhs_elem = lhs ? uniform_vector_p (lhs) : NULL_TREE;
+ if (rhs_elem && lhs_elem)
+ {
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Reducing vector comparison: ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ }
+
+ gimple_cond_set_rhs (as_a <gcond *>(stmt), rhs_elem);
+ gimple_cond_set_lhs (as_a <gcond *>(stmt), lhs_elem);
+ gimple_set_modified (stmt, true);
+
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "To scalar equivalent: ");
+ print_gimple_stmt (dump_file, stmt, 0);
+ fprintf (dump_file, "\n");
+ }
+ }
+ }
+ }
+}
+
/* Optimize the statement in block BB pointed to by iterator SI.
We try to perform some simplistic global redundancy elimination and
@@ -1966,11 +1990,16 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
}
+ /* STMT may be a comparison of uniform vectors that we can simplify
+ down to a comparison of scalars. Do that transformation first
+ so that all the scalar optimizations from here onward apply. */
+ reduce_vector_comparison_to_scalar_comparison (stmt);
+
update_stmt_if_modified (stmt);
opt_stats.num_stmts++;
/* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */
- cprop_into_stmt (stmt, &evrp_range_analyzer);
+ cprop_into_stmt (stmt, m_evrp_range_analyzer);
/* If the statement has been modified with constant replacements,
fold its RHS before checking for redundant computations. */
@@ -2068,8 +2097,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
SSA_NAMES. */
update_stmt_if_modified (stmt);
edge taken_edge = NULL;
- evrp_range_analyzer.vrp_visit_cond_stmt (as_a <gcond *> (stmt),
- &taken_edge);
+ m_evrp_range_analyzer->vrp_visit_cond_stmt
+ (as_a <gcond *> (stmt), &taken_edge);
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)
@@ -2136,7 +2165,7 @@ 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_dummy_cond, m_avail_exprs_stack);
+ test_for_singularity (stmt, m_avail_exprs_stack);
}
/* Record any additional equivalences created by this statement. */