aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>2004-07-17 20:08:10 +0200
committerZdenek Dvorak <rakdver@gcc.gnu.org>2004-07-17 18:08:10 +0000
commit8a807136e16752e8024f34967cf2071e4c1c284f (patch)
treef9b4d8d5ff8c3cf2b8b7d8b0817c4d09fca2073d /gcc/tree-cfg.c
parent0e242c8215a01f83fd09116711e8ec13e5341d93 (diff)
downloadgcc-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.c51
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