aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
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