#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "rtl.h"
#include "tm_p.h"
+#include "hard-reg-set.h"
#include "basic-block.h"
#include "function.h"
#include "tree-flow.h"
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