Commit 2942c502 by Jan Hubicka Committed by Jan Hubicka

* lto-symtab.c (lto_symtab_entry_def) Add vnode.

	(lto_varpool_replace_node): New.
	(lto_symtab_resolve_symbols): Resolve varpool nodes.
	(lto_symtab_merge_decls_1): Prefer decls with varpool node.
	(lto_symtab_merge_cgraph_nodes_1): Merge varpools.
	* cgraph.h (varpool_node_ptr): New type.
	(varpool_node_ptr): New vector.
	(varpool_node_set_def): New structure.
	(varpool_node_set): New type.
	(varpool_node_set): New vector.
	(varpool_node_set_element_def): New structure.
	(varpool_node_set_element, const_varpool_node_set_element): New types.
	(varpool_node_set_iterator): New type.
	(varpool_node): Add prev pointers, add used_from_other_partition,
	in_other_partition.
	(varpool_node_set_new, varpool_node_set_find, varpool_node_set_add,
	varpool_node_set_remove, dump_varpool_node_set, debug_varpool_node_set,
	varpool_get_node, varpool_remove_node): Declare.
	(vsi_end_p, vsi_next, vsi_node, vsi_start, varpool_node_in_set_p,
	varpool_node_set_size): New inlines.
	* cgraph.c (dump_cgraph_node): Dump asm names of aliases.
	* tree-pass.h (varpool_node_set_def): Forward declare.
	(ipa_opt_pass_d): Summary writting takes vnode sets too.
	(ipa_write_optimization_summaries): Update prototype.
	* ipa-cp.c (ipcp_write_summary): Update.
	* ipa-reference.c (ipa_reference_write_summary): Update.
	* lto-cgraph.c (lto_output_varpool_node): New static function.
	(output_varpool): New function.
	(input_varpool_node): New static function.
	(input_varpool_1): New function.
	(input_cgraph): Input varpool.
	* ipa-pure-const.c (pure_const_write_summary): Update.
	* lto-streamer-out.c (lto_output): Update, output varpool too.
	(write_global_stream): Kill WPA hack.
	(produce_asm_for_decls): Update.
	(output_alias_pair_p): Handle variables.
	(output_unreferenced_globals): Output only needed partition of varpool.
	* ipa-inline.c (inline_write_summary): Update.
	* lto-streamer-in.c (lto_input_tree_ref, lto_input_tree): Do not build cgraph.
	* lto-section-in.c (lto_section_name): Add varpool and jump funcs.
	* ipa.c (hash_varpool_node_set_element, eq_varpool_node_set_element,
	varpool_node_set_new, varpool_node_set_add,
	varpool_node_set_remove, varpool_node_set_find, dump_varpool_node_set,
	debug_varpool_node_set): New functions.
	* passes.c (rest_of_decl_compilation): when in LTO do not finalize.
	(execute_one_pass): Process new decls too.
	(ipa_write_summaries_2): Pass around vsets.
	(ipa_write_summaries_1): Likewise.
	(ipa_write_summaries): Build vset; be more selective about cgraph nodes
	to add.
	(ipa_write_optimization_summaries_1): Pass around vsets.
	(ipa_write_optimization_summaries): Likewise.
	* varpool.c (varpool_get_node): New.
	(varpool_node): Update doubly linked lists.
	(varpool_remove_node): New.
	(dump_varpool_node): More dumping.
	(varpool_enqueue_needed_node): Update doubly linked lists.
	(decide_is_variable_needed): Kill ltrans hack.
	(varpool_finalize_decl): Kill lto hack.
	(varpool_assemble_decl): Skip decls in other partitions.
	(varpool_assemble_pending_decls): Update doubly linkes lists.
	(varpool_empty_needed_queue): Likewise.
	(varpool_extra_name_alias): Likewise.
	* lto-streamer.c (lto_get_section_name): Add vars section.
	* lto-streamer.h (lto_section_type): Update.
	(output_varpool, input_varpool): Declare.

	* lto.c (lto_varpool_node_sets): New.
	(lto_1_to_1_map): Partition varpool too.
	(globalize_context_t, globalize_cross_file_statics,
	lto_scan_statics_in_ref_table, lto_scan_statics_in_cgraph_node,
	lto_scan_statics_in_remaining_global_vars): Remove.
	(lto_promote_cross_file_statics): Rewrite.
	(get_filename_for_set): Take vset argument.
	(lto_wpa_write_files): Pass around vsets.

