diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cgraph.h | 9 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 15 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/lto/lto.c | 91 |
5 files changed, 120 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d96152e..75b5645 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-07-05 Jan Hubicka <jh@suse.cz> + + * cgraph.h (cgraph_node, cgraph_varpool_node): Update docmentation of + in_other_partition. + * lto-cgraph.c (referenced_from_other_partition_p, + reachable_from_other_partition_p): Use in_other_partition flags. + (output_node, output_varpool_node): COMDAT nodes always have private + copies and thus are never used from other partition. + 2010-07-05 Anatoly Sokolov <aesok@post.ru> * config/ia64/ia64.h (MEMORY_MOVE_COST): Remove macro. diff --git a/gcc/cgraph.h b/gcc/cgraph.h index ef556b9..bbce3d8 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -286,7 +286,9 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node { /* Set once the function has been instantiated and its callee lists created. */ unsigned analyzed : 1; - /* Set when function is available in the other LTRANS partition. */ + /* Set when function is available in the other LTRANS partition. + During WPA output it is used to mark nodes that are present in + multiple partitions. */ unsigned in_other_partition : 1; /* Set when function is scheduled to be processed by local passes. */ unsigned process : 1; @@ -497,7 +499,9 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { unsigned alias : 1; /* Set when variable is used from other LTRANS partition. */ unsigned used_from_other_partition : 1; - /* Set when variable is available in the other LTRANS partition. */ + /* Set when variable is available in the other LTRANS partition. + During WPA output it is used to mark nodes that are present in + multiple partitions. */ unsigned in_other_partition : 1; }; @@ -556,6 +560,7 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int, gcov_type, int, int); struct cgraph_node * cgraph_get_node (tree); +struct cgraph_node * cgraph_get_node_or_alias (tree); struct cgraph_node *cgraph_node (tree); bool cgraph_same_body_alias (tree, tree); void cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 15427975..4217a71 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -319,13 +319,15 @@ referenced_from_other_partition_p (struct ipa_ref_list *list, cgraph_node_set se { if (ref->refering_type == IPA_REF_CGRAPH) { - if (!cgraph_node_in_set_p (ipa_ref_refering_node (ref), set)) + if (ipa_ref_refering_node (ref)->in_other_partition + || !cgraph_node_in_set_p (ipa_ref_refering_node (ref), set)) return true; } else { - if (!varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref), - vset)) + if (ipa_ref_refering_varpool_node (ref)->in_other_partition + || !varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref), + vset)) return true; } } @@ -343,7 +345,8 @@ reachable_from_other_partition_p (struct cgraph_node *node, cgraph_node_set set) if (node->global.inlined_to) return false; for (e = node->callers; e; e = e->next_caller) - if (!cgraph_node_in_set_p (e->caller, set)) + if (e->caller->in_other_partition + || !cgraph_node_in_set_p (e->caller, set)) return true; return false; } @@ -503,6 +506,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->abstract_and_needed, 1); bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node && !DECL_EXTERNAL (node->decl) + && !DECL_COMDAT (node->decl) && (reachable_from_other_partition_p (node, set) || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1); bp_pack_value (&bp, node->lowered, 1); @@ -576,7 +580,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node /* Constant pool initializers can be de-unified into individual ltrans units. FIXME: Alternatively at -Os we may want to avoid generating for them the local labels and share them across LTRANS partitions. */ - if (DECL_IN_CONSTANT_POOL (node->decl)) + if (DECL_IN_CONSTANT_POOL (node->decl) + && !DECL_COMDAT (node->decl)) { bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */ bp_pack_value (&bp, 0, 1); /* in_other_partition. */ diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 567cfcd..a1a03b6 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,14 @@ +2010-07-05 Jan Hubicka <jh@suse.cz> + + * lto.c (add_cgraph_node_to_partition): Forward declare; walk also + nodes from same comdat group as well as all comdat functions referenced + here. + (add_varpool_node_to_partition, add_references_to_partition): New function. + (lto_1_1_map): Skip COMDAT fnctions/variables; use add_varpool_node_to_partition; + clear aux flags when done. + (lto_promote_cross_file_statics): Do not promote stuff that gets duplicated to + each ltrans. + 2010-07-04 Jan Hubicka <jh@suse.cz> * lto.c (read_cgraph_and_symbols): Dump cgraph before merging. diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 27d2600..4ac1ac1 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -525,6 +525,9 @@ DEF_VEC_ALLOC_P(ltrans_partition,gc); static GTY (()) VEC(ltrans_partition, gc) *ltrans_partitions; +static void add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node); +static void add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode); + /* Create new partition with name NAME. */ static ltrans_partition new_partition (const char *name) @@ -538,17 +541,77 @@ new_partition (const char *name) return part; } -/* Add NODE to partition as well as the inline callees into partition PART. */ +/* See all references that go to comdat objects and bring them into partition too. */ +static void +add_references_to_partition (ltrans_partition part, struct ipa_ref_list *refs) +{ + int i; + struct ipa_ref *ref; + for (i = 0; ipa_ref_list_reference_iterate (refs, i, ref); i++) + { + if (ref->refered_type == IPA_REF_CGRAPH + && DECL_COMDAT (ipa_ref_node (ref)->decl) + && !cgraph_node_in_set_p (ipa_ref_node (ref), part->cgraph_set)) + add_cgraph_node_to_partition (part, ipa_ref_node (ref)); + else + if (ref->refered_type == IPA_REF_VARPOOL + && DECL_COMDAT (ipa_ref_varpool_node (ref)->decl) + && !varpool_node_in_set_p (ipa_ref_varpool_node (ref), part->varpool_set)) + add_varpool_node_to_partition (part, ipa_ref_varpool_node (ref)); + } +} + +/* Add NODE to partition as well as the inline callees and referred comdats into partition PART. */ static void add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node) { struct cgraph_edge *e; + part->insns += node->local.inline_summary.self_size; + + if (node->aux) + { + gcc_assert (node->aux != part); + node->in_other_partition = 1; + } + else + node->aux = part; + cgraph_node_set_add (part->cgraph_set, node); + for (e = node->callees; e; e = e->next_callee) - if (!e->inline_failed) + if ((!e->inline_failed || DECL_COMDAT (e->callee->decl)) + && !cgraph_node_in_set_p (e->callee, part->cgraph_set)) add_cgraph_node_to_partition (part, e->callee); + + add_references_to_partition (part, &node->ref_list); + + if (node->same_comdat_group + && !cgraph_node_in_set_p (node->same_comdat_group, part->cgraph_set)) + add_cgraph_node_to_partition (part, node->same_comdat_group); +} + +/* Add VNODE to partition as well as comdat references partition PART. */ + +static void +add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode) +{ + varpool_node_set_add (part->varpool_set, vnode); + + if (vnode->aux) + { + gcc_assert (vnode->aux != part); + vnode->in_other_partition = 1; + } + else + vnode->aux = part; + + add_references_to_partition (part, &vnode->ref_list); + + if (vnode->same_comdat_group + && !varpool_node_in_set_p (vnode->same_comdat_group, part->varpool_set)) + add_varpool_node_to_partition (part, vnode->same_comdat_group); } /* Group cgrah nodes by input files. This is used mainly for testing @@ -577,6 +640,10 @@ lto_1_to_1_map (void) /* Nodes without a body do not need partitioning. */ if (!node->analyzed) continue; + /* Extern inlines and comdat are always only in partitions they are needed. */ + if (DECL_EXTERNAL (node->decl) + || DECL_COMDAT (node->decl)) + continue; file_data = node->local.lto_file_data; gcc_assert (!node->same_body_alias && file_data); @@ -599,6 +666,10 @@ lto_1_to_1_map (void) { if (vnode->alias || !vnode->needed) continue; + /* Constant pool and comdat are always only in partitions they are needed. */ + if (DECL_IN_CONSTANT_POOL (vnode->decl) + || DECL_COMDAT (vnode->decl)) + continue; file_data = vnode->lto_file_data; slot = pointer_map_contains (pmap, file_data); if (slot) @@ -611,8 +682,12 @@ lto_1_to_1_map (void) npartitions++; } - varpool_node_set_add (partition->varpool_set, vnode); + add_varpool_node_to_partition (partition, vnode); } + for (node = cgraph_nodes; node; node = node->next) + node->aux = NULL; + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + vnode->aux = NULL; /* If the cgraph is empty, create one cgraph node set so that there is still an output file for any variables that need to be exported in a DSO. */ @@ -704,7 +779,7 @@ lto_promote_cross_file_statics (void) continue; if (node->global.inlined_to) continue; - if (!DECL_EXTERNAL (node->decl) + if ((!DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl)) && (referenced_from_other_partition_p (&node->ref_list, set, vset) || reachable_from_other_partition_p (node, set))) promote_fn (node); @@ -715,10 +790,10 @@ lto_promote_cross_file_statics (void) /* Constant pool references use internal labels and thus can not be made global. It is sensible to keep those ltrans local to allow better optimization. */ - if (!DECL_IN_CONSTANT_POOL (vnode->decl) - && !vnode->externally_visible && vnode->analyzed - && referenced_from_other_partition_p (&vnode->ref_list, - set, vset)) + if (!DECL_IN_CONSTANT_POOL (vnode->decl) && !DECL_COMDAT (vnode->decl) + && !vnode->externally_visible && vnode->analyzed + && referenced_from_other_partition_p (&vnode->ref_list, + set, vset)) promote_var (vnode); } |