diff options
author | Richard Guenther <rguenther@suse.de> | 2010-04-12 15:20:48 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2010-04-12 15:20:48 +0000 |
commit | d086d3119d95e23154679e6c6ca43b0356fd92df (patch) | |
tree | a5f4bc000b917f934f12c45b1b6e764ac0256de6 /gcc/tree-tailcall.c | |
parent | af961c7f461a46db81d59c997b513509f6e32ae8 (diff) | |
download | gcc-d086d3119d95e23154679e6c6ca43b0356fd92df.tar.gz |
gsstruct.def (GSS_CALL): New.
2010-04-12 Richard Guenther <rguenther@suse.de>
* gsstruct.def (GSS_CALL): New.
* gimple.def (GIMPLE_CALL): Change to GSS_CALL.
* gimple.h: Include tree-ssa-alias.h.
(struct gimple_statement_call): New.
(union gimple_statement_struct_d): Add gimple_call member.
(gimple_call_reset_alias_info): Declare.
(gimple_call_use_set): New function.
(gimple_call_clobber_set): Likewise.
* Makefile.in (GIMPLE_H): Add tree-ssa-alias.h.
* gimple.c (gimple_call_reset_alias_info): New function.
(gimple_build_call_1): Call it.
* lto-streamer-in.c (input_gimple_stmt): Likewise.
* tree-inline.c (remap_gimple_stmt): Likewise.
(expand_call_inline): Remove callused handling.
* cfgexpand.c (update_alias_info_with_stack_vars): Likewise.
* tree-dfa.c (dump_variable): Likewise.
* tree-parloops.c (parallelize_loops): Likewise.
* tree-ssa.c (init_tree_ssa): Likewise.
(delete_tree_ssa): Likewise.
* tree-flow-inline.h (is_call_used): Remove.
* tree-flow.h (struct gimple_df): Remove callused member.
* tree-nrv.c (dest_safe_for_nrv_p): Adjust predicate.
* tree-ssa-alias.c (dump_alias_info): Remove callused handling.
(ref_maybe_used_by_call_p_1): Simplify.
(call_may_clobber_ref_p_1): Likewise.
* tree-ssa-structalias.c (compute_points_to_sets): Set
the call stmt used and clobbered sets.
* tree-tailcall.c (suitable_for_tail_opt_p): Adjust predicate.
(find_tail_calls): Verify the tail call.
From-SVN: r158226
Diffstat (limited to 'gcc/tree-tailcall.c')
-rw-r--r-- | gcc/tree-tailcall.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 2ecca4aaae7..e0d3f4844e9 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -136,11 +136,23 @@ suitable_for_tail_opt_p (void) if (cfun->stdarg) return false; - /* No local variable nor structure field should be call-used. */ + /* No local variable nor structure field should escape to callees. */ FOR_EACH_REFERENCED_VAR (var, rvi) { if (!is_global_var (var) - && is_call_used (var)) + /* ??? We do not have a suitable predicate for escaping to + callees. With IPA-PTA the following might be incorrect. + We want to catch + foo { + int i; + bar (&i); + foo (); + } + where bar might store &i somewhere and in the next + recursion should not be able to tell if it got the + same (with tail-recursion applied) or a different + address. */ + && is_call_clobbered (var)) return false; } @@ -430,7 +442,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret) func = gimple_call_fndecl (call); if (func == current_function_decl) { - tree arg; + tree arg, var; + referenced_var_iterator rvi; + for (param = DECL_ARGUMENTS (func), idx = 0; param && idx < gimple_call_num_args (call); param = TREE_CHAIN (param), idx ++) @@ -460,6 +474,15 @@ find_tail_calls (basic_block bb, struct tailcall **ret) } if (idx == gimple_call_num_args (call) && !param) tail_recursion = true; + + /* Make sure the tail invocation of this function does not refer + to local variables. */ + FOR_EACH_REFERENCED_VAR (var, rvi) + { + if (!is_global_var (var) + && ref_maybe_used_by_stmt_p (call, var)) + return; + } } /* Now check the statements after the call. None of them has virtual |