diff options
author | Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> | 2004-07-17 20:08:10 +0200 |
---|---|---|
committer | Zdenek Dvorak <rakdver@gcc.gnu.org> | 2004-07-17 18:08:10 +0000 |
commit | 8a807136e16752e8024f34967cf2071e4c1c284f (patch) | |
tree | f9b4d8d5ff8c3cf2b8b7d8b0817c4d09fca2073d /gcc/tree-cfg.c | |
parent | 0e242c8215a01f83fd09116711e8ec13e5341d93 (diff) | |
download | gcc-8a807136e16752e8024f34967cf2071e4c1c284f.zip gcc-8a807136e16752e8024f34967cf2071e4c1c284f.tar.gz gcc-8a807136e16752e8024f34967cf2071e4c1c284f.tar.bz2 |
loop-init.c (loop_optimizer_init, [...]): Do not destroy dominance information.
* loop-init.c (loop_optimizer_init, loop_optimizer_finalize): Do not
destroy dominance information.
* passes.c (rest_of_handle_loop2): Free dominance information.
* tree-cfg.c (cleanup_tree_cfg): Remove unreachable blocks before
jump threading.
(thread_jumps): Update dominance information and remove unreachable
blocks.
* tree-ssa-phiopt.c (replace_phi_with_stmt): Update dominance
information and remove the unreachable block.
From-SVN: r84873
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index ac2d5da..c80dcf1 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -733,8 +733,8 @@ cleanup_tree_cfg (void) while (something_changed) { something_changed = cleanup_control_flow (); - something_changed |= thread_jumps (); something_changed |= delete_unreachable_blocks (); + something_changed |= thread_jumps (); } /* Merging the blocks creates no new opportunities for the other @@ -3904,7 +3904,7 @@ static bool thread_jumps (void) { edge e, next, last, old; - basic_block bb, dest, tmp; + basic_block bb, dest, tmp, old_dest, dom; tree phi; int arg; bool retval = false; @@ -3991,11 +3991,9 @@ thread_jumps (void) /* Perform the redirection. */ retval = true; + old_dest = e->dest; e = redirect_edge_and_branch (e, dest); - /* TODO -- updating dominators in this case is simple. */ - free_dominance_info (CDI_DOMINATORS); - if (!old) { /* Update PHI nodes. We know that the new argument should @@ -4009,6 +4007,49 @@ thread_jumps (void) add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e); } } + + /* Update the dominators. */ + if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK) + { + /* Remove the unreachable blocks (observe that if all blocks + were reachable before, only those in the path we threaded + over and did not have any predecessor outside of the path + become unreachable). */ + for (; old_dest != dest; old_dest = tmp) + { + tmp = old_dest->succ->dest; + + if (old_dest->pred) + break; + + delete_basic_block (old_dest); + } + /* If the dominator of the destination was in the path, set its + dominator to the start of the redirected edge. */ + if (get_immediate_dominator (CDI_DOMINATORS, old_dest) == NULL) + set_immediate_dominator (CDI_DOMINATORS, old_dest, bb); + + /* Now proceed like if we forwarded just over one edge at a time. + Algorithm for forwarding over edge A --> B then is + + if (idom (B) == A) + idom (B) = idom (A); + recount_idom (A); */ + + for (; old_dest != dest; old_dest = tmp) + { + tmp = old_dest->succ->dest; + + if (get_immediate_dominator (CDI_DOMINATORS, tmp) == old_dest) + { + dom = get_immediate_dominator (CDI_DOMINATORS, old_dest); + set_immediate_dominator (CDI_DOMINATORS, tmp, dom); + } + + dom = recount_dominator (CDI_DOMINATORS, old_dest); + set_immediate_dominator (CDI_DOMINATORS, old_dest, dom); + } + } } /* Reset the forwardable bit on our block since it's no longer in |