/* 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;
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;
};
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);
{
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;
}
}
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;
}
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);
/* 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. */
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)
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
/* 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);
{
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)
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. */
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);
/* 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);
}