diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02fae673e4e..8e551523644 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2013-06-24 Martin Jambor + + PR tree-optimization/57539 + * cgraphclones.c (cgraph_clone_node): Add parameter new_inlined_to, set + global.inlined_to of the new node to it. All callers changed. + * ipa-inline-transform.c (clone_inlined_nodes): New variable + inlining_into, pass it to cgraph_clone_node. + * ipa-prop.c (ipa_propagate_indirect_call_infos): Do not call + ipa_free_edge_args_substructures. + (ipa_edge_duplication_hook): Only add edges from inlined nodes to + rdesc linked list. Do not assert rdesc edges have inlined caller. + Assert we have found an rdesc in the rdesc list. + 2013-06-24 Richard Biener * pointer-set.h (struct pointer_set_t): Move here from diff --git a/gcc/cgraph.h b/gcc/cgraph.h index ef2a2a0a348..1e17cb70e8d 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -715,7 +715,7 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, unsigned, gcov_type, int, bool); struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type, int, bool, vec, - bool); + bool, struct cgraph_node *); tree clone_function_name (tree decl, const char *); struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node *old_node, vec, diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index d82eb371798..f2a57fc1d08 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -167,13 +167,19 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, function's profile to reflect the fact that part of execution is handled by node. When CALL_DUPLICATOIN_HOOK is true, the ipa passes are acknowledged about - the new clone. Otherwise the caller is responsible for doing so later. */ + the new clone. Otherwise the caller is responsible for doing so later. + + If the new node is being inlined into another one, NEW_INLINED_TO should be + the outline function the new one is (even indirectly) inlined to. All hooks + will see this in node's global.inlined_to, when invoked. Can be NULL if the + node is not inlined. */ struct cgraph_node * cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, bool update_original, vec redirect_callers, - bool call_duplication_hook) + bool call_duplication_hook, + struct cgraph_node *new_inlined_to) { struct cgraph_node *new_node = cgraph_create_empty_node (); struct cgraph_edge *e; @@ -195,6 +201,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, new_node->symbol.externally_visible = false; new_node->local.local = true; new_node->global = n->global; + new_node->global.inlined_to = new_inlined_to; new_node->rtl = n->rtl; new_node->count = count; new_node->frequency = n->frequency; @@ -307,7 +314,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, new_node = cgraph_clone_node (old_node, new_decl, old_node->count, CGRAPH_FREQ_BASE, false, - redirect_callers, false); + redirect_callers, false, NULL); /* Update the properties. Make clone visible only within this translation unit. Make sure that is not weak also. diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 9e131a4aa0e..d421c87c222 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -132,6 +132,13 @@ void clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, bool update_original, int *overall_size) { + struct cgraph_node *inlining_into; + + if (e->caller->global.inlined_to) + inlining_into = e->caller->global.inlined_to; + else + inlining_into = e->caller; + if (duplicate) { /* We may eliminate the need for out-of-line copy to be output. @@ -167,18 +174,15 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, { struct cgraph_node *n; n = cgraph_clone_node (e->callee, e->callee->symbol.decl, - e->count, e->frequency, - update_original, vNULL, true); + e->count, e->frequency, update_original, + vNULL, true, inlining_into); cgraph_redirect_edge_callee (e, n); } } else symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee); - if (e->caller->global.inlined_to) - e->callee->global.inlined_to = e->caller->global.inlined_to; - else - e->callee->global.inlined_to = e->caller; + e->callee->global.inlined_to = inlining_into; /* Recursively clone all bodies. */ for (e = e->callee->callees; e; e = e->next_callee) diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index d1f0089eb83..6eede0d35fc 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -1314,7 +1314,7 @@ recursive_inlining (struct cgraph_edge *edge, /* We need original clone to copy around. */ master_clone = cgraph_clone_node (node, node->symbol.decl, node->count, CGRAPH_FREQ_BASE, - false, vNULL, true); + false, vNULL, true, NULL); for (e = master_clone->callees; e; e = e->next_callee) if (!e->inline_failed) clone_inlined_nodes (e, true, false, NULL); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index a65adbbe331..e5e7dd00eee 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2684,9 +2684,6 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, propagate_controlled_uses (cs); changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges); - /* We do not keep jump functions of inlined edges up to date. Better to free - them so we do not access them accidentally. */ - ipa_free_edge_args_substructures (IPA_EDGE_REF (cs)); return changed; } @@ -2816,9 +2813,12 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, dst_rdesc = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool); dst_rdesc->cs = dst; - dst_rdesc->next_duplicate = src_rdesc->next_duplicate; - src_rdesc->next_duplicate = dst_rdesc; dst_rdesc->refcount = src_rdesc->refcount; + if (dst->caller->global.inlined_to) + { + dst_rdesc->next_duplicate = src_rdesc->next_duplicate; + src_rdesc->next_duplicate = dst_rdesc; + } dst_jf->value.constant.rdesc = dst_rdesc; } else @@ -2833,13 +2833,10 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc; dst_rdesc = dst_rdesc->next_duplicate) - { - gcc_assert (dst_rdesc->cs->caller->global.inlined_to); - if (dst_rdesc->cs->caller->global.inlined_to - == dst->caller->global.inlined_to) - break; - } - + if (dst_rdesc->cs->caller->global.inlined_to + == dst->caller->global.inlined_to) + break; + gcc_assert (dst_rdesc); dst_jf->value.constant.rdesc = dst_rdesc; } } diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 6c9a0285f81..4a287f65463 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -955,7 +955,7 @@ input_node (struct lto_file_decl_data *file_data, { node = cgraph_clone_node (cgraph (nodes[clone_ref]), fn_decl, 0, CGRAPH_FREQ_BASE, false, - vNULL, false); + vNULL, false, NULL); } else {