aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2017-03-16 13:21:33 -0600
committerJeff Law <law@gcc.gnu.org>2017-03-16 13:21:33 -0600
commitc87550223ac148a5c50b7b3c785ef1f1f5ffd3ac (patch)
tree2015d481070a9147dbdeef1dd1ffd15cc2a515b3 /gcc/tree-vrp.c
parent8d7437be4725af093548429f6e4c80a7867cdb41 (diff)
downloadgcc-c87550223ac148a5c50b7b3c785ef1f1f5ffd3ac.zip
gcc-c87550223ac148a5c50b7b3c785ef1f1f5ffd3ac.tar.gz
gcc-c87550223ac148a5c50b7b3c785ef1f1f5ffd3ac.tar.bz2
re PR tree-optimization/71437 (Performance regression after r235817)
PR tree-optimization/71437 * tree-ssa-dom.c (dom_opt_dom_walker): Remove thread_across_edge member function. Implementation moved into after_dom_children member function and into the threader's thread_outgoing_edges function. (dom_opt_dom_walker::after_dom_children): Simplify by moving some code into new thread_outgoing_edges. * tree-ssa-threadedge.c (thread_across_edge): Make static and simplify definition. Simplify marker handling (do it here). Assume we always have the available expression and the const/copies tables. (thread_outgoing_edges): New function extracted from tree-ssa-dom.c and tree-vrp.c * tree-ssa-threadedge.h (thread_outgoing_edges): Declare. * tree-vrp.c (equiv_stack): No longer file scoped. (vrp_dom_walker): New class. (vrp_dom_walker::before_dom_children): New member function. (vrp_dom_walker::after_dom_children): Likewise. (identify_jump_threads): Setup domwalker. Use it rather than walking edges in a random order by hand. Simplify setup/finalization. (finalize_jump_threads): Remove. (vrp_finalize): Do not call identify_jump_threads here. (execute_vrp): Do it here instead and call thread_through_all_blocks here too. From-SVN: r246208
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c171
1 files changed, 88 insertions, 83 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 82ef742..4a09a57 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -10746,9 +10746,6 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
return simplify_stmt_using_ranges (si);
}
-/* Unwindable const/copy equivalences. */
-const_and_copies *equiv_stack;
-
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
BB. If no such ASSERT_EXPR is found, return OP. */
@@ -10879,6 +10876,74 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
return NULL_TREE;
}
+class vrp_dom_walker : public dom_walker
+{
+public:
+ vrp_dom_walker (cdi_direction direction,
+ class const_and_copies *const_and_copies,
+ class avail_exprs_stack *avail_exprs_stack)
+ : dom_walker (direction, true),
+ m_const_and_copies (const_and_copies),
+ m_avail_exprs_stack (avail_exprs_stack),
+ m_dummy_cond (NULL) {}
+
+ virtual edge before_dom_children (basic_block);
+ virtual void after_dom_children (basic_block);
+
+private:
+ class const_and_copies *m_const_and_copies;
+ class avail_exprs_stack *m_avail_exprs_stack;
+
+ gcond *m_dummy_cond;
+};
+
+/* Called before processing dominator children of BB. We want to look
+ at ASSERT_EXPRs and record information from them in the appropriate
+ tables.
+
+ We could look at other statements here. It's not seen as likely
+ to significantly increase the jump threads we discover. */
+
+edge
+vrp_dom_walker::before_dom_children (basic_block bb)
+{
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (gimple_assign_rhs1 (stmt)) == ASSERT_EXPR)
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ tree rhs1 = gimple_assign_rhs1 (stmt);
+ m_const_and_copies->record_const_or_copy (lhs,
+ TREE_OPERAND (rhs1, 0));
+ continue;
+ }
+ break;
+ }
+ return NULL;
+}
+
+/* Called after processing dominator children of BB. This is where we
+ actually call into the threader. */
+void
+vrp_dom_walker::after_dom_children (basic_block bb)
+{
+ if (!m_dummy_cond)
+ m_dummy_cond = gimple_build_cond (NE_EXPR,
+ integer_zero_node, integer_zero_node,
+ NULL, NULL);
+
+ thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
+ m_avail_exprs_stack,
+ simplify_stmt_for_jump_threading);
+
+ m_avail_exprs_stack->pop_to_marker ();
+ m_const_and_copies->pop_to_marker ();
+}
+
/* Blocks which have more than one predecessor and more than
one successor present jump threading opportunities, i.e.,
when the block is reached from a specific predecessor, we
@@ -10902,8 +10967,6 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
static void
identify_jump_threads (void)
{
- basic_block bb;
- gcond *dummy;
int i;
edge e;
@@ -10926,69 +10989,15 @@ identify_jump_threads (void)
/* Allocate our unwinder stack to unwind any temporary equivalences
that might be recorded. */
- equiv_stack = new const_and_copies ();
-
- /* To avoid lots of silly node creation, we create a single
- conditional and just modify it in-place when attempting to
- thread jumps. */
- dummy = gimple_build_cond (EQ_EXPR,
- integer_zero_node, integer_zero_node,
- NULL, NULL);
-
- /* Walk through all the blocks finding those which present a
- potential jump threading opportunity. We could set this up
- as a dominator walker and record data during the walk, but
- I doubt it's worth the effort for the classes of jump
- threading opportunities we are trying to identify at this
- point in compilation. */
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple *last;
+ const_and_copies *equiv_stack = new const_and_copies ();
- /* If the generic jump threading code does not find this block
- interesting, then there is nothing to do. */
- if (! potentially_threadable_block (bb))
- continue;
+ hash_table<expr_elt_hasher> *avail_exprs
+ = new hash_table<expr_elt_hasher> (1024);
+ avail_exprs_stack *avail_exprs_stack
+ = new class avail_exprs_stack (avail_exprs);
- last = last_stmt (bb);
-
- /* We're basically looking for a switch or any kind of conditional with
- integral or pointer type arguments. Note the type of the second
- argument will be the same as the first argument, so no need to
- check it explicitly.
-
- We also handle the case where there are no statements in the
- block. This come up with forwarder blocks that are not
- optimized away because they lead to a loop header. But we do
- want to thread through them as we can sometimes thread to the
- loop exit which is obviously profitable. */
- if (!last
- || gimple_code (last) == GIMPLE_SWITCH
- || (gimple_code (last) == GIMPLE_COND
- && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
- && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
- || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))))
- && (TREE_CODE (gimple_cond_rhs (last)) == SSA_NAME
- || is_gimple_min_invariant (gimple_cond_rhs (last)))))
- {
- edge_iterator ei;
-
- /* We've got a block with multiple predecessors and multiple
- successors which also ends in a suitable conditional or
- switch statement. For each predecessor, see if we can thread
- it to a specific successor. */
- FOR_EACH_EDGE (e, ei, bb->preds)
- {
- /* Do not thread across edges marked to ignoreor abnormal
- edges in the CFG. */
- if (e->flags & (EDGE_IGNORE | EDGE_COMPLEX))
- continue;
-
- thread_across_edge (dummy, e, equiv_stack, NULL,
- simplify_stmt_for_jump_threading);
- }
- }
- }
+ vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack);
+ walker.walk (cfun->cfg->x_entry_block_ptr);
/* Clear EDGE_IGNORE. */
FOR_EACH_VEC_ELT (to_remove_edges, i, e)
@@ -10997,19 +11006,8 @@ identify_jump_threads (void)
/* We do not actually update the CFG or SSA graphs at this point as
ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
handle ASSERT_EXPRs gracefully. */
-}
-
-/* We identified all the jump threading opportunities earlier, but could
- not transform the CFG at that time. This routine transforms the
- CFG and arranges for the dominator tree to be rebuilt if necessary.
-
- Note the SSA graph update will occur during the normal TODO
- processing by the pass manager. */
-static void
-finalize_jump_threads (void)
-{
- thread_through_all_blocks (false);
delete equiv_stack;
+ delete avail_exprs_stack;
}
/* Free VRP lattice. */
@@ -11075,10 +11073,6 @@ vrp_finalize (bool warn_array_bounds_p)
if (warn_array_bounds && warn_array_bounds_p)
check_all_array_refs ();
-
- /* We must identify jump threading opportunities before we release
- the datastructures built by VRP. */
- identify_jump_threads ();
}
/* evrp_dom_walker visits the basic blocks in the dominance order and set
@@ -11670,6 +11664,11 @@ execute_vrp (bool warn_array_bounds_p)
vrp_initialize ();
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
vrp_finalize (warn_array_bounds_p);
+
+ /* We must identify jump threading opportunities before we release
+ the datastructures built by VRP. */
+ identify_jump_threads ();
+
vrp_free_lattice ();
free_numbers_of_iterations_estimates (cfun);
@@ -11686,7 +11685,13 @@ execute_vrp (bool warn_array_bounds_p)
duplication and CFG manipulation. */
update_ssa (TODO_update_ssa);
- finalize_jump_threads ();
+ /* We identified all the jump threading opportunities earlier, but could
+ not transform the CFG at that time. This routine transforms the
+ CFG and arranges for the dominator tree to be rebuilt if necessary.
+
+ Note the SSA graph update will occur during the normal TODO
+ processing by the pass manager. */
+ thread_through_all_blocks (false);
/* Remove dead edges from SWITCH_EXPR optimization. This leaves the
CFG in a broken state and requires a cfg_cleanup run. */