diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/tree-ssa-threadupdate.c | 40 |
2 files changed, 47 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 690d4d9..55a43e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-07-03 Roger Sayle <roger@eyesopen.com> + + PR tree-optimization/26251 + * tree-ssa-threadupdate.c (redirection_block_p): New function. + (thread_block): When optimizing for size refuse to thread jumps + that would require duplication of blocks other than redirection + blocks. + 2006-07-03 Paolo Bonzini <bonzini@gnu.org> * configure.ac: Fix thinko in previous check-in. diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 444bbb7..0697ae4 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -1,5 +1,5 @@ /* Thread edges through blocks and update the control flow and SSA graphs. - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -652,6 +652,33 @@ redirect_edges (void **slot, void *data) return 1; } +/* Return true if this block has no executable statements other than + a simple ctrl flow instruction. When the number of outgoing edges + is one, this is equivalent to a "forwarder" block. */ + +static bool +redirection_block_p (basic_block bb) +{ + block_stmt_iterator bsi; + + /* Advance to the first executable statement. */ + bsi = bsi_start (bb); + while (!bsi_end_p (bsi) + && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR + || IS_EMPTY_STMT (bsi_stmt (bsi)))) + bsi_next (&bsi); + + /* Check if this is an empty block. */ + if (bsi_end_p (bsi)) + return true; + + /* Test that we've reached the terminating control statement. */ + return bsi_stmt (bsi) + && (TREE_CODE (bsi_stmt (bsi)) == COND_EXPR + || TREE_CODE (bsi_stmt (bsi)) == GOTO_EXPR + || TREE_CODE (bsi_stmt (bsi)) == SWITCH_EXPR); +} + /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB is reached via one or more specific incoming edges, we know which outgoing edge from BB will be traversed. @@ -699,6 +726,17 @@ thread_block (basic_block bb) be threaded to a duplicate of BB. */ bool all = true; + /* If optimizing for size, only thread this block if we don't have + to duplicate it or it's an otherwise empty redirection block. */ + if (optimize_size + && EDGE_COUNT (bb->preds) > 1 + && !redirection_block_p (bb)) + { + FOR_EACH_EDGE (e, ei, bb->preds) + e->aux = NULL; + return false; + } + /* To avoid scanning a linear array for the element we need we instead use a hash table. For normal code there should be no noticeable difference. However, if we have a block with a large number of |