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
This commit is contained in:
Richard Sandiford 2005-01-22 17:52:44 +00:00 committed by Richard Sandiford
parent 111e0c9f4b
commit d7f3fc1990
5 changed files with 72 additions and 1 deletions

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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++;
}

View File

@ -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.