diff options
author | Jeff Law <law@redhat.com> | 2017-03-16 13:21:33 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2017-03-16 13:21:33 -0600 |
commit | c87550223ac148a5c50b7b3c785ef1f1f5ffd3ac (patch) | |
tree | 2015d481070a9147dbdeef1dd1ffd15cc2a515b3 /gcc/tree-ssa-threadedge.c | |
parent | 8d7437be4725af093548429f6e4c80a7867cdb41 (diff) | |
download | gcc-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-ssa-threadedge.c')
-rw-r--r-- | gcc/tree-ssa-threadedge.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 7f70b40..536c471 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -1100,16 +1100,18 @@ thread_through_normal_block (edge e, SIMPLIFY is a pass-specific function used to simplify statements. */ -void +static void thread_across_edge (gcond *dummy_cond, edge e, class const_and_copies *const_and_copies, class avail_exprs_stack *avail_exprs_stack, - tree (*simplify) (gimple *, gimple *, - class avail_exprs_stack *, basic_block)) + pfn_simplify simplify) { bitmap visited = BITMAP_ALLOC (NULL); + const_and_copies->push_marker (); + avail_exprs_stack->push_marker (); + stmt_count = 0; vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> (); @@ -1132,6 +1134,7 @@ thread_across_edge (gcond *dummy_cond, propagate_threaded_block_debug_into (path->last ()->e->dest, e->dest); const_and_copies->pop_to_marker (); + avail_exprs_stack->pop_to_marker (); BITMAP_FREE (visited); register_jump_thread (path); return; @@ -1156,6 +1159,7 @@ thread_across_edge (gcond *dummy_cond, { BITMAP_FREE (visited); const_and_copies->pop_to_marker (); + avail_exprs_stack->pop_to_marker (); return; } } @@ -1182,6 +1186,7 @@ thread_across_edge (gcond *dummy_cond, if (taken_edge->flags & EDGE_ABNORMAL) { const_and_copies->pop_to_marker (); + avail_exprs_stack->pop_to_marker (); BITMAP_FREE (visited); return; } @@ -1196,8 +1201,7 @@ thread_across_edge (gcond *dummy_cond, /* Push a fresh marker so we can unwind the equivalences created for each of E->dest's successors. */ const_and_copies->push_marker (); - if (avail_exprs_stack) - avail_exprs_stack->push_marker (); + avail_exprs_stack->push_marker (); /* Avoid threading to any block we have already visited. */ bitmap_clear (visited); @@ -1240,12 +1244,71 @@ thread_across_edge (gcond *dummy_cond, delete_jump_thread_path (path); /* And unwind the equivalence table. */ - if (avail_exprs_stack) - avail_exprs_stack->pop_to_marker (); + avail_exprs_stack->pop_to_marker (); const_and_copies->pop_to_marker (); } BITMAP_FREE (visited); } const_and_copies->pop_to_marker (); + avail_exprs_stack->pop_to_marker (); +} + +/* Examine the outgoing edges from BB and conditionally + try to thread them. + + DUMMY_COND is a shared cond_expr used by condition simplification as scratch, + to avoid allocating memory. + + CONST_AND_COPIES is used to undo temporary equivalences created during the + walk of E->dest. + + The available expression table is referenced vai AVAIL_EXPRS_STACK. + + SIMPLIFY is a pass-specific function used to simplify statements. */ + +void +thread_outgoing_edges (basic_block bb, gcond *dummy_cond, + class const_and_copies *const_and_copies, + class avail_exprs_stack *avail_exprs_stack, + tree (*simplify) (gimple *, gimple *, + class avail_exprs_stack *, + basic_block)) +{ + int flags = (EDGE_IGNORE | EDGE_COMPLEX | EDGE_ABNORMAL); + gimple *last; + + /* If we have an outgoing edge to a block with multiple incoming and + outgoing edges, then we may be able to thread the edge, i.e., we + may be able to statically determine which of the outgoing edges + will be traversed when the incoming edge from BB is traversed. */ + if (single_succ_p (bb) + && (single_succ_edge (bb)->flags & flags) == 0 + && potentially_threadable_block (single_succ (bb))) + { + thread_across_edge (dummy_cond, single_succ_edge (bb), + const_and_copies, avail_exprs_stack, + simplify); + } + else if ((last = last_stmt (bb)) + && gimple_code (last) == GIMPLE_COND + && EDGE_COUNT (bb->succs) == 2 + && (EDGE_SUCC (bb, 0)->flags & flags) == 0 + && (EDGE_SUCC (bb, 1)->flags & flags) == 0) + { + edge true_edge, false_edge; + + extract_true_false_edges_from_block (bb, &true_edge, &false_edge); + + /* Only try to thread the edge if it reaches a target block with + more than one predecessor and more than one successor. */ + if (potentially_threadable_block (true_edge->dest)) + thread_across_edge (dummy_cond, true_edge, + const_and_copies, avail_exprs_stack, simplify); + + /* Similarly for the ELSE arm. */ + if (potentially_threadable_block (false_edge->dest)) + thread_across_edge (dummy_cond, false_edge, + const_and_copies, avail_exprs_stack, simplify); + } } |