Hi,
this patch fixes undefined symbol seen while compiling LLVM with LTO.
The bug here is that lto-cgraph and lto-partition both contain
knowledge about what symbols gets partitioned and what gets duplicated
to each partition that uses them. This has got out of sync
causing lto-cgraph to not set in_other_partition for symbols it believed
to be duplicated while they was really partitioned.
This patch unifies the logic.
Bootstrapped/regtsted x86_64-linux, comitted.
PR ipa/59469
* lto-cgraph.c (lto_output_node): Use
symtab_get_symbol_partitioning_class.
(lto_output_varpool_node): likewise.
(symtab_get_symbol_partitioning_class): Move here from
lto/lto-partition.c
* cgraph.h (symbol_partitioning_class): Likewise.
(symtab_get_symbol_partitioning_class): Declare.
* lto-partition.c (symbol_class): Move to cgraph.h
(get_symbol_class): Move to symtab.c
(add_references_to_partition, add_symbol_to_partition_1,
lto_max_map, lto_1_to_1_map, lto_balanced_map,
lto_promote_cross_file_statics): Update.
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c (revision 207588)
+++ lto-cgraph.c (working copy)
@@ -417,7 +417,8 @@ lto_output_node (struct lto_simple_outpu
Cherry-picked nodes: These are nodes we pulled from other
translation units into SET during IPA-inlining. We make them as
local static nodes to prevent clashes with other local statics. */
- if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->decl))
+ if (boundary_p && node->analyzed
+ && symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION)
{
/* Inline clones can not be part of boundary.
gcc_assert (!node->global.inlined_to);
@@ -501,8 +502,7 @@ lto_output_node (struct lto_simple_outpu
bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->address_taken, 1);
bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
- && !DECL_EXTERNAL (node->decl)
- && !DECL_COMDAT (node->decl)
+ && symtab_get_symbol_partitioning_class (node) ==
SYMBOL_PARTITION
&& (reachable_from_other_partition_p (node, encoder)
|| referenced_from_other_partition_p (&node->ref_list,
encoder)), 1);
@@ -569,9 +569,7 @@ lto_output_varpool_node (struct lto_simp
/* 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)
- && !DECL_EXTERNAL (node->decl)
- && !DECL_COMDAT (node->decl))
+ if (symtab_get_symbol_partitioning_class (node) != SYMBOL_PARTITION)
{
bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */
bp_pack_value (&bp, 0, 1); /* in_other_partition. */
Index: symtab.c
===================================================================
--- symtab.c (revision 207588)
+++ symtab.c (working copy)
@@ -1267,4 +1267,55 @@ symtab_semantically_equivalent_p (symtab
bb = b;
return bb == ba;
}
+
+/* Classify symbol NODE for partitioning. */
+
+enum symbol_partitioning_class
+symtab_get_symbol_partitioning_class (symtab_node *node)
+{
+ /* Inline clones are always duplicated.
+ This include external delcarations. */
+ cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+
+ if (DECL_ABSTRACT (node->decl))
+ return SYMBOL_EXTERNAL;
+
+ if (cnode && cnode->global.inlined_to)
+ return SYMBOL_DUPLICATE;
+
+ /* Weakref aliases are always duplicated. */
+ if (node->weakref)
+ return SYMBOL_DUPLICATE;
+
+ /* External declarations are external. */
+ if (DECL_EXTERNAL (node->decl))
+ return SYMBOL_EXTERNAL;
+
+ if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+ {
+ /* Constant pool references use local symbol names that can not
+ be promoted global. We should never put into a constant pool
+ objects that can not be duplicated across partitions. */
+ if (DECL_IN_CONSTANT_POOL (node->decl))
+ return SYMBOL_DUPLICATE;
+ gcc_checking_assert (vnode->definition);
+ }
+ /* Functions that are cloned may stay in callgraph even if they are unused.
+ Handle them as external; compute_ltrans_boundary take care to make
+ proper things to happen (i.e. to make them appear in the boundary but
+ with body streamed, so clone can me materialized). */
+ else if (!cgraph (node)->definition)
+ return SYMBOL_EXTERNAL;
+
+ /* Linker discardable symbols are duplicated to every use unless they are
+ keyed.
+ Keyed symbols or those. */
+ if (DECL_ONE_ONLY (node->decl)
+ && !node->force_output
+ && !node->forced_by_abi
+ && !symtab_used_from_object_file_p (node))
+ return SYMBOL_DUPLICATE;
+
+ return SYMBOL_PARTITION;
+}
#include "gt-symtab.h"
Index: cgraph.h
===================================================================
--- cgraph.h (revision 207588)
+++ cgraph.h (working copy)
@@ -704,6 +704,20 @@ extern GTY(()) struct asm_node *asm_node
extern GTY(()) int symtab_order;
extern bool cpp_implicit_aliases_done;
+/* Classifcation of symbols WRT partitioning. */
+enum symbol_partitioning_class
+{
+ /* External declarations are ignored by partitioning algorithms and they are
+ added into the boundary later via compute_ltrans_boundary. */
+ SYMBOL_EXTERNAL,
+ /* Partitioned symbols are pur into one of partitions. */
+ SYMBOL_PARTITION,
+ /* Duplicated symbols (such as comdat or constant pool references) are
+ copied into every node needing them via add_symbol_to_partition. */
+ SYMBOL_DUPLICATE
+};
+
+
/* In symtab.c */
void symtab_register_node (symtab_node *);
void symtab_unregister_node (symtab_node *);
@@ -734,6 +748,7 @@ bool symtab_for_node_and_aliases (symtab
symtab_node *symtab_nonoverwritable_alias (symtab_node *);
enum availability symtab_node_availability (symtab_node *);
bool symtab_semantically_equivalent_p (symtab_node *, symtab_node *);
+enum symbol_partitioning_class symtab_get_symbol_partitioning_class
(symtab_node *);
/* In cgraph.c */
void dump_cgraph (FILE *);
Index: lto/lto-partition.c
===================================================================
--- lto/lto-partition.c (revision 207588)
+++ lto/lto-partition.c (working copy)
@@ -38,73 +38,10 @@ along with GCC; see the file COPYING3.
#include "ipa-utils.h"
#include "lto-partition.h"
-/* Classifcation of symbols into classes WRT partitioning. */
-enum symbol_class
-{
- /* External declarations are ignored by partitioning algorithms and they are
- added into the boundary later via compute_ltrans_boundary. */
- SYMBOL_EXTERNAL,
- /* Partitioned symbols are pur into one of partitions. */
- SYMBOL_PARTITION,
- /* Duplicated symbols (such as comdat or constant pool references) are
- copied into every node needing them via add_symbol_to_partition. */
- SYMBOL_DUPLICATE
-};
-
vec<ltrans_partition> ltrans_partitions;
static void add_symbol_to_partition (ltrans_partition part, symtab_node *node);
-/* Classify symbol NODE. */
-
-enum symbol_class
-get_symbol_class (symtab_node *node)
-{
- /* Inline clones are always duplicated.
- This include external delcarations. */
- cgraph_node *cnode = dyn_cast <cgraph_node> (node);
-
- if (DECL_ABSTRACT (node->decl))
- return SYMBOL_EXTERNAL;
-
- if (cnode && cnode->global.inlined_to)
- return SYMBOL_DUPLICATE;
-
- /* Weakref aliases are always duplicated. */
- if (node->weakref)
- return SYMBOL_DUPLICATE;
-
- /* External declarations are external. */
- if (DECL_EXTERNAL (node->decl))
- return SYMBOL_EXTERNAL;
-
- if (varpool_node *vnode = dyn_cast <varpool_node> (node))
- {
- /* Constant pool references use local symbol names that can not
- be promoted global. We should never put into a constant pool
- objects that can not be duplicated across partitions. */
- if (DECL_IN_CONSTANT_POOL (node->decl))
- return SYMBOL_DUPLICATE;
- gcc_checking_assert (vnode->definition);
- }
- /* Functions that are cloned may stay in callgraph even if they are unused.
- Handle them as external; compute_ltrans_boundary take care to make
- proper things to happen (i.e. to make them appear in the boundary but
- with body streamed, so clone can me materialized). */
- else if (!cgraph (node)->definition)
- return SYMBOL_EXTERNAL;
-
- /* Linker discardable symbols are duplicated to every use unless they are
- keyed.
- Keyed symbols or those. */
- if (DECL_ONE_ONLY (node->decl)
- && !node->force_output
- && !node->forced_by_abi
- && !symtab_used_from_object_file_p (node))
- return SYMBOL_DUPLICATE;
-
- return SYMBOL_PARTITION;
-}
/* Create new partition with name NAME. */
@@ -153,7 +90,7 @@ add_references_to_partition (ltrans_part
/* Add all duplicated references to the partition. */
for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
- if (get_symbol_class (ref->referred) == SYMBOL_DUPLICATE)
+ if (symtab_get_symbol_partitioning_class (ref->referred) ==
SYMBOL_DUPLICATE)
add_symbol_to_partition (part, ref->referred);
/* References to a readonly variable may be constant foled into its value.
Recursively look into the initializers of the constant variable and add
@@ -175,7 +112,7 @@ add_references_to_partition (ltrans_part
static bool
add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
{
- enum symbol_class c = get_symbol_class (node);
+ enum symbol_partitioning_class c = symtab_get_symbol_partitioning_class
(node);
int i;
struct ipa_ref *ref;
symtab_node *node1;
@@ -218,7 +155,7 @@ add_symbol_to_partition_1 (ltrans_partit
for (e = cnode->callees; e; e = e->next_callee)
if (!e->inline_failed)
add_symbol_to_partition_1 (part, e->callee);
- else if (get_symbol_class (e->callee) == SYMBOL_DUPLICATE)
+ else if (symtab_get_symbol_partitioning_class (e->callee) ==
SYMBOL_DUPLICATE)
add_symbol_to_partition (part, e->callee);
/* Add all thunks associated with the function. */
@@ -238,10 +175,11 @@ add_symbol_to_partition_1 (ltrans_partit
if (node->same_comdat_group)
for (node1 = node->same_comdat_group;
node1 != node; node1 = node1->same_comdat_group)
- {
- bool added = add_symbol_to_partition_1 (part, node1);
- gcc_assert (added);
- }
+ if (!node->alias)
+ {
+ bool added = add_symbol_to_partition_1 (part, node1);
+ gcc_assert (added);
+ }
return true;
}
@@ -276,7 +214,7 @@ add_symbol_to_partition (ltrans_partitio
symtab_node *node1;
/* Verify that we do not try to duplicate something that can not be. */
- gcc_checking_assert (get_symbol_class (node) == SYMBOL_DUPLICATE
+ gcc_checking_assert (symtab_get_symbol_partitioning_class (node) ==
SYMBOL_DUPLICATE
|| !symbol_partitioned_p (node));
while ((node1 = contained_in_symbol (node)) != node)
@@ -289,7 +227,7 @@ add_symbol_to_partition (ltrans_partitio
Be lax about comdats; they may or may not be duplicated and we may
end up in need to duplicate keyed comdat because it has unkeyed alias. */
- gcc_assert (get_symbol_class (node) == SYMBOL_DUPLICATE
+ gcc_assert (symtab_get_symbol_partitioning_class (node) == SYMBOL_DUPLICATE
|| DECL_COMDAT (node->decl)
|| !symbol_partitioned_p (node));
@@ -336,7 +274,7 @@ lto_1_to_1_map (void)
FOR_EACH_SYMBOL (node)
{
- if (get_symbol_class (node) != SYMBOL_PARTITION
+ if (symtab_get_symbol_partitioning_class (node) != SYMBOL_PARTITION
|| symbol_partitioned_p (node))
continue;
@@ -388,7 +326,7 @@ lto_max_map (void)
FOR_EACH_SYMBOL (node)
{
- if (get_symbol_class (node) != SYMBOL_PARTITION
+ if (symtab_get_symbol_partitioning_class (node) != SYMBOL_PARTITION
|| symbol_partitioned_p (node))
continue;
partition = new_partition (node->asm_name ());
@@ -498,7 +436,7 @@ lto_balanced_map (void)
gcc_assert (!vnode->aux);
FOR_EACH_DEFINED_FUNCTION (node)
- if (get_symbol_class (node) == SYMBOL_PARTITION)
+ if (symtab_get_symbol_partitioning_class (node) == SYMBOL_PARTITION)
{
order[n_nodes++] = node;
total_size += inline_summary (node)->size;
@@ -518,13 +456,13 @@ lto_balanced_map (void)
if (!flag_toplevel_reorder)
{
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class (vnode) == SYMBOL_PARTITION)
+ if (symtab_get_symbol_partitioning_class (vnode) == SYMBOL_PARTITION)
n_varpool_nodes++;
varpool_order = XNEWVEC (varpool_node *, n_varpool_nodes);
n_varpool_nodes = 0;
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class (vnode) == SYMBOL_PARTITION)
+ if (symtab_get_symbol_partitioning_class (vnode) == SYMBOL_PARTITION)
varpool_order[n_varpool_nodes++] = vnode;
qsort (varpool_order, n_varpool_nodes, sizeof (varpool_node *),
varpool_node_cmp);
@@ -643,7 +581,7 @@ lto_balanced_map (void)
if (!vnode->definition)
continue;
if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
- && get_symbol_class (vnode) == SYMBOL_PARTITION)
+ && symtab_get_symbol_partitioning_class (vnode) ==
SYMBOL_PARTITION)
add_symbol_to_partition (partition, vnode);
index = lto_symtab_encoder_lookup (partition->encoder,
vnode);
@@ -676,7 +614,7 @@ lto_balanced_map (void)
vnode = ipa_ref_referring_varpool_node (ref);
gcc_assert (vnode->definition);
if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder
- && get_symbol_class (vnode) == SYMBOL_PARTITION)
+ && symtab_get_symbol_partitioning_class (vnode) ==
SYMBOL_PARTITION)
add_symbol_to_partition (partition, vnode);
index = lto_symtab_encoder_lookup (partition->encoder,
vnode);
@@ -769,7 +707,7 @@ lto_balanced_map (void)
if (flag_toplevel_reorder)
{
FOR_EACH_VARIABLE (vnode)
- if (get_symbol_class (vnode) == SYMBOL_PARTITION
+ if (symtab_get_symbol_partitioning_class (vnode) == SYMBOL_PARTITION
&& !symbol_partitioned_p (vnode))
add_symbol_to_partition (partition, vnode);
}
@@ -979,7 +917,7 @@ lto_promote_cross_file_statics (void)
|| lto_symtab_encoder_in_partition_p (encoder, node)
/* ... or if we do not partition it. This mean that it will
appear in every partition refernecing it. */
- || get_symbol_class (node) != SYMBOL_PARTITION)
+ || symtab_get_symbol_partitioning_class (node) !=
SYMBOL_PARTITION)
continue;
promote_symbol (node);
Index: symtab.c
===================================================================
--- symtab.c (revision 207588)
+++ symtab.c (working copy)
@@ -1267,4 +1267,55 @@ symtab_semantically_equivalent_p (symtab
bb = b;
return bb == ba;
}
+
+/* Classify symbol NODE for partitioning. */
+
+enum symbol_partitioning_class
+symtab_get_symbol_partitioning_class (symtab_node *node)
+{
+ /* Inline clones are always duplicated.
+ This include external delcarations. */
+ cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+
+ if (DECL_ABSTRACT (node->decl))
+ return SYMBOL_EXTERNAL;
+
+ if (cnode && cnode->global.inlined_to)
+ return SYMBOL_DUPLICATE;
+
+ /* Weakref aliases are always duplicated. */
+ if (node->weakref)
+ return SYMBOL_DUPLICATE;
+
+ /* External declarations are external. */
+ if (DECL_EXTERNAL (node->decl))
+ return SYMBOL_EXTERNAL;
+
+ if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+ {
+ /* Constant pool references use local symbol names that can not
+ be promoted global. We should never put into a constant pool
+ objects that can not be duplicated across partitions. */
+ if (DECL_IN_CONSTANT_POOL (node->decl))
+ return SYMBOL_DUPLICATE;
+ gcc_checking_assert (vnode->definition);
+ }
+ /* Functions that are cloned may stay in callgraph even if they are unused.
+ Handle them as external; compute_ltrans_boundary take care to make
+ proper things to happen (i.e. to make them appear in the boundary but
+ with body streamed, so clone can me materialized). */
+ else if (!cgraph (node)->definition)
+ return SYMBOL_EXTERNAL;
+
+ /* Linker discardable symbols are duplicated to every use unless they are
+ keyed.
+ Keyed symbols or those. */
+ if (DECL_ONE_ONLY (node->decl)
+ && !node->force_output
+ && !node->forced_by_abi
+ && !symtab_used_from_object_file_p (node))
+ return SYMBOL_DUPLICATE;
+
+ return SYMBOL_PARTITION;
+}
#include "gt-symtab.h"