summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-21 16:06:31 +0000
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-21 16:06:31 +0000
commit77aecf4bdbdaddffc6f3f80d609d58707b56d4b7 (patch)
tree516898685cab1732ef82fb735a8ba8f54a49646a /gcc/tree-cfg.c
parent1e8b248c365b50bfa64929c81cbbb1f2161ec08a (diff)
downloadgcc-77aecf4bdbdaddffc6f3f80d609d58707b56d4b7.tar.gz
* tree-cfg.c (thread_jumps): Speed up by using a worklist.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89381 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c103
1 files changed, 85 insertions, 18 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 3c4cd713146..d58bb13d9dd 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3942,35 +3942,102 @@ thread_jumps (void)
{
basic_block bb;
bool retval = false;
- bool rerun;
+ int *worklist = xmalloc (sizeof (int) * last_basic_block);
+ unsigned int size = 0;
FOR_EACH_BB (bb)
- bb_ann (bb)->forwardable = tree_forwarder_block_p (bb);
+ {
+ bb_ann (bb)->forwardable = tree_forwarder_block_p (bb);
+ bb->flags &= ~BB_VISITED;
+ }
- do
+ /* Initialize WORKLIST by putting the indexes of non-forwarder
+ blocks that immediately precede forwarder blocks because those
+ are the ones that we know we can thread jumps from. We use
+ BB_VISITED to indicate that whether a given basic block is in
+ WORKLIST or not, thereby avoiding duplicates in WORKLIST. */
+ FOR_EACH_BB (bb)
{
- rerun = false;
- FOR_EACH_BB (bb)
+ edge_iterator ei;
+ edge e;
+
+ /* We are not interested in finding non-forwarder blocks
+ directly. We want to find non-forwarder blocks as
+ predecessors of a forwarder block. */
+ if (!bb_ann (bb)->forwardable)
+ continue;
+
+ /* Now we know BB is a forwarder block. Visit each of its
+ incoming edges and add to WORKLIST all non-forwarder blocks
+ among BB's predecessors. */
+ FOR_EACH_EDGE (e, ei, bb->preds)
{
- /* Don't waste time on forwarders. */
- if (bb_ann (bb)->forwardable)
- continue;
+ /* We are not interested in threading jumps from a forwarder
+ block. */
+ if (!bb_ann (e->src)->forwardable
+ /* We don't want to visit ENTRY_BLOCK_PTR. */
+ && e->src->index >= 0
+ /* We don't want to put a duplicate into WORKLIST. */
+ && (e->src->flags & BB_VISITED) == 0)
+ {
+ e->src->flags |= BB_VISITED;
+ worklist[size] = e->src->index;
+ size++;
+ }
+ }
+ }
- if (thread_jumps_from_bb (bb))
+ /* Now let's drain WORKLIST. */
+ while (size > 0)
+ {
+ size--;
+ bb = BASIC_BLOCK (worklist[size]);
+
+ /* Check if BB is NULL because BB may have been deleted. This
+ could happen if BB is originally a non-forwarder block, later
+ becomes a forwarder block, and it is deleted when a jump is
+ threaded through it. */
+ if (!bb)
+ continue;
+
+ /* BB->INDEX is not longer in WORKLIST, so clear BB_VISITED. */
+ bb->flags &= ~BB_VISITED;
+
+ if (thread_jumps_from_bb (bb))
+ {
+ retval = true;
+
+ if (tree_forwarder_block_p (bb))
{
- retval = true;
+ edge_iterator ej;
+ edge f;
+
+ bb_ann (bb)->forwardable = true;
- /* If we succeeded in threading a jump at BB, update the
- forwardable mark as BB may have become a new
- forwarder block. This could happen if we have a
- useless "if" statement whose two arms eventually
- merge without any intervening statements. */
- if (tree_forwarder_block_p (bb))
- bb_ann (bb)->forwardable = rerun = true;
+ /* Attempts to thread through BB may have been blocked
+ because BB was not a forwarder block before. Now
+ that BB is a forwarder block, we should revisit BB's
+ predecessors. */
+ FOR_EACH_EDGE (f, ej, bb->preds)
+ {
+ /* We are not interested in threading jumps from a
+ forwarder block. */
+ if (!bb_ann (f->src)->forwardable
+ /* We don't want to visit ENTRY_BLOCK_PTR. */
+ && f->src->index >= 0
+ /* We don't want to put a duplicate into WORKLIST. */
+ && (f->src->flags & BB_VISITED) == 0)
+ {
+ f->src->flags |= BB_VISITED;
+ worklist[size] = f->src->index;
+ size++;
+ }
+ }
}
}
}
- while (rerun);
+
+ free (worklist);
return retval;
}