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 | |
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
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/loop-init.c | 2 | ||||
-rw-r--r-- | gcc/passes.c | 2 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 51 | ||||
-rw-r--r-- | gcc/tree-ssa-phiopt.c | 12 |
5 files changed, 68 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50b998b..c86cd8e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-07-17 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> + + * 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. + 2004-07-17 Graham Stott <graham.stott@btinternet.com> * emit-rtl.c (reorder_insns): Don't set BB for a BARRIER insn. diff --git a/gcc/loop-init.c b/gcc/loop-init.c index ff441e8..35fa12e 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -55,7 +55,6 @@ loop_optimizer_init (FILE *dumpfile) { /* No loops. */ flow_loops_free (loops); - free_dominance_info (CDI_DOMINATORS); free (loops); return NULL; @@ -105,7 +104,6 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile) /* Clean up. */ flow_loops_free (loops); - free_dominance_info (CDI_DOMINATORS); free (loops); /* Checking. */ diff --git a/gcc/passes.c b/gcc/passes.c index 60b4c08..108d185 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1380,6 +1380,8 @@ rest_of_handle_loop2 (void) loop_optimizer_finalize (loops, dump_file); } + free_dominance_info (CDI_DOMINATORS); + /* Finalize layout changes. */ FOR_EACH_BB (bb) if (bb->next_bb != EXIT_BLOCK_PTR) 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 diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index bc14dc4..50c845e 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -236,6 +236,8 @@ static void replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb, basic_block cond_block, tree phi, tree new) { + basic_block block_to_remove; + /* Insert our new statement at the head of our block. */ bsi_insert_after (&bsi, new, BSI_NEW_STMT); @@ -250,21 +252,23 @@ replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb, release_phi_node (phi); bb_ann (bb)->phi_nodes = NULL; - /* Disconnect the edge leading into the empty block. That will - make the empty block unreachable and it will be removed later. */ + /* Remove the empty basic block. */ if (cond_block->succ->dest == bb) { cond_block->succ->flags |= EDGE_FALLTHRU; cond_block->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); - ssa_remove_edge (cond_block->succ->succ_next); + + block_to_remove = cond_block->succ->succ_next->dest; } else { cond_block->succ->succ_next->flags |= EDGE_FALLTHRU; cond_block->succ->succ_next->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE); - ssa_remove_edge (cond_block->succ); + + block_to_remove = cond_block->succ->dest; } + delete_basic_block (block_to_remove); /* Eliminate the COND_EXPR at the end of COND_BLOCK. */ bsi = bsi_last (cond_block); |