mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-25 16:34:51 +08:00
re PR tree-optimization/19578 (function pointer propagation fails for noreturn functions (part 2))
PR tree-optimization/19578 * tree-flow.h (modified_noreturn_calls): Declare. (noreturn_call_p): Declare. * tree-flow-inline.h (noreturn_call_p): New function. (modify_stmt): Add modified noreturn calls to modified_noreturn_calls. * tree-cfg.c (modified_noreturn_calls): New variable. (cleanup_control_flow): Use noreturn_call_p. Split basic blocks that contain a mid-block noreturn call. * tree-ssa.c (delete_tree_ssa): Clear modified_noreturn_calls. From-SVN: r94610
This commit is contained in:
parent
d01da8bd5e
commit
7ded35b4c2
@ -1,3 +1,15 @@
|
||||
2005-02-02 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
PR tree-optimization/19578
|
||||
* tree-flow.h (modified_noreturn_calls): Declare.
|
||||
(noreturn_call_p): Declare.
|
||||
* tree-flow-inline.h (noreturn_call_p): New function.
|
||||
(modify_stmt): Add modified noreturn calls to modified_noreturn_calls.
|
||||
* tree-cfg.c (modified_noreturn_calls): New variable.
|
||||
(cleanup_control_flow): Use noreturn_call_p. Split basic blocks
|
||||
that contain a mid-block noreturn call.
|
||||
* tree-ssa.c (delete_tree_ssa): Clear modified_noreturn_calls.
|
||||
|
||||
2005-02-02 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* df.c (df_def_record_1, df_uses_record): Don't use
|
||||
|
@ -1,3 +1,8 @@
|
||||
2005-02-02 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
PR tree-optimization/19578
|
||||
* gcc.c-torture/compile/20050202-1.c: New test.
|
||||
|
||||
2005-02-02 Joseph S. Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/19435
|
||||
|
10
gcc/testsuite/gcc.c-torture/compile/20050202-1.c
Normal file
10
gcc/testsuite/gcc.c-torture/compile/20050202-1.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* From PR 19578. */
|
||||
extern void foo (void) __attribute__((noreturn));
|
||||
|
||||
void
|
||||
g (void)
|
||||
{
|
||||
void (*f) (void) = foo;
|
||||
f ();
|
||||
f ();
|
||||
}
|
@ -2052,6 +2052,14 @@ remove_bb (basic_block bb)
|
||||
remove_phi_nodes_and_edges_for_unreachable_block (bb);
|
||||
}
|
||||
|
||||
/* A list of all the noreturn calls passed to modify_stmt.
|
||||
cleanup_control_flow uses it to detect cases where a mid-block
|
||||
indirect call has been turned into a noreturn call. When this
|
||||
happens, all the instructions after the call are no longer
|
||||
reachable and must be deleted as dead. */
|
||||
|
||||
VEC(tree) *modified_noreturn_calls;
|
||||
|
||||
/* Try to remove superfluous control structures. */
|
||||
|
||||
static bool
|
||||
@ -2060,7 +2068,16 @@ cleanup_control_flow (void)
|
||||
basic_block bb;
|
||||
block_stmt_iterator bsi;
|
||||
bool retval = false;
|
||||
tree stmt, call;
|
||||
tree stmt;
|
||||
|
||||
/* Detect cases where a mid-block call is now known not to return. */
|
||||
while (VEC_length (tree, modified_noreturn_calls))
|
||||
{
|
||||
stmt = VEC_pop (tree, modified_noreturn_calls);
|
||||
bb = bb_for_stmt (stmt);
|
||||
if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
|
||||
split_block (bb, stmt);
|
||||
}
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
@ -2076,10 +2093,7 @@ cleanup_control_flow (void)
|
||||
|
||||
/* 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))
|
||||
if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
|
||||
{
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
retval = true;
|
||||
|
@ -131,6 +131,14 @@ get_filename (tree expr)
|
||||
return "???";
|
||||
}
|
||||
|
||||
/* Return true if T is a noreturn call. */
|
||||
static inline bool
|
||||
noreturn_call_p (tree t)
|
||||
{
|
||||
tree call = get_call_expr_in (t);
|
||||
return call != 0 && (call_expr_flags (call) & ECF_NORETURN) != 0;
|
||||
}
|
||||
|
||||
/* Mark statement T as modified. */
|
||||
static inline void
|
||||
modify_stmt (tree t)
|
||||
@ -138,6 +146,8 @@ modify_stmt (tree t)
|
||||
stmt_ann_t ann = stmt_ann (t);
|
||||
if (ann == NULL)
|
||||
ann = create_stmt_ann (t);
|
||||
else if (noreturn_call_p (t))
|
||||
VEC_safe_push (tree, modified_noreturn_calls, t);
|
||||
ann->modified = 1;
|
||||
}
|
||||
|
||||
|
@ -297,6 +297,8 @@ union tree_ann_d GTY((desc ("ann_type ((tree_ann_t)&%h)")))
|
||||
struct stmt_ann_d GTY((tag ("STMT_ANN"))) stmt;
|
||||
};
|
||||
|
||||
extern GTY(()) VEC(tree) *modified_noreturn_calls;
|
||||
|
||||
typedef union tree_ann_d *tree_ann_t;
|
||||
typedef struct var_ann_d *var_ann_t;
|
||||
typedef struct stmt_ann_d *stmt_ann_t;
|
||||
@ -310,6 +312,7 @@ static inline stmt_ann_t get_stmt_ann (tree);
|
||||
static inline enum tree_ann_type ann_type (tree_ann_t);
|
||||
static inline basic_block bb_for_stmt (tree);
|
||||
extern void set_bb_for_stmt (tree, basic_block);
|
||||
static inline bool noreturn_call_p (tree);
|
||||
static inline void modify_stmt (tree);
|
||||
static inline void unmodify_stmt (tree);
|
||||
static inline bool stmt_modified_p (tree);
|
||||
|
@ -766,6 +766,7 @@ delete_tree_ssa (void)
|
||||
call_clobbered_vars = NULL;
|
||||
BITMAP_XFREE (addressable_vars);
|
||||
addressable_vars = NULL;
|
||||
modified_noreturn_calls = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user