summaryrefslogtreecommitdiff
path: root/gcc/tree-tailcall.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-04-12 15:20:48 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-04-12 15:20:48 +0000
commitd086d3119d95e23154679e6c6ca43b0356fd92df (patch)
treea5f4bc000b917f934f12c45b1b6e764ac0256de6 /gcc/tree-tailcall.c
parentaf961c7f461a46db81d59c997b513509f6e32ae8 (diff)
downloadgcc-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.c29
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