if (cfun->stdarg)
return false;
+ /* No local variable nor structure field should escape to callees. */
+ FOR_EACH_REFERENCED_VAR (var, rvi)
+ {
+ if (!is_global_var (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;
+ }
+
return true;
}
/* Returns false when the function is not suitable for tail call optimization
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);
}
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;
+ }
}
/* 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))
+ if (TREE_CODE (var) != PARM_DECL
+ && auto_var_in_fn_p (var, cfun->decl)
+ && (ref_maybe_used_by_stmt_p (call, var)
+ || call_may_clobber_ref_p (call, var)))
return;
}