aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cgraph.h9
-rw-r--r--gcc/lto-cgraph.c15
-rw-r--r--gcc/lto/ChangeLog11
-rw-r--r--gcc/lto/lto.c91
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);
}