From-SVN: r158854
parent 74ca3393
2010-04-28 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_symtab_entry_def) Add vnode.
(lto_varpool_replace_node): New.
(lto_symtab_resolve_symbols): Resolve varpool nodes.
(lto_symtab_merge_decls_1): Prefer decls with varpool node.
(lto_symtab_merge_cgraph_nodes_1): Merge varpools.
* cgraph.h (varpool_node_ptr): New type.
(varpool_node_ptr): New vector.
(varpool_node_set_def): New structure.
(varpool_node_set): New type.
(varpool_node_set): New vector.
(varpool_node_set_element_def): New structure.
(varpool_node_set_element, const_varpool_node_set_element): New types.
(varpool_node_set_iterator): New type.
(varpool_node): Add prev pointers, add used_from_other_partition,
in_other_partition.
(varpool_node_set_new, varpool_node_set_find, varpool_node_set_add,
varpool_node_set_remove, dump_varpool_node_set, debug_varpool_node_set,
varpool_get_node, varpool_remove_node): Declare.
(vsi_end_p, vsi_next, vsi_node, vsi_start, varpool_node_in_set_p,
varpool_node_set_size): New inlines.
* cgraph.c (dump_cgraph_node): Dump asm names of aliases.
* tree-pass.h (varpool_node_set_def): Forward declare.
(ipa_opt_pass_d): Summary writting takes vnode sets too.
(ipa_write_optimization_summaries): Update prototype.
* ipa-cp.c (ipcp_write_summary): Update.
* ipa-reference.c (ipa_reference_write_summary): Update.
* lto-cgraph.c (lto_output_varpool_node): New static function.
(output_varpool): New function.
(input_varpool_node): New static function.
(input_varpool_1): New function.
(input_cgraph): Input varpool.
* ipa-pure-const.c (pure_const_write_summary): Update.
* lto-streamer-out.c (lto_output): Update, output varpool too.
(write_global_stream): Kill WPA hack.
(produce_asm_for_decls): Update.
(output_alias_pair_p): Handle variables.
(output_unreferenced_globals): Output only needed partition of varpool.
* ipa-inline.c (inline_write_summary): Update.
* lto-streamer-in.c (lto_input_tree_ref, lto_input_tree): Do not build cgraph.
* lto-section-in.c (lto_section_name): Add varpool and jump funcs.
* ipa.c (hash_varpool_node_set_element, eq_varpool_node_set_element,
varpool_node_set_new, varpool_node_set_add,
varpool_node_set_remove, varpool_node_set_find, dump_varpool_node_set,
debug_varpool_node_set): New functions.
* passes.c (rest_of_decl_compilation): when in LTO do not finalize.
(execute_one_pass): Process new decls too.
(ipa_write_summaries_2): Pass around vsets.
(ipa_write_summaries_1): Likewise.
(ipa_write_summaries): Build vset; be more selective about cgraph nodes
to add.
(ipa_write_optimization_summaries_1): Pass around vsets.
(ipa_write_optimization_summaries): Likewise.
* varpool.c (varpool_get_node): New.
(varpool_node): Update doubly linked lists.
(varpool_remove_node): New.
(dump_varpool_node): More dumping.
(varpool_enqueue_needed_node): Update doubly linked lists.
(decide_is_variable_needed): Kill ltrans hack.
(varpool_finalize_decl): Kill lto hack.
(varpool_assemble_decl): Skip decls in other partitions.
(varpool_assemble_pending_decls): Update doubly linkes lists.
(varpool_empty_needed_queue): Likewise.
(varpool_extra_name_alias): Likewise.
* lto-streamer.c (lto_get_section_name): Add vars section.
* lto-streamer.h (lto_section_type): Update.
(output_varpool, input_varpool): Declare.
2010-04-28 Mike Stump <mikestump@comcast.net>
* config/i386/darwin.h (CC1_SPEC): Ignore -mdynamic-no-pic for now.
......
......@@ -1877,6 +1877,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
(int)n->thunk.virtual_offset_p);
fprintf (f, ")");
}
if (DECL_ASSEMBLER_NAME_SET_P (n->decl))
fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl)));
}
fprintf (f, "\n");
}
......
......@@ -274,7 +274,7 @@ 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 LTO partition. */
/* Set when function is available in the other LTRANS partition. */
unsigned in_other_partition : 1;
/* Set when function is scheduled to be processed by local passes. */
unsigned process : 1;
......@@ -305,12 +305,33 @@ struct GTY(()) cgraph_node_set_def
PTR GTY ((skip)) aux;
};
typedef struct varpool_node *varpool_node_ptr;
DEF_VEC_P(varpool_node_ptr);
DEF_VEC_ALLOC_P(varpool_node_ptr,heap);
DEF_VEC_ALLOC_P(varpool_node_ptr,gc);
/* A varpool node set is a collection of varpool nodes. A varpool node
can appear in multiple sets. */
struct GTY(()) varpool_node_set_def
{
htab_t GTY((param_is (struct varpool_node_set_element_def))) hashtab;
VEC(varpool_node_ptr, gc) *nodes;
PTR GTY ((skip)) aux;
};
typedef struct cgraph_node_set_def *cgraph_node_set;
DEF_VEC_P(cgraph_node_set);
DEF_VEC_ALLOC_P(cgraph_node_set,gc);
DEF_VEC_ALLOC_P(cgraph_node_set,heap);
typedef struct varpool_node_set_def *varpool_node_set;
DEF_VEC_P(varpool_node_set);
DEF_VEC_ALLOC_P(varpool_node_set,gc);
DEF_VEC_ALLOC_P(varpool_node_set,heap);
/* A cgraph node set element contains an index in the vector of nodes in
the set. */
struct GTY(()) cgraph_node_set_element_def
......@@ -329,6 +350,24 @@ typedef struct
unsigned index;
} cgraph_node_set_iterator;
/* A varpool node set element contains an index in the vector of nodes in
the set. */
struct GTY(()) varpool_node_set_element_def
{
struct varpool_node *node;
HOST_WIDE_INT index;
};
typedef struct varpool_node_set_element_def *varpool_node_set_element;
typedef const struct varpool_node_set_element_def *const_varpool_node_set_element;
/* Iterator structure for varpool node sets. */
typedef struct
{
varpool_node_set set;
unsigned index;
} varpool_node_set_iterator;
#define DEFCIFCODE(code, string) CIF_ ## code,
/* Reasons for inlining failures. */
typedef enum {
......@@ -398,9 +437,9 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
struct GTY((chain_next ("%h.next"))) varpool_node {
tree decl;
/* Pointer to the next function in varpool_nodes. */
struct varpool_node *next;
struct varpool_node *next, *prev;
/* Pointer to the next function in varpool_nodes_queue. */
struct varpool_node *next_needed;
struct varpool_node *next_needed, *prev_needed;
/* For normal nodes a pointer to the first extra name alias. For alias
nodes a pointer to the normal node. */
struct varpool_node *extra_name;
......@@ -425,6 +464,10 @@ struct GTY((chain_next ("%h.next"))) varpool_node {
/* Set for aliases once they got through assemble_alias. Also set for
extra name aliases in varpool_extra_name_alias. */
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. */
unsigned in_other_partition : 1;
};
/* Every top level asm statement is put into a cgraph_asm_node. */
......@@ -594,6 +637,13 @@ void cgraph_node_set_remove (cgraph_node_set, struct cgraph_node *);
void dump_cgraph_node_set (FILE *, cgraph_node_set);
void debug_cgraph_node_set (cgraph_node_set);
varpool_node_set varpool_node_set_new (void);
varpool_node_set_iterator varpool_node_set_find (varpool_node_set,
struct varpool_node *);
void varpool_node_set_add (varpool_node_set, struct varpool_node *);
void varpool_node_set_remove (varpool_node_set, struct varpool_node *);
void dump_varpool_node_set (FILE *, varpool_node_set);
void debug_varpool_node_set (varpool_node_set);
/* In predict.c */
bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e);
......@@ -616,6 +666,9 @@ void cgraph_make_decl_local (tree);
void cgraph_make_node_local (struct cgraph_node *);
bool cgraph_node_can_be_local_p (struct cgraph_node *);
struct varpool_node * varpool_get_node (tree decl);
void varpool_remove_node (struct varpool_node *node);
bool varpool_assemble_pending_decls (void);
bool varpool_assemble_decl (struct varpool_node *node);
bool varpool_analyze_pending_decls (void);
......@@ -734,6 +787,54 @@ cgraph_node_set_size (cgraph_node_set set)
return htab_elements (set->hashtab);
}
/* Return true if iterator VSI points to nothing. */
static inline bool
vsi_end_p (varpool_node_set_iterator vsi)
{
return vsi.index >= VEC_length (varpool_node_ptr, vsi.set->nodes);
}
/* Advance iterator VSI. */
static inline void
vsi_next (varpool_node_set_iterator *vsi)
{
vsi->index++;
}
/* Return the node pointed to by VSI. */
static inline struct varpool_node *
vsi_node (varpool_node_set_iterator vsi)
{
return VEC_index (varpool_node_ptr, vsi.set->nodes, vsi.index);
}
/* Return an iterator to the first node in SET. */
static inline varpool_node_set_iterator
vsi_start (varpool_node_set set)
{
varpool_node_set_iterator vsi;
vsi.set = set;
vsi.index = 0;
return vsi;
}
/* Return true if SET contains NODE. */
static inline bool
varpool_node_in_set_p (struct varpool_node *node, varpool_node_set set)
{
varpool_node_set_iterator vsi;
vsi = varpool_node_set_find (set, node);
return !vsi_end_p (vsi);
}
/* Return number of nodes in SET. */
static inline size_t
varpool_node_set_size (varpool_node_set set)
{
return htab_elements (set->hashtab);
}
/* Uniquize all constants that appear in memory.
Each constant in memory thus far output is recorded
in `const_desc_table'. */
......
......@@ -382,6 +382,7 @@ cgraph_process_new_functions (void)
tree fndecl;
struct cgraph_node *node;
varpool_analyze_pending_decls ();
/* Note that this queue may grow as its being processed, as the new
functions may generate new ones. */
while (cgraph_new_nodes)
......@@ -437,6 +438,7 @@ cgraph_process_new_functions (void)
break;
}
cgraph_call_function_insertion_hooks (node);
varpool_analyze_pending_decls ();
}
return output;
}
......
......@@ -1304,7 +1304,8 @@ ipcp_generate_summary (void)
/* Write ipcp summary for nodes in SET. */
static void
ipcp_write_summary (cgraph_node_set set)
ipcp_write_summary (cgraph_node_set set,
varpool_node_set vset ATTRIBUTE_UNUSED)
{
ipa_prop_write_jump_functions (set);
}
......
......@@ -2097,7 +2097,8 @@ inline_read_summary (void)
active, we don't need to write them twice. */
static void
inline_write_summary (cgraph_node_set set)
inline_write_summary (cgraph_node_set set,
varpool_node_set vset ATTRIBUTE_UNUSED)
{
if (flag_indirect_inlining && !flag_ipa_cp)
ipa_prop_write_jump_functions (set);
......
......@@ -771,7 +771,8 @@ generate_summary (void)
/* Serialize the ipa info for lto. */
static void
pure_const_write_summary (cgraph_node_set set)
pure_const_write_summary (cgraph_node_set set,
varpool_node_set vset ATTRIBUTE_UNUSED)
{
struct cgraph_node *node;
struct lto_simple_output_block *ob
......
......@@ -1040,7 +1040,8 @@ write_node_summary_p (struct cgraph_node *node)
/* Serialize the ipa info for lto. */
static void
ipa_reference_write_summary (cgraph_node_set set)
ipa_reference_write_summary (cgraph_node_set set,
varpool_node_set vset ATTRIBUTE_UNUSED)
{
struct cgraph_node *node;
struct lto_simple_output_block *ob
......
......@@ -762,6 +762,164 @@ debug_cgraph_node_set (cgraph_node_set set)
dump_cgraph_node_set (stderr, set);
}
/* Hash a varpool node set element. */
static hashval_t
hash_varpool_node_set_element (const void *p)
{
const_varpool_node_set_element element = (const_varpool_node_set_element) p;
return htab_hash_pointer (element->node);
}
/* Compare two varpool node set elements. */
static int
eq_varpool_node_set_element (const void *p1, const void *p2)
{
const_varpool_node_set_element e1 = (const_varpool_node_set_element) p1;
const_varpool_node_set_element e2 = (const_varpool_node_set_element) p2;
return e1->node == e2->node;
}
/* Create a new varpool node set. */
varpool_node_set
varpool_node_set_new (void)
{
varpool_node_set new_node_set;
new_node_set = GGC_NEW (struct varpool_node_set_def);
new_node_set->hashtab = htab_create_ggc (10,
hash_varpool_node_set_element,
eq_varpool_node_set_element,
NULL);
new_node_set->nodes = NULL;
return new_node_set;
}
/* Add varpool_node NODE to varpool_node_set SET. */
void
varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
{
void **slot;
varpool_node_set_element element;
struct varpool_node_set_element_def dummy;
dummy.node = node;
slot = htab_find_slot (set->hashtab, &dummy, INSERT);
if (*slot != HTAB_EMPTY_ENTRY)
{
element = (varpool_node_set_element) *slot;
gcc_assert (node == element->node
&& (VEC_index (varpool_node_ptr, set->nodes, element->index)
== node));
return;
}
/* Insert node into hash table. */
element =
(varpool_node_set_element) GGC_NEW (struct varpool_node_set_element_def);
element->node = node;
element->index = VEC_length (varpool_node_ptr, set->nodes);
*slot = element;
/* Insert into node vector. */
VEC_safe_push (varpool_node_ptr, gc, set->nodes, node);
}
/* Remove varpool_node NODE from varpool_node_set SET. */
void
varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
{
void **slot, **last_slot;
varpool_node_set_element element, last_element;
struct varpool_node *last_node;
struct varpool_node_set_element_def dummy;
dummy.node = node;
slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
if (slot == NULL)
return;
element = (varpool_node_set_element) *slot;
gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
== node);
/* Remove from vector. We do this by swapping node with the last element
of the vector. */
last_node = VEC_pop (varpool_node_ptr, set->nodes);
if (last_node != node)
{
dummy.node = last_node;
last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
last_element = (varpool_node_set_element) *last_slot;
gcc_assert (last_element);
/* Move the last element to the original spot of NODE. */
last_element->index = element->index;
VEC_replace (varpool_node_ptr, set->nodes, last_element->index,
last_node);
}
/* Remove element from hash table. */
htab_clear_slot (set->hashtab, slot);
ggc_free (element);
}
/* Find NODE in SET and return an iterator to it if found. A null iterator
is returned if NODE is not in SET. */
varpool_node_set_iterator
varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
{
void **slot;
struct varpool_node_set_element_def dummy;
varpool_node_set_element element;
varpool_node_set_iterator vsi;
dummy.node = node;
slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
if (slot == NULL)
vsi.index = (unsigned) ~0;
else
{
element = (varpool_node_set_element) *slot;
gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
== node);
vsi.index = element->index;
}
vsi.set = set;
return vsi;
}
/* Dump content of SET to file F. */
void
dump_varpool_node_set (FILE *f, varpool_node_set set)
{
varpool_node_set_iterator iter;
for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
{
struct varpool_node *node = vsi_node (iter);
dump_varpool_node (f, node);
}
}
/* Dump content of SET to stderr. */
void
debug_varpool_node_set (varpool_node_set set)
{
dump_varpool_node_set (stderr, set);
}
/* Simple ipa profile pass propagating frequencies across the callgraph. */
static unsigned int
......
......@@ -378,6 +378,45 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
lto_output_uleb128_stream (ob->main_stream, 0);
}
/* Output the varpool NODE to OB.
If NODE is not in SET, then NODE is a boundary. */
static void
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
varpool_node_set set)
{
bool boundary_p = !varpool_node_in_set_p (node, set) && node->analyzed;
struct bitpack_d *bp;
struct varpool_node *alias;
int count = 0;
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
bp = bitpack_create ();
bp_pack_value (bp, node->externally_visible, 1);
bp_pack_value (bp, node->force_output, 1);
bp_pack_value (bp, node->finalized, 1);
gcc_assert (node->finalized || !node->analyzed);
gcc_assert (node->needed);
gcc_assert (!node->alias);
/* FIXME: We have no idea how we move references around. For moment assume that
everything is used externally. */
bp_pack_value (bp, flag_wpa, 1); /* used_from_other_parition. */
bp_pack_value (bp, boundary_p, 1); /* in_other_partition. */
/* Also emit any extra name aliases. */
for (alias = node->extra_name; alias; alias = alias->next)
count++;
bp_pack_value (bp, count != 0, 1);
lto_output_bitpack (ob->main_stream, bp);
bitpack_delete (bp);
if (count)
{
lto_output_uleb128_stream (ob->main_stream, count);
for (alias = node->extra_name; alias; alias = alias->next)
lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl);
}
}
/* Stream out profile_summary to OB. */
static void
......@@ -564,6 +603,32 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
}
/* Output the part of the cgraph in SET. */
void
output_varpool (varpool_node_set set)
{
struct varpool_node *node;
struct lto_simple_output_block *ob;
int len = 0;
ob = lto_create_simple_output_block (LTO_section_varpool);
for (node = varpool_nodes; node; node = node->next)
if (node->needed && node->analyzed)
len++;
lto_output_uleb128_stream (ob->main_stream, len);
/* Write out the nodes. We must first output a node and then its clones,
otherwise at a time reading back the node there would be nothing to clone
from. */
for (node = varpool_nodes; node; node = node->next)
if (node->needed && node->analyzed)
lto_output_varpool_node (ob, node, set);
lto_destroy_simple_output_block (ob);
}
/* Read a node from input_block IB. TAG is the node's tag just read.
Return the node read or overwriten. */
......@@ -683,6 +748,48 @@ input_node (struct lto_file_decl_data *file_data,
return node;
}
/* Read a node from input_block IB. TAG is the node's tag just read.
Return the node read or overwriten. */
static struct varpool_node *
input_varpool_node (struct lto_file_decl_data *file_data,
struct lto_input_block *ib)
{
int decl_index;
tree var_decl;
struct varpool_node *node;
struct bitpack_d *bp;
bool aliases_p;
int count;
decl_index = lto_input_uleb128 (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
node = varpool_node (var_decl);
bp = lto_input_bitpack (ib);
node->externally_visible = bp_unpack_value (bp, 1);
node->force_output = bp_unpack_value (bp, 1);
node->finalized = bp_unpack_value (bp, 1);
node->analyzed = 1;
node->used_from_other_partition = bp_unpack_value (bp, 1);
node->in_other_partition = bp_unpack_value (bp, 1);
aliases_p = bp_unpack_value (bp, 1);
if (node->finalized)
varpool_mark_needed_node (node);
bitpack_delete (bp);
if (aliases_p)
{
count = lto_input_uleb128 (ib);
for (; count > 0; count --)
{
tree decl = lto_file_decl_data_get_var_decl (file_data,
lto_input_uleb128 (ib));
varpool_extra_name_alias (decl, var_decl);
}
}
return node;
}
/* Read an edge from IB. NODES points to a vector of previously read nodes for
decoding caller and callee of the edge to be read. If INDIRECT is true, the
......@@ -812,6 +919,22 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
VEC_free (cgraph_node_ptr, heap, nodes);
}
/* Read a varpool from IB using the info in FILE_DATA. */
static void
input_varpool_1 (struct lto_file_decl_data *file_data,
struct lto_input_block *ib)
{
unsigned HOST_WIDE_INT len;
len = lto_input_uleb128 (ib);
while (len)
{
input_varpool_node (file_data, ib);
len--;
}
}
static struct gcov_ctr_summary lto_gcov_summary;
/* Input profile_info from IB. */
......@@ -867,6 +990,12 @@ input_cgraph (void)
lto_destroy_simple_input_block (file_data, LTO_section_cgraph,
ib, data, len);
ib = lto_create_simple_input_block (file_data, LTO_section_varpool,
&data, &len);
input_varpool_1 (file_data, ib);
lto_destroy_simple_input_block (file_data, LTO_section_varpool,
ib, data, len);
/* Assume that every file read needs to be processed by LTRANS. */
if (flag_wpa)
lto_mark_file_for_ltrans (file_data);
......
......@@ -52,6 +52,8 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
"function_body",
"static_initializer",
"cgraph",
"varpool",
"jump_funcs"
"ipa_pure_const",
"ipa_reference",
"symtab",
......
......@@ -358,8 +358,6 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
case LTO_label_decl_ref:
ix_u = lto_input_uleb128 (ib);
result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u);
if (TREE_CODE (result) == VAR_DECL)
varpool_mark_needed_node (varpool_node (result));
break;
default:
......@@ -2727,17 +2725,6 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
the code and class. */
result = lto_get_builtin_tree (ib, data_in);
}
else if (tag == LTO_var_decl_alias)
{
/* An extra_name alias for a variable. */
unsigned HOST_WIDE_INT ix;
tree target;
ix = lto_input_uleb128 (ib);
result = lto_file_decl_data_get_var_decl (data_in->file_data, ix);
ix = lto_input_uleb128 (ib);
target = lto_file_decl_data_get_var_decl (data_in->file_data, ix);
varpool_extra_name_alias (result, target);
}
else if (tag == lto_tree_code_to_tag (INTEGER_CST))
{
/* For integer constants we only need the type and its hi/low
......
......@@ -1930,22 +1930,14 @@ output_function (struct cgraph_node *node)
the file processed by LTRANS. */
static bool
output_alias_pair_p (alias_pair *p, cgraph_node_set set)
output_alias_pair_p (alias_pair *p, cgraph_node_set set, varpool_node_set vset)
{
cgraph_node_set_iterator csi;
struct cgraph_node *target_node;
/* Always emit VAR_DECLs. FIXME lto, we should probably only emit
those VAR_DECLs that are instantiated in this file partition, but
we have no easy way of knowing this based on SET. */
if (TREE_CODE (p->decl) == VAR_DECL)
return true;
return varpool_node_in_set_p (varpool_node_for_asm (p->target), vset);
/* Check if the assembler name for P->TARGET has its cgraph node in SET. */
gcc_assert (TREE_CODE (p->decl) == FUNCTION_DECL);
target_node = cgraph_node_for_asm (p->target);
csi = cgraph_node_set_find (set, target_node);
return (!csi_end_p (csi));
return cgraph_node_in_set_p (cgraph_node_for_asm (p->target), set);
}
......@@ -1953,7 +1945,7 @@ output_alias_pair_p (alias_pair *p, cgraph_node_set set)
and labels. */
static void
output_unreferenced_globals (cgraph_node_set set)
output_unreferenced_globals (cgraph_node_set set, varpool_node_set vset)
{
struct output_block *ob;
alias_pair *p;
......@@ -1974,40 +1966,28 @@ output_unreferenced_globals (cgraph_node_set set)
symbols at link time if a file defines a global symbol but
never references it. */
FOR_EACH_STATIC_VARIABLE (vnode)
{
tree var = vnode->decl;
if (TREE_CODE (var) == VAR_DECL)
{
struct varpool_node *alias;
/* Output the object in order to output references used in the
initialization. */
lto_output_tree (ob, var, true);
/* If it is public we also need a reference to the object itself. */
if (TREE_PUBLIC (var))
lto_output_tree_ref (ob, var);
/* Also output any extra_name aliases for this variable. */
for (alias = vnode->extra_name; alias; alias = alias->next)
{
lto_output_tree (ob, alias->decl, true);
output_record_start (ob, LTO_var_decl_alias);
lto_output_var_decl_index (ob->decl_state, ob->main_stream,
alias->decl);
lto_output_var_decl_index (ob->decl_state, ob->main_stream,
var);
}
}
}
if (vnode->needed && varpool_node_in_set_p (vnode, vset))
{
tree var = vnode->decl;
if (TREE_CODE (var) == VAR_DECL)
{
/* Output the object in order to output references used in the
initialization. */
lto_output_tree (ob, var, true);
/* If it is public we also need a reference to the object itself. */
if (TREE_PUBLIC (var))
lto_output_tree_ref (ob, var);
}
}
output_zero (ob);
/* Emit the alias pairs for the nodes in SET. */
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
{
if (output_alias_pair_p (p, set))
if (output_alias_pair_p (p, set, vset))
{
lto_output_tree_ref (ob, p->decl);
lto_output_tree_ref (ob, p->target);
......@@ -2091,7 +2071,7 @@ lto_writer_init (void)
/* Main entry point from the pass manager. */
static void
lto_output (cgraph_node_set set)
lto_output (cgraph_node_set set, varpool_node_set vset)
{
struct cgraph_node *node;
struct lto_out_decl_state *decl_state;
......@@ -2124,6 +2104,7 @@ lto_output (cgraph_node_set set)
have been renumbered so that edges can be associated with call
statements using the statement UIDs. */
output_cgraph (set);
output_varpool (vset);
lto_bitmap_free (output);
}
......@@ -2178,20 +2159,6 @@ write_global_stream (struct output_block *ob,
t = lto_tree_ref_encoder_get_tree (encoder, index);
if (!lto_streamer_cache_lookup (ob->writer_cache, t, NULL))
lto_output_tree (ob, t, false);
if (flag_wpa)
{
/* In WPA we should not emit multiple definitions of the
same symbol to all the files in the link set. If
T had already been emitted as the pervailing definition
in one file, do not emit it in the others. */
/* FIXME lto. We should check if T belongs to the
file we are writing to. */
if (TREE_CODE (t) == VAR_DECL
&& TREE_PUBLIC (t)
&& !DECL_EXTERNAL (t))
TREE_ASM_WRITTEN (t) = 1;
}
}
}
......@@ -2444,7 +2411,7 @@ produce_symtab (struct lto_streamer_cache_d *cache)
recover these on other side. */
static void
produce_asm_for_decls (cgraph_node_set set)
produce_asm_for_decls (cgraph_node_set set, varpool_node_set vset)
{
struct lto_out_decl_state *out_state;
struct lto_out_decl_state *fn_out_state;
......@@ -2462,7 +2429,7 @@ produce_asm_for_decls (cgraph_node_set set)
/* Write out unreferenced globals, alias pairs and labels. We defer
doing this until now so that we can write out only what is
needed. */
output_unreferenced_globals (set);
output_unreferenced_globals (set, vset);
memset (&header, 0, sizeof (struct lto_decl_header));
......
......@@ -160,6 +160,9 @@ lto_get_section_name (int section_type, const char *name)
case LTO_section_cgraph:
return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL);
case LTO_section_varpool:
return concat (LTO_SECTION_NAME_PREFIX, ".vars", NULL);
case LTO_section_jump_functions:
return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL);
......
......@@ -217,9 +217,6 @@ enum LTO_tags
/* Special for global streamer. Reference to previously-streamed node. */
LTO_tree_pickle_reference,
/* A decl which exists only to provide an extra symbol for another var. */
LTO_var_decl_alias,
/* References to indexable tree nodes. These objects are stored in
tables that are written separately from the function bodies that
reference them. This way they can be instantiated even when the
......@@ -259,11 +256,11 @@ enum lto_section_type
LTO_section_function_body,
LTO_section_static_initializer,
LTO_section_cgraph,
LTO_section_varpool,
LTO_section_jump_functions,
LTO_section_ipa_pure_const,
LTO_section_ipa_reference,
LTO_section_symtab,
LTO_section_wpa_fixup,
LTO_section_opts,
LTO_N_SECTION_TYPES /* Must be last. */
};
......@@ -834,6 +831,8 @@ int lto_cgraph_encoder_encode (lto_cgraph_encoder_t, struct cgraph_node *);
void lto_cgraph_encoder_delete (lto_cgraph_encoder_t encoder);
void output_cgraph (cgraph_node_set);
void input_cgraph (void);
void output_varpool (varpool_node_set);
void input_varpool (void);
/* In lto-symtab.c. */
......
......@@ -44,6 +44,9 @@ struct GTY(()) lto_symtab_entry_def
/* The cgraph node if decl is a function decl. Filled in during the
merging process. */
struct cgraph_node *node;
/* The varpool node if decl is a variable decl. Filled in during the
merging process. */
struct varpool_node *vnode;
/* LTO file-data and symbol resolution for this decl. */
struct lto_file_decl_data * GTY((skip (""))) file_data;
enum ld_plugin_symbol_resolution resolution;
......@@ -244,6 +247,26 @@ lto_cgraph_replace_node (struct cgraph_node *node,
cgraph_remove_node (node);
}
/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
all edges and removing the old node. */
static void
lto_varpool_replace_node (struct varpool_node *vnode,
struct varpool_node *prevailing_node)
{
/* Merge node flags. */
if (vnode->needed)
{
gcc_assert (prevailing_node->analyzed);
varpool_mark_needed_node (prevailing_node);
}
gcc_assert (!vnode->finalized || prevailing_node->finalized);
gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
/* Finally remove the replaced node. */
varpool_remove_node (vnode);
}
/* Merge two variable or function symbol table entries PREVAILING and ENTRY.
Return false if the symbols are not fully compatible and a diagnostic
should be emitted. */
......@@ -406,6 +429,8 @@ lto_symtab_resolve_symbols (void **slot)
{
if (TREE_CODE (e->decl) == FUNCTION_DECL)
e->node = cgraph_get_node (e->decl);
else if (TREE_CODE (e->decl) == VAR_DECL)
e->vnode = varpool_get_node (e->decl);
}
e = (lto_symtab_entry_t) *slot;
......@@ -559,6 +584,10 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
while (!prevailing->node
&& prevailing->next)
prevailing = prevailing->next;
if (TREE_CODE (prevailing->decl) == VAR_DECL)
while (!prevailing->vnode
&& prevailing->next)
prevailing = prevailing->next;
/* We do not stream varpool nodes, so the first decl has to
be good enough for now.
??? For QOI choose a variable with readonly initializer
......@@ -625,7 +654,8 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
lto_symtab_merge_decls_2 (slot);
/* Drop all but the prevailing decl from the symtab. */
if (TREE_CODE (prevailing->decl) != FUNCTION_DECL)
if (TREE_CODE (prevailing->decl) != FUNCTION_DECL
&& TREE_CODE (prevailing->decl) != VAR_DECL)
prevailing->next = NULL;
return 1;
......@@ -650,8 +680,6 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
if (!prevailing->next)
return 1;
gcc_assert (TREE_CODE (prevailing->decl) == FUNCTION_DECL);
/* Replace the cgraph node of each entry with the prevailing one. */
for (e = prevailing->next; e; e = e->next)
{
......@@ -672,6 +700,8 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
}
lto_cgraph_replace_node (e->node, prevailing->node);
}
if (e->vnode != NULL)
lto_varpool_replace_node (e->vnode, prevailing->vnode);
}
/* Drop all but the prevailing decl from the symtab. */
......
2010-04-28 Jan Hubicka <jh@suse.cz>
* lto.c (lto_varpool_node_sets): New.
(lto_1_to_1_map): Partition varpool too.
(globalize_context_t, globalize_cross_file_statics,
lto_scan_statics_in_ref_table, lto_scan_statics_in_cgraph_node,
lto_scan_statics_in_remaining_global_vars): Remove.
(lto_promote_cross_file_statics): Rewrite.
(get_filename_for_set): Take vset argument.
(lto_wpa_write_files): Pass around vsets.
2010-04-27 Dave Korn <dave.korn.cygwin@gmail.com>
PR lto/42776
......
......@@ -191,7 +191,11 @@ rest_of_decl_compilation (tree decl,
|| DECL_INITIAL (decl))
&& !DECL_EXTERNAL (decl))
{
if (TREE_CODE (decl) != FUNCTION_DECL)
/* When reading LTO unit, we also read varpool, so do not
rebuild it. */
if (in_lto_p && !at_end)
;
else if (TREE_CODE (decl) != FUNCTION_DECL)
varpool_finalize_decl (decl);
else
assemble_variable (decl, top_level, at_end, 0);
......@@ -218,7 +222,9 @@ rest_of_decl_compilation (tree decl,
}
/* Let cgraph know about the existence of variables. */
if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
if (in_lto_p && !at_end)
;
else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
varpool_node (decl);
}
......@@ -1649,6 +1655,7 @@ execute_pass_list (struct opt_pass *pass)
static void
ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set,
varpool_node_set vset,
struct lto_out_decl_state *state)
{
while (pass)
......@@ -1665,7 +1672,7 @@ ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set,
if (pass->tv_id)
timevar_push (pass->tv_id);
ipa_pass->write_summary (set);
ipa_pass->write_summary (set,vset);
/* If a timevar is present, start it. */
if (pass->tv_id)
......@@ -1673,7 +1680,7 @@ ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set,
}
if (pass->sub && pass->sub->type != GIMPLE_PASS)
ipa_write_summaries_2 (pass->sub, set, state);
ipa_write_summaries_2 (pass->sub, set, vset, state);
pass = pass->next;
}
......@@ -1684,14 +1691,14 @@ ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set,
summaries. SET is the set of nodes to be written. */
static void
ipa_write_summaries_1 (cgraph_node_set set)
ipa_write_summaries_1 (cgraph_node_set set, varpool_node_set vset)
{
struct lto_out_decl_state *state = lto_new_out_decl_state ();
lto_push_out_decl_state (state);
gcc_assert (!flag_wpa);
ipa_write_summaries_2 (all_regular_ipa_passes, set, state);
ipa_write_summaries_2 (all_lto_gen_passes, set, state);
ipa_write_summaries_2 (all_regular_ipa_passes, set, vset, state);
ipa_write_summaries_2 (all_lto_gen_passes, set, vset, state);
gcc_assert (lto_get_out_decl_state () == state);
lto_pop_out_decl_state ();
......@@ -1704,7 +1711,9 @@ void
ipa_write_summaries (void)
{
cgraph_node_set set;
varpool_node_set vset;
struct cgraph_node **order;
struct varpool_node *vnode;
int i, order_pos;
if (!flag_generate_lto || errorcount || sorrycount)
......@@ -1736,13 +1745,20 @@ ipa_write_summaries (void)
renumber_gimple_stmt_uids ();
pop_cfun ();
}
cgraph_node_set_add (set, node);
if (node->needed || node->reachable || node->address_taken)
cgraph_node_set_add (set, node);
}
vset = varpool_node_set_new ();
ipa_write_summaries_1 (set);
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
if (vnode->needed && !vnode->alias)
varpool_node_set_add (vset, vnode);
ipa_write_summaries_1 (set, vset);
free (order);
ggc_free (set);
ggc_free (vset);
}
/* Same as execute_pass_list but assume that subpasses of IPA passes
......@@ -1751,6 +1767,7 @@ ipa_write_summaries (void)
static void
ipa_write_optimization_summaries_1 (struct opt_pass *pass, cgraph_node_set set,
varpool_node_set vset,
struct lto_out_decl_state *state)
{
while (pass)
......@@ -1767,7 +1784,7 @@ ipa_write_optimization_summaries_1 (struct opt_pass *pass, cgraph_node_set set,
if (pass->tv_id)
timevar_push (pass->tv_id);
ipa_pass->write_optimization_summary (set);
ipa_pass->write_optimization_summary (set, vset);
/* If a timevar is present, start it. */
if (pass->tv_id)
......@@ -1775,7 +1792,7 @@ ipa_write_optimization_summaries_1 (struct opt_pass *pass, cgraph_node_set set,
}
if (pass->sub && pass->sub->type != GIMPLE_PASS)
ipa_write_optimization_summaries_1 (pass->sub, set, state);
ipa_write_optimization_summaries_1 (pass->sub, set, vset, state);
pass = pass->next;
}
......@@ -1785,14 +1802,14 @@ ipa_write_optimization_summaries_1 (struct opt_pass *pass, cgraph_node_set set,
NULL, write out all summaries of all nodes. */
void
ipa_write_optimization_summaries (cgraph_node_set set)
ipa_write_optimization_summaries (cgraph_node_set set, varpool_node_set vset)
{
struct lto_out_decl_state *state = lto_new_out_decl_state ();
lto_push_out_decl_state (state);
gcc_assert (flag_wpa);
ipa_write_optimization_summaries_1 (all_regular_ipa_passes, set, state);
ipa_write_optimization_summaries_1 (all_lto_gen_passes, set, state);
ipa_write_optimization_summaries_1 (all_regular_ipa_passes, set, vset, state);
ipa_write_optimization_summaries_1 (all_lto_gen_passes, set, vset, state);
gcc_assert (lto_get_out_decl_state () == state);
lto_pop_out_decl_state ();
......
......@@ -168,6 +168,7 @@ struct rtl_opt_pass
struct varpool_node;
struct cgraph_node;
struct cgraph_node_set_def;
struct varpool_node_set_def;
/* Description of IPA pass with generate summary, write, execute, read and
transform stages. */
......@@ -180,13 +181,15 @@ struct ipa_opt_pass_d
void (*generate_summary) (void);
/* This hook is used to serialize IPA summaries on disk. */
void (*write_summary) (struct cgraph_node_set_def *);
void (*write_summary) (struct cgraph_node_set_def *,
struct varpool_node_set_def *);
/* This hook is used to deserialize IPA summaries from disk. */
void (*read_summary) (void);
/* This hook is used to serialize IPA optimization summaries on disk. */
void (*write_optimization_summary) (struct cgraph_node_set_def *);
void (*write_optimization_summary) (struct cgraph_node_set_def *,
struct varpool_node_set_def *);
/* This hook is used to deserialize IPA summaries from disk. */
void (*read_optimization_summary) (void);
......@@ -607,7 +610,8 @@ extern const char *get_current_pass_name (void);
extern void print_current_pass (FILE *);
extern void debug_pass (void);
extern void ipa_write_summaries (void);
extern void ipa_write_optimization_summaries (struct cgraph_node_set_def *);
extern void ipa_write_optimization_summaries (struct cgraph_node_set_def *,
struct varpool_node_set_def *);
extern void ipa_read_summaries (void);
extern void ipa_read_optimization_summaries (void);
extern void register_one_dump_file (struct opt_pass *);
......
......@@ -105,6 +105,22 @@ eq_varpool_node (const void *p1, const void *p2)
return DECL_UID (n1->decl) == DECL_UID (n2->decl);
}
/* Return varpool node assigned to DECL without creating new one. */
struct varpool_node *
varpool_get_node (tree decl)
{
struct varpool_node key, **slot;
gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
if (!varpool_hash)
return NULL;
key.decl = decl;
slot = (struct varpool_node **)
htab_find_slot (varpool_hash, &key, INSERT);
return *slot;
}
/* Return varpool node assigned to DECL. Create new one when needed. */
struct varpool_node *
varpool_node (tree decl)
......@@ -125,11 +141,50 @@ varpool_node (tree decl)
node->decl = decl;
node->order = cgraph_order++;
node->next = varpool_nodes;
if (varpool_nodes)
varpool_nodes->prev = node;
varpool_nodes = node;
*slot = node;
return node;
}
/* Remove node from the varpool. */
void
varpool_remove_node (struct varpool_node *node)
{
void **slot;
slot = htab_find_slot (varpool_hash, node, NO_INSERT);
gcc_assert (*slot == node);
htab_clear_slot (varpool_hash, slot);
gcc_assert (!varpool_assembled_nodes_queue);
if (node->next)
node->next->prev = node->prev;
if (node->prev)
node->prev->next = node->next;
else if (node->next)
{
gcc_assert (varpool_nodes == node);
varpool_nodes = node->next;
}
if (varpool_first_unanalyzed_node == node)
varpool_first_unanalyzed_node = node->next_needed;
if (node->next_needed)
node->next_needed->prev_needed = node->prev_needed;
else if (node->prev_needed)
{
gcc_assert (varpool_last_needed_node);
varpool_last_needed_node = node->prev_needed;
}
if (node->prev_needed)
node->prev_needed->next_needed = node->next_needed;
else if (node->next_needed)
{
gcc_assert (varpool_nodes_queue == node);
varpool_nodes_queue = node->next_needed;
}
node->decl = NULL;
}
/* Dump given cgraph node. */
void
dump_varpool_node (FILE *f, struct varpool_node *node)
......@@ -139,8 +194,12 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
cgraph_function_flags_ready
? cgraph_availability_names[cgraph_variable_initializer_availability (node)]
: "not-ready");
if (DECL_ASSEMBLER_NAME_SET_P (node->decl))
fprintf (f, " (asm: %s)", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
if (DECL_INITIAL (node->decl))
fprintf (f, " initialized");
if (TREE_ASM_WRITTEN (node->decl))
fprintf (f, " (asm written)");
if (node->needed)
fprintf (f, " needed");
if (node->analyzed)
......@@ -151,6 +210,10 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
fprintf (f, " output");
if (node->externally_visible)
fprintf (f, " externally_visible");
if (node->in_other_partition)
fprintf (f, " in_other_partition");
else if (node->used_from_other_partition)
fprintf (f, " used_from_other_partition");
fprintf (f, "\n");
}
......@@ -192,7 +255,10 @@ static void
varpool_enqueue_needed_node (struct varpool_node *node)
{
if (varpool_last_needed_node)
varpool_last_needed_node->next_needed = node;
{
varpool_last_needed_node->next_needed = node;
node->prev_needed = varpool_last_needed_node;
}
varpool_last_needed_node = node;
node->next_needed = NULL;
if (!varpool_nodes_queue)
......@@ -230,11 +296,7 @@ varpool_reset_queue (void)
bool
decide_is_variable_needed (struct varpool_node *node, tree decl)
{
/* We do not track variable references at all and thus have no idea if the
variable was referenced in some other partition or not.
FIXME: We really need address taken edges in callgraph and varpool to
drive WPA and decide whether other partition might reference it or not. */
if (flag_ltrans)
if (node->used_from_other_partition)
return true;
/* If the user told us it is used, then it must be so. */
if ((node->externally_visible && !DECL_COMDAT (decl))
......@@ -288,17 +350,6 @@ varpool_finalize_decl (tree decl)
{
struct varpool_node *node = varpool_node (decl);
/* FIXME: We don't really stream varpool datastructure and instead rebuild it
by varpool_finalize_decl. This is not quite correct since this way we can't
attach any info to varpool. Eventually we will want to stream varpool nodes
and the flags.
For the moment just prevent analysis of varpool nodes to happen again, so
we will re-try to compute "address_taken" flag of varpool that breaks
in presence of clones. */
if (in_lto_p)
node->analyzed = true;
/* The first declaration of a variable that comes through this function
decides whether it is global (in C, has external linkage)
or local (in C, has internal linkage). So do nothing more
......@@ -364,7 +415,7 @@ varpool_analyze_pending_decls (void)
We however don't want to re-analyze already analyzed nodes. */
if (!analyzed)
{
gcc_assert (!in_lto_p);
gcc_assert (!in_lto_p || cgraph_function_flags_ready);
/* Compute the alignment early so function body expanders are
already informed about increased alignment. */
align_variable (decl, 0);
......@@ -385,6 +436,7 @@ varpool_assemble_decl (struct varpool_node *node)
if (!TREE_ASM_WRITTEN (decl)
&& !node->alias
&& !node->in_other_partition
&& !DECL_EXTERNAL (decl)
&& (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
{
......@@ -394,6 +446,9 @@ varpool_assemble_decl (struct varpool_node *node)
struct varpool_node *alias;
node->next_needed = varpool_assembled_nodes_queue;
node->prev_needed = NULL;
if (varpool_assembled_nodes_queue)
varpool_assembled_nodes_queue->prev_needed = node;
varpool_assembled_nodes_queue = node;
node->finalized = 1;
......@@ -476,7 +531,10 @@ varpool_assemble_pending_decls (void)
if (varpool_assemble_decl (node))
changed = true;
else
node->next_needed = NULL;
{
node->prev_needed = NULL;
node->next_needed = NULL;
}
}
/* varpool_nodes_queue is now empty, clear the pointer to the last element
in the queue. */
......@@ -498,6 +556,7 @@ varpool_empty_needed_queue (void)
struct varpool_node *node = varpool_nodes_queue;
varpool_nodes_queue = varpool_nodes_queue->next_needed;
node->next_needed = NULL;
node->prev_needed = NULL;
}
/* varpool_nodes_queue is now empty, clear the pointer to the last element
in the queue. */
......@@ -559,6 +618,8 @@ varpool_extra_name_alias (tree alias, tree decl)
alias_node->alias = 1;
alias_node->extra_name = decl_node;
alias_node->next = decl_node->extra_name;
if (decl_node->extra_name)
decl_node->extra_name->prev = alias_node;
decl_node->extra_name = alias_node;
*slot = alias_node;
return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment