{
struct cgraph_edge *edge;
+ /* We always version the actual function and redirect through the aliases. */
+ if (node->alias)
+ return false;
+
/* There are a number of generic reasons functions cannot be versioned. We
also cannot remove parameters if there are type attributes such as fnspec
present. */
return false;
/* Removing arguments doesn't work if the function takes varargs
- or use __builtin_apply_args. */
+ or use __builtin_apply_args.
+ FIXME: handle this together with can_change_signature flag. */
for (edge = node->callees; edge; edge = edge->next_callee)
{
tree t = edge->callee->decl;
gcov_type direct_call_sum = 0;
struct cgraph_edge *e;
+ /* We look through aliases, so we clone the aliased function instead. */
+ if (node->alias)
+ return false;
+
/* We never clone functions that are not visible from outside.
FIXME: in future we should clone such functions when they are called with
different constants, but current ipcp implementation is not good on this.
struct ipa_node_params *info = IPA_NODE_REF (node);
enum ipa_lattice_type type;
- if (ipa_is_called_with_var_arguments (info))
+ if (ipa_is_called_with_var_arguments (info) || node->alias)
type = IPA_BOTTOM;
else if (node->local.local)
type = IPA_TOP;
for (cs = node->callees; cs; cs = cs->next_callee)
{
- struct ipa_node_params *callee_info = IPA_NODE_REF (cs->callee);
+ struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, NULL);
+ struct ipa_node_params *callee_info = IPA_NODE_REF (callee);
struct ipa_edge_args *args = IPA_EDGE_REF (cs);
if (ipa_is_called_with_var_arguments (callee_info)
{
dest_lat->type = new_lat.type;
dest_lat->constant = new_lat.constant;
- ipa_push_func_to_list (&wl, cs->callee);
+ ipa_push_func_to_list (&wl, callee);
}
if (ipcp_propagate_types (info, callee_info, jump_func, i))
- ipa_push_func_to_list (&wl, cs->callee);
+ ipa_push_func_to_list (&wl, callee);
}
}
}
/* Some lattices have changed from IPA_TOP to IPA_BOTTOM.
This change should be propagated. */
{
- gcc_assert (n_cloning_candidates);
+ /*gcc_assert (n_cloning_candidates);*/
ipcp_propagate_stage ();
}
if (dump_file)
{
struct ipa_node_params *orig_callee_info;
int i, count;
- struct cgraph_node *node = cs->callee, *orig;
+ struct cgraph_node *node = cgraph_function_or_thunk_node (cs->callee, NULL);
+ struct cgraph_node *orig;
if (!n_cloning_candidates)
return false;
int i;
VEC (cgraph_edge_p, heap) * redirect_callers;
VEC (ipa_replace_map_p,gc)* replace_trees;
- int node_callers, count;
+ int count;
tree parm_tree;
struct ipa_replace_map *replace_param;
fibheap_t heap;
dead_nodes = BITMAP_ALLOC (NULL);
- for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed)
- {
- if (node->count > max_count)
- max_count = node->count;
- overall_size += inline_summary (node)->self_size;
- }
+ FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+ {
+ if (node->count > max_count)
+ max_count = node->count;
+ overall_size += inline_summary (node)->self_size;
+ }
max_new_size = overall_size;
if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS))
if (!cs && cgraph_will_be_removed_from_program_if_no_direct_calls (node))
bitmap_set_bit (dead_nodes, node->uid);
- /* Compute how many callers node has. */
- node_callers = 0;
- for (cs = node->callers; cs != NULL; cs = cs->next_caller)
- node_callers++;
- redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers);
- for (cs = node->callers; cs != NULL; cs = cs->next_caller)
- if (!cs->indirect_inlining_edge)
- VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
+ redirect_callers = collect_callers_of_node (node);
/* Redirecting all the callers of the node to the
new versioned node. */
dump_function_to_file (node1->decl, dump_file, dump_flags);
for (cs = node->callees; cs; cs = cs->next_callee)
- if (cs->callee->aux)
- {
- fibheap_delete_node (heap, (fibnode_t) cs->callee->aux);
- cs->callee->aux = fibheap_insert (heap,
- ipcp_estimate_cloning_cost (cs->callee),
- cs->callee);
- }
+ {
+ struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, NULL);
+ if (callee->aux)
+ {
+ fibheap_delete_node (heap, (fibnode_t) callee->aux);
+ callee->aux = fibheap_insert (heap,
+ ipcp_estimate_cloning_cost (callee),
+ callee);
+ }
+ }
}
while (!fibheap_empty (heap))
wl = NULL;
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed)
+ if (node->analyzed && !node->alias)
{
struct ipa_node_params *info = IPA_NODE_REF (node);
/* Unreachable nodes should have been eliminated before ipcp and
for (cs = node->callees; cs; cs = cs->next_callee)
{
+ struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, NULL);
/* We do not need to bother analyzing calls to unknown
functions unless they may become known during lto/whopr. */
if (!cs->callee->analyzed && !flag_lto)
ipa_count_arguments (cs);
/* If the descriptor of the callee is not initialized yet, we have to do
it now. */
- if (cs->callee->analyzed)
- ipa_initialize_node_params (cs->callee);
+ if (callee->analyzed)
+ ipa_initialize_node_params (callee);
if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
- != ipa_get_param_count (IPA_NODE_REF (cs->callee)))
- ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
+ != ipa_get_param_count (IPA_NODE_REF (callee)))
+ ipa_set_called_with_variable_arg (IPA_NODE_REF (callee));
ipa_compute_jump_functions_for_edge (parms_info, cs);
}