#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"
#include "tree-dump.h"
-#include "diagnostic.h"
+#include "gimple-pretty-print.h"
#include "except.h"
#include "tree-pass.h"
#include "flags.h"
static bool
suitable_for_tail_opt_p (void)
{
- referenced_var_iterator rvi;
- tree var;
-
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
but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */
for (param = DECL_ARGUMENTS (current_function_decl);
param;
- param = TREE_CHAIN (param))
+ param = DECL_CHAIN (param))
if (TREE_ADDRESSABLE (param))
return false;
tree m, a;
basic_block abb;
size_t idx;
+ tree var;
+ referenced_var_iterator rvi;
if (!single_succ_p (bb))
return;
func = gimple_call_fndecl (call);
if (func == current_function_decl)
{
- tree arg, var;
- referenced_var_iterator rvi;
+ tree arg;
for (param = DECL_ARGUMENTS (func), idx = 0;
param && idx < gimple_call_num_args (call);
- param = TREE_CHAIN (param), idx ++)
+ param = DECL_CHAIN (param), idx ++)
{
arg = gimple_call_arg (call, idx);
if (param != arg)
}
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 (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;
}
/* Now check the statements after the call. None of them has virtual
{
tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
- tree tmp = create_tmp_var (ret_type, label);
+ tree tmp = create_tmp_reg (ret_type, label);
gimple stmt;
tree result;
- if (TREE_CODE (ret_type) == COMPLEX_TYPE
- || TREE_CODE (ret_type) == VECTOR_TYPE)
- DECL_GIMPLE_REG_P (tmp) = 1;
add_referenced_var (tmp);
if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
for (param = DECL_ARGUMENTS (current_function_decl),
idx = 0, gsi = gsi_start_phis (first);
param;
- param = TREE_CHAIN (param), idx++)
+ param = DECL_CHAIN (param), idx++)
{
if (!arg_needs_copy_p (param))
continue;
create_tailcall_accumulator (const char *label, basic_block bb, tree init)
{
tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
- tree tmp = create_tmp_var (ret_type, label);
+ tree tmp = create_tmp_reg (ret_type, label);
gimple phi;
- if (TREE_CODE (ret_type) == COMPLEX_TYPE
- || TREE_CODE (ret_type) == VECTOR_TYPE)
- DECL_GIMPLE_REG_P (tmp) = 1;
add_referenced_var (tmp);
phi = create_phi_node (tmp, bb);
/* RET_TYPE can be a float when -ffast-maths is enabled. */
/* Copy the args if needed. */
for (param = DECL_ARGUMENTS (current_function_decl);
param;
- param = TREE_CHAIN (param))
+ param = DECL_CHAIN (param))
if (arg_needs_copy_p (param))
{
tree name = gimple_default_def (cfun, param);