static bool
suitable_for_tail_opt_p (void)
{
- int i;
+ referenced_var_iterator rvi;
+ tree var;
if (current_function_stdarg)
return false;
/* No local variable nor structure field should be call-clobbered. We
ignore any kind of memory tag, as these are not real variables. */
- for (i = 0; i < (int) num_referenced_vars; i++)
+
+ FOR_EACH_REFERENCED_VAR (var, rvi)
{
- tree var = VEC_index (tree, referenced_vars, i);
- if (!(TREE_STATIC (var) || DECL_EXTERNAL (var))
- && (var_ann (var)->mem_tag_kind == NOT_A_TAG
- || var_ann (var)->mem_tag_kind == STRUCT_FIELD)
+ if (!is_global_var (var)
+ && (!MTAG_P (var) || TREE_CODE (var) == STRUCT_FIELD_TAG)
&& is_call_clobbered (var))
return false;
}
}
/* Checks whether the expression EXPR in stmt AT is independent of the
- statement pointed by BSI (in a sense that we already know EXPR's value
+ statement pointed to by BSI (in a sense that we already know EXPR's value
at BSI). We use the fact that we are only called from the chain of
basic blocks that have only single successor. Returns the expression
containing the value of EXPR at BSI. */
var = m_acc;
else
{
- stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
- build (MULT_EXPR, ret_type, m_acc, a));
+ stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+ build2 (MULT_EXPR, ret_type, m_acc, a));
tmp = create_tmp_var (ret_type, "acc_tmp");
add_referenced_tmp_var (tmp);
else
var = a;
- stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
- build (PLUS_EXPR, ret_type, a_acc, var));
+ stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+ build2 (PLUS_EXPR, ret_type, a_acc, var));
var = make_ssa_name (SSA_NAME_VAR (a_acc), stmt);
TREE_OPERAND (stmt, 0) = var;
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
if (m)
{
- stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
- build (MULT_EXPR, ret_type, m_acc, m));
+ stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+ build2 (MULT_EXPR, ret_type, m_acc, m));
var = make_ssa_name (SSA_NAME_VAR (m_acc), stmt);
TREE_OPERAND (stmt, 0) = var;
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
if (m)
{
- stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
- build (MULT_EXPR, ret_type, m_acc, ret_var));
+ stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+ build2 (MULT_EXPR, ret_type, m_acc, ret_var));
tmp = create_tmp_var (ret_type, "acc_tmp");
add_referenced_tmp_var (tmp);
if (a)
{
- stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
- build (PLUS_EXPR, ret_type, a_acc, var));
+ stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+ build2 (PLUS_EXPR, ret_type, a_acc, var));
tmp = create_tmp_var (ret_type, "acc_tmp");
add_referenced_tmp_var (tmp);
update_stmt (ret_stmt);
}
+/* Subtract COUNT and FREQUENCY from the basic block and it's
+ outgoing edge. */
+static void
+decrease_profile (basic_block bb, gcov_type count, int frequency)
+{
+ edge e;
+ bb->count -= count;
+ if (bb->count < 0)
+ bb->count = 0;
+ bb->frequency -= frequency;
+ if (bb->frequency < 0)
+ bb->frequency = 0;
+ if (!single_succ_p (bb))
+ {
+ gcc_assert (!EDGE_COUNT (bb->succs));
+ return;
+ }
+ e = single_succ_edge (bb);
+ e->count -= count;
+ if (e->count < 0)
+ e->count = 0;
+}
+
/* Eliminates tail call described by T. TMP_VARS is a list of
temporary variables used to copy the function arguments. */
release_defs (t);
}
+ /* Number of executions of function has reduced by the tailcall. */
+ e = single_succ_edge (t->call_block);
+ decrease_profile (EXIT_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
+ decrease_profile (ENTRY_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
+ if (e->dest != EXIT_BLOCK_PTR)
+ decrease_profile (e->dest, e->count, EDGE_FREQUENCY (e));
+
/* Replace the call by a jump to the start of function. */
e = redirect_edge_and_branch (single_succ_edge (t->call_block), first);
gcc_assert (e);
if (!phi)
{
- tree name = var_ann (param)->default_def;
+ tree name = default_def (param);
tree new_name;
if (!name)
}
new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
- var_ann (param)->default_def = new_name;
+ set_default_def (param, new_name);
phi = create_phi_node (name, first);
SSA_NAME_DEF_STMT (name) = phi;
add_phi_arg (phi, new_name, single_succ_edge (ENTRY_BLOCK_PTR));
if (!phis_constructed)
{
+ tree name;
/* Ensure that there is only one predecessor of the block. */
if (!single_pred_p (first))
first = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
&& var_ann (param)
/* Also parameters that are only defined but never used need not
be copied. */
- && (var_ann (param)->default_def
- && TREE_CODE (var_ann (param)->default_def) == SSA_NAME))
+ && ((name = default_def (param))
+ && TREE_CODE (name) == SSA_NAME))
{
- tree name = var_ann (param)->default_def;
tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
tree phi;
- var_ann (param)->default_def = new_name;
+ set_default_def (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));