diff options
author | Richard Sandiford <rsandifo@redhat.com> | 2005-01-22 17:52:44 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2005-01-22 17:52:44 +0000 |
commit | d7f3fc19903a41f07d22b0b7b38d06e16cff55b8 (patch) | |
tree | 1772c197ad2c8da8b3c610884def31e0650ecfba /gcc | |
parent | 111e0c9f4b0027d393f46fb8a5805fa2ac68283a (diff) | |
download | gcc-d7f3fc19903a41f07d22b0b7b38d06e16cff55b8.zip gcc-d7f3fc19903a41f07d22b0b7b38d06e16cff55b8.tar.gz gcc-d7f3fc19903a41f07d22b0b7b38d06e16cff55b8.tar.bz2 |
re PR tree-optimization/19484 (function pointer propagation fails for noreturn functions)
PR tree-optimization/19484
* tree-cfg.c (remove_fallthru_edge): New function.
(cleanup_control_flow): Remove fallthru edges from calls that are
now known not to return.
From-SVN: r94070
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/20050122-1.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/20050122-2.c | 19 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 30 |
5 files changed, 72 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1a9d9e6..69b5bc1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-01-22 Richard Sandiford <rsandifo@redhat.com> + + PR tree-optimization/19484 + * tree-cfg.c (remove_fallthru_edge): New function. + (cleanup_control_flow): Remove fallthru edges from calls that are + now known not to return. + 2005-01-20 Daniel Berlin <dberlin@dberlin.org> Fix PR tree-optimization/19038 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6b16fc8..c8930cb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-01-22 Richard Sandiford <rsandifo@redhat.com> + + PR tree-optimization/19484 + * gcc.c-torture/compile/20050122-[12].c: New tests. + 2005-01-22 Paul Brook <paul@codesourcery.com> * gfortran.dg/implicit_2.f90: New test. diff --git a/gcc/testsuite/gcc.c-torture/compile/20050122-1.c b/gcc/testsuite/gcc.c-torture/compile/20050122-1.c new file mode 100644 index 0000000..a70907d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20050122-1.c @@ -0,0 +1,12 @@ +/* From PR 19484. */ +extern void foo (void) __attribute__((noreturn)); +int n; + +void +g (void) +{ + void (*f) (void) = foo; + if (n) + f (); + n = 1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/20050122-2.c b/gcc/testsuite/gcc.c-torture/compile/20050122-2.c new file mode 100644 index 0000000..d73f624 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/20050122-2.c @@ -0,0 +1,19 @@ +/* Related to PR 19484. */ +extern void foo (void) __attribute__((noreturn)); +int n; + +void +g (void) +{ + __label__ lab; + void h (void) { if (n == 2) goto lab; } + void (*f1) (void) = foo; + void (*f2) (void) = h; + + f2 (); + if (n) + f1 (); + n = 1; + lab: + n++; +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index b69ec0c..4df5855 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -114,6 +114,7 @@ static void make_goto_expr_edges (basic_block); static edge tree_redirect_edge_and_branch (edge, basic_block); static edge tree_try_redirect_by_replacing_jump (edge, basic_block); static void split_critical_edges (void); +static bool remove_fallthru_edge (VEC(edge) *); /* Various helpers. */ static inline bool stmt_starts_bb_p (tree, tree); @@ -2059,7 +2060,7 @@ cleanup_control_flow (void) basic_block bb; block_stmt_iterator bsi; bool retval = false; - tree stmt; + tree stmt, call; FOR_EACH_BB (bb) { @@ -2072,6 +2073,17 @@ cleanup_control_flow (void) if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR) retval |= cleanup_control_expr_graph (bb, bsi); + + /* Check for indirect calls that have been turned into + noreturn calls. */ + call = get_call_expr_in (stmt); + if (call != 0 + && (call_expr_flags (call) & ECF_NORETURN) != 0 + && remove_fallthru_edge (bb->succs)) + { + free_dominance_info (CDI_DOMINATORS); + retval = true; + } } return retval; } @@ -2140,6 +2152,22 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi) return retval; } +/* Remove any fallthru edge from EV. Return true if an edge was removed. */ + +static bool +remove_fallthru_edge (VEC(edge) *ev) +{ + edge_iterator ei; + edge e; + + FOR_EACH_EDGE (e, ei, ev) + if ((e->flags & EDGE_FALLTHRU) != 0) + { + remove_edge (e); + return true; + } + return false; +} /* Given a basic block BB ending with COND_EXPR or SWITCH_EXPR, and a predicate VAL, return the edge that will be taken out of the block. |