split_function (struct split_point *split_point)
{
VEC (tree, heap) *args_to_pass = NULL;
- bitmap args_to_skip = BITMAP_ALLOC (NULL);
+ bitmap args_to_skip;
tree parm;
int num = 0;
- struct cgraph_node *node;
+ struct cgraph_node *node, *cur_node = cgraph_get_node (current_function_decl);
basic_block return_bb = find_return_bb ();
basic_block call_bb;
gimple_stmt_iterator gsi;
tree retval = NULL, real_retval = NULL;
bool split_part_return_p = false;
gimple last_stmt = NULL;
- bool conv_needed = false;
unsigned int i;
tree arg;
dump_split_point (dump_file, split_point);
}
+ if (cur_node->local.can_change_signature)
+ args_to_skip = BITMAP_ALLOC (NULL);
+ else
+ args_to_skip = NULL;
+
/* Collect the parameters of new function and args_to_skip bitmap. */
for (parm = DECL_ARGUMENTS (current_function_decl);
parm; parm = DECL_CHAIN (parm), num++)
- if (!is_gimple_reg (parm)
- || !gimple_default_def (cfun, parm)
- || !bitmap_bit_p (split_point->ssa_names_to_pass,
- SSA_NAME_VERSION (gimple_default_def (cfun, parm))))
+ if (args_to_skip
+ && (!is_gimple_reg (parm)
+ || !gimple_default_def (cfun, parm)
+ || !bitmap_bit_p (split_point->ssa_names_to_pass,
+ SSA_NAME_VERSION (gimple_default_def (cfun,
+ parm)))))
bitmap_set_bit (args_to_skip, num);
else
{
- arg = gimple_default_def (cfun, parm);
- if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
- != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
+ /* This parm might not have been used up to now, but is going to be
+ used, hence register it. */
+ add_referenced_var (parm);
+ if (is_gimple_reg (parm))
{
- conv_needed = true;
- arg = fold_convert (DECL_ARG_TYPE (parm), arg);
+ arg = gimple_default_def (cfun, parm);
+ if (!arg)
+ {
+ arg = make_ssa_name (parm, gimple_build_nop ());
+ set_default_def (parm, arg);
+ }
}
+ else
+ arg = parm;
+
+ if (!useless_type_conversion_p (DECL_ARG_TYPE (parm), TREE_TYPE (arg)))
+ arg = fold_convert (DECL_ARG_TYPE (parm), arg);
VEC_safe_push (tree, heap, args_to_pass, arg);
}
/* Now create the actual clone. */
rebuild_cgraph_edges ();
- node = cgraph_function_versioning (cgraph_get_node (current_function_decl),
- NULL, NULL,
- args_to_skip,
+ node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip,
split_point->split_bbs,
split_point->entry_bb, "part");
/* For usual cloning it is enough to clear builtin only when signature
DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
}
- cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
+ cgraph_node_remove_callees (cur_node);
if (!split_part_return_p)
TREE_THIS_VOLATILE (node->decl) = 1;
if (dump_file)
/* Produce the call statement. */
gsi = gsi_last_bb (call_bb);
- if (conv_needed)
- FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
- if (!is_gimple_val (arg))
- {
- arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
- false, GSI_NEW_STMT);
- VEC_replace (tree, args_to_pass, i, arg);
- }
+ FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
+ if (!is_gimple_val (arg))
+ {
+ arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
+ false, GSI_CONTINUE_LINKING);
+ VEC_replace (tree, args_to_pass, i, arg);
+ }
call = gimple_build_call_vec (node->decl, args_to_pass);
gimple_set_block (call, DECL_INITIAL (current_function_decl));
}
}
if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
- gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+ {
+ gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+ gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+ }
else
- gimple_call_set_lhs (call, retval);
+ {
+ tree restype;
+ restype = TREE_TYPE (DECL_RESULT (current_function_decl));
+ gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+ if (!useless_type_conversion_p (TREE_TYPE (retval), restype))
+ {
+ gimple cpy;
+ tree tem = create_tmp_reg (restype, NULL);
+ tem = make_ssa_name (tem, call);
+ cpy = gimple_build_assign_with_ops (NOP_EXPR, retval,
+ tem, NULL_TREE);
+ gsi_insert_after (&gsi, cpy, GSI_NEW_STMT);
+ retval = tem;
+ }
+ gimple_call_set_lhs (call, retval);
+ update_stmt (call);
+ }
}
- gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+ else
+ gsi_insert_after (&gsi, call, GSI_NEW_STMT);
}
/* We don't use return block (there is either no return in function or
multiple of them). So create new basic block with return statement.
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
+ TODO_verify_all /* todo_flags_finish */
}
};
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
+ TODO_verify_all /* todo_flags_finish */
}
};