/* Tail call optimization on trees.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
This file is part of GCC.
#include "basic-block.h"
#include "function.h"
#include "tree-flow.h"
-#include "tree-dump.h"
#include "gimple-pretty-print.h"
#include "except.h"
#include "tree-pass.h"
#include "langhooks.h"
#include "dbgcnt.h"
#include "target.h"
+#include "cfgloop.h"
#include "common/common-target.h"
/* The file implements the tail recursion elimination. It is also used to
basic_block abb;
size_t idx;
tree var;
- referenced_var_iterator rvi;
if (!single_succ_p (bb))
return;
/* Make sure the tail invocation of this function does not refer
to local variables. */
- FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
+ FOR_EACH_LOCAL_DECL (cfun, idx, var)
{
if (TREE_CODE (var) != PARM_DECL
&& auto_var_in_fn_p (var, cfun->decl)
{
tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
- tree tmp = create_tmp_reg (ret_type, label);
+ tree result = make_temp_ssa_name (ret_type, NULL, label);
gimple stmt;
- tree result;
-
- add_referenced_var (tmp);
if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
- stmt = gimple_build_assign_with_ops (code, tmp, acc, op1);
+ stmt = gimple_build_assign_with_ops (code, result, acc, op1);
else
{
tree rhs = fold_convert (TREE_TYPE (acc),
op1));
rhs = force_gimple_operand_gsi (&gsi, rhs,
false, NULL, true, GSI_SAME_STMT);
- stmt = gimple_build_assign (NULL_TREE, rhs);
+ stmt = gimple_build_assign (result, rhs);
}
- result = make_ssa_name (tmp, stmt);
- gimple_assign_set_lhs (stmt, result);
- update_stmt (stmt);
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
return result;
}
gimple_stmt_iterator gsi)
{
gimple stmt;
- tree var;
+ tree var = copy_ssa_name (acc, NULL);
if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
- stmt = gimple_build_assign_with_ops (code, SSA_NAME_VAR (acc), acc, op1);
+ stmt = gimple_build_assign_with_ops (code, var, acc, op1);
else
{
tree rhs = fold_convert (TREE_TYPE (acc),
op1));
rhs = force_gimple_operand_gsi (&gsi, rhs,
false, NULL, false, GSI_CONTINUE_LINKING);
- stmt = gimple_build_assign (NULL_TREE, rhs);
+ stmt = gimple_build_assign (var, rhs);
}
- var = make_ssa_name (SSA_NAME_VAR (acc), stmt);
- gimple_assign_set_lhs (stmt, var);
- update_stmt (stmt);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
return var;
}
{
tree def;
- if (!is_gimple_reg (param) || !var_ann (param))
+ if (!is_gimple_reg (param))
return false;
/* Parameters that are only defined but never used need not be copied. */
- def = gimple_default_def (cfun, param);
+ def = ssa_default_def (cfun, param);
if (!def)
return false;
release_defs (call);
}
-/* Add phi nodes for the virtual operands defined in the function to the
- header of the loop created by tail recursion elimination.
-
- Originally, we used to add phi nodes only for call clobbered variables,
- as the value of the non-call clobbered ones obviously cannot be used
- or changed within the recursive call. However, the local variables
- from multiple calls now share the same location, so the virtual ssa form
- requires us to say that the location dies on further iterations of the loop,
- which requires adding phi nodes.
-*/
-static void
-add_virtual_phis (void)
-{
- referenced_var_iterator rvi;
- tree var;
-
- /* The problematic part is that there is no way how to know what
- to put into phi nodes (there in fact does not have to be such
- ssa name available). A solution would be to have an artificial
- use/kill for all virtual operands in EXIT node. Unless we have
- this, we cannot do much better than to rebuild the ssa form for
- possibly affected virtual ssa names from scratch. */
-
- FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
- {
- if (!is_gimple_reg (var) && gimple_default_def (cfun, var) != NULL_TREE)
- mark_sym_for_renaming (var);
- }
-}
-
/* Optimizes the tailcall described by T. If OPT_TAILCALLS is true, also
mark the tailcalls for the sibcall optimization. */
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_reg (ret_type, label);
+ tree tmp = make_temp_ssa_name (ret_type, NULL, label);
gimple phi;
- add_referenced_var (tmp);
phi = create_phi_node (tmp, bb);
/* RET_TYPE can be a float when -ffast-maths is enabled. */
add_phi_arg (phi, fold_convert (ret_type, init), single_pred_edge (bb),
param = DECL_CHAIN (param))
if (arg_needs_copy_p (param))
{
- tree name = gimple_default_def (cfun, param);
+ tree name = ssa_default_def (cfun, param);
tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
gimple phi;
- set_default_def (param, new_name);
+ set_ssa_default_def (cfun, param, new_name);
phi = create_phi_node (name, first);
- SSA_NAME_DEF_STMT (name) = phi;
add_phi_arg (phi, new_name, single_pred_edge (first),
EXPR_LOCATION (param));
}
}
if (changed)
- free_dominance_info (CDI_DOMINATORS);
+ {
+ /* We may have created new loops. Make them magically appear. */
+ if (current_loops)
+ loops_state_set (LOOPS_NEED_FIXUP);
+ free_dominance_info (CDI_DOMINATORS);
+ }
+ /* Add phi nodes for the virtual operands defined in the function to the
+ header of the loop created by tail recursion elimination. Do so
+ by triggering the SSA renamer. */
if (phis_constructed)
- add_virtual_phis ();
+ mark_virtual_operands_for_renaming (cfun);
+
if (changed)
return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
return 0;
{
GIMPLE_PASS,
"tailr", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_tail_calls, /* gate */
execute_tail_recursion, /* execute */
NULL, /* sub */
{
GIMPLE_PASS,
"tailc", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_tail_calls, /* gate */
execute_tail_calls, /* execute */
NULL, /* sub */