lto: Remap node order for stability.
This patch adds remapping of node order for each lto partition. Resulting order conserves relative order inside partition, but is independent of outside symbols. So if lto partition contains identical set of symbols, their remapped order will be stable between compilations. This stability is needed for Incremental LTO. gcc/ChangeLog: * ipa-devirt.cc (ipa_odr_summary_write): Add unused argument. * ipa-fnsummary.cc (ipa_fn_summary_write): Likewise. * ipa-icf.cc (sem_item_optimizer::write_summary): Likewise. * ipa-modref.cc (modref_write): Likewise. * ipa-prop.cc (ipa_prop_write_jump_functions): Likewise. (ipcp_write_transformation_summaries): Likewise. * ipa-sra.cc (ipa_sra_write_summary): Likewise. * lto-cgraph.cc (lto_symtab_encoder_delete): Delete remap. (lto_output_node): Remap order. (lto_output_varpool_node): Likewise. (output_cgraph_opt_summary): Add unused argument. * lto-streamer-out.cc (produce_symbol_asm): Renamed. Use remapped order. (produce_asm): Rename. New wrapper. (output_function): Propagate remapped order. (output_constructor): Likewise. (copy_function_or_variable): Likewise. (cmp_int): New. (create_order_remap): New. (lto_output): Create remap. Remap order. * lto-streamer.h (struct lto_symtab_encoder_d): Remap hash_map. (produce_asm): Add order argument.
This commit is contained in:
parent
0895aef01c
commit
b47e7eabff
9 changed files with 99 additions and 25 deletions
|
@ -4131,7 +4131,7 @@ ipa_odr_summary_write (void)
|
|||
odr_enum_map = NULL;
|
||||
}
|
||||
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -5091,7 +5091,7 @@ ipa_fn_summary_write (void)
|
|||
}
|
||||
}
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
|
||||
ipa_prop_write_jump_functions ();
|
||||
|
|
|
@ -2216,7 +2216,7 @@ sem_item_optimizer::write_summary (void)
|
|||
}
|
||||
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -3746,7 +3746,7 @@ modref_write ()
|
|||
{
|
||||
streamer_write_uhwi (ob, 0);
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
return;
|
||||
}
|
||||
|
@ -3821,7 +3821,7 @@ modref_write ()
|
|||
}
|
||||
}
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -5430,7 +5430,7 @@ ipa_prop_write_jump_functions (void)
|
|||
ipa_write_node_info (ob, node);
|
||||
}
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
@ -5628,7 +5628,7 @@ ipcp_write_transformation_summaries (void)
|
|||
write_ipcp_transformation_info (ob, cnode, ts);
|
||||
}
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -2898,7 +2898,7 @@ ipa_sra_write_summary (void)
|
|||
isra_write_node_summary (ob, node);
|
||||
}
|
||||
streamer_write_char_stream (ob->main_stream, 0);
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,8 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
|
|||
encoder->nodes.release ();
|
||||
if (encoder->map)
|
||||
delete encoder->map;
|
||||
if (encoder->order_remap)
|
||||
delete encoder->order_remap;
|
||||
free (encoder);
|
||||
}
|
||||
|
||||
|
@ -405,7 +407,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
|||
|
||||
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
|
||||
tag);
|
||||
streamer_write_hwi_stream (ob->main_stream, node->order);
|
||||
int output_order = *encoder->order_remap->get (node->order);
|
||||
streamer_write_hwi_stream (ob->main_stream, output_order);
|
||||
|
||||
/* In WPA mode, we only output part of the call-graph. Also, we
|
||||
fake cgraph node attributes. There are two cases that we care.
|
||||
|
@ -602,7 +605,8 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
|
|||
|
||||
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
|
||||
LTO_symtab_variable);
|
||||
streamer_write_hwi_stream (ob->main_stream, node->order);
|
||||
int output_order = *encoder->order_remap->get (node->order);
|
||||
streamer_write_hwi_stream (ob->main_stream, output_order);
|
||||
lto_output_var_decl_ref (ob->decl_state, ob->main_stream, node->decl);
|
||||
bp = bitpack_create (ob->main_stream);
|
||||
bp_pack_value (&bp, node->externally_visible, 1);
|
||||
|
@ -2111,7 +2115,7 @@ output_cgraph_opt_summary (void)
|
|||
output_node_opt_summary (ob, cnode, encoder);
|
||||
}
|
||||
}
|
||||
produce_asm (ob, NULL);
|
||||
produce_asm (ob);
|
||||
destroy_output_block (ob);
|
||||
}
|
||||
|
||||
|
|
|
@ -2202,12 +2202,11 @@ output_cfg (struct output_block *ob, struct function *fn)
|
|||
ob->main_stream = tmp_stream;
|
||||
}
|
||||
|
||||
|
||||
/* Create the header in the file using OB. If the section type is for
|
||||
a function, set FN to the decl for that function. */
|
||||
|
||||
void
|
||||
produce_asm (struct output_block *ob, tree fn)
|
||||
produce_symbol_asm (struct output_block *ob, tree fn, int output_order)
|
||||
{
|
||||
enum lto_section_type section_type = ob->section_type;
|
||||
struct lto_function_header header;
|
||||
|
@ -2217,8 +2216,7 @@ produce_asm (struct output_block *ob, tree fn)
|
|||
{
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn));
|
||||
section_name = lto_get_section_name (section_type, name,
|
||||
symtab_node::get (fn)->order,
|
||||
NULL);
|
||||
output_order, NULL);
|
||||
}
|
||||
else
|
||||
section_name = lto_get_section_name (section_type, NULL, 0, NULL);
|
||||
|
@ -2245,6 +2243,14 @@ produce_asm (struct output_block *ob, tree fn)
|
|||
lto_end_section ();
|
||||
}
|
||||
|
||||
/* Wrapper for unused arguments. */
|
||||
|
||||
void
|
||||
produce_asm (struct output_block *ob)
|
||||
{
|
||||
produce_symbol_asm (ob, NULL, -1);
|
||||
}
|
||||
|
||||
|
||||
/* Output the base body of struct function FN using output block OB. */
|
||||
|
||||
|
@ -2402,7 +2408,7 @@ streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
|
|||
/* Output the body of function NODE->DECL. */
|
||||
|
||||
static void
|
||||
output_function (struct cgraph_node *node)
|
||||
output_function (struct cgraph_node *node, int output_order)
|
||||
{
|
||||
tree function;
|
||||
struct function *fn;
|
||||
|
@ -2479,7 +2485,7 @@ output_function (struct cgraph_node *node)
|
|||
streamer_write_uhwi (ob, 0);
|
||||
|
||||
/* Create a section to hold the pickled output of this function. */
|
||||
produce_asm (ob, function);
|
||||
produce_symbol_asm (ob, function, output_order);
|
||||
|
||||
destroy_output_block (ob);
|
||||
if (streamer_dump_file)
|
||||
|
@ -2490,7 +2496,7 @@ output_function (struct cgraph_node *node)
|
|||
/* Output the body of function NODE->DECL. */
|
||||
|
||||
static void
|
||||
output_constructor (struct varpool_node *node)
|
||||
output_constructor (struct varpool_node *node, int output_order)
|
||||
{
|
||||
tree var = node->decl;
|
||||
struct output_block *ob;
|
||||
|
@ -2512,7 +2518,7 @@ output_constructor (struct varpool_node *node)
|
|||
stream_write_tree (ob, DECL_INITIAL (var), true);
|
||||
|
||||
/* Create a section to hold the pickled output of this function. */
|
||||
produce_asm (ob, var);
|
||||
produce_symbol_asm (ob, var, output_order);
|
||||
|
||||
destroy_output_block (ob);
|
||||
if (streamer_dump_file)
|
||||
|
@ -2580,7 +2586,7 @@ lto_output_toplevel_asms (void)
|
|||
/* Copy the function body or variable constructor of NODE without deserializing. */
|
||||
|
||||
static void
|
||||
copy_function_or_variable (struct symtab_node *node)
|
||||
copy_function_or_variable (struct symtab_node *node, int output_order)
|
||||
{
|
||||
tree function = node->decl;
|
||||
struct lto_file_decl_data *file_data = node->lto_file_data;
|
||||
|
@ -2588,7 +2594,7 @@ copy_function_or_variable (struct symtab_node *node)
|
|||
size_t len;
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
|
||||
char *section_name =
|
||||
lto_get_section_name (LTO_section_function_body, name, node->order, NULL);
|
||||
lto_get_section_name (LTO_section_function_body, name, output_order, NULL);
|
||||
size_t i, j;
|
||||
struct lto_in_decl_state *in_state;
|
||||
struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
|
||||
|
@ -2733,6 +2739,63 @@ cmp_symbol_files (const void *pn1, const void *pn2, void *id_map_)
|
|||
return n1->order - n2->order;
|
||||
}
|
||||
|
||||
/* Compare ints, callback for qsort. */
|
||||
|
||||
static int
|
||||
cmp_int (const void *a, const void *b)
|
||||
{
|
||||
int ia = *(int const*) a;
|
||||
int ib = *(int const*) b;
|
||||
return ia - ib;
|
||||
}
|
||||
|
||||
/* Create order mapping independent on symbols outside of the partition.
|
||||
Results in stable order values for incremental LTO.
|
||||
|
||||
Remapping is not done in place, because symbols can be used
|
||||
by multiple partitions. */
|
||||
|
||||
static void
|
||||
create_order_remap (lto_symtab_encoder_t encoder)
|
||||
{
|
||||
auto_vec<int> orders;
|
||||
unsigned i;
|
||||
struct asm_node* anode;
|
||||
encoder->order_remap = new hash_map<int_hash<int, -1, -2>, int>;
|
||||
unsigned n_nodes = lto_symtab_encoder_size (encoder);
|
||||
|
||||
for (i = 0; i < n_nodes; i++)
|
||||
orders.safe_push (lto_symtab_encoder_deref (encoder, i)->order);
|
||||
|
||||
if (!asm_nodes_output)
|
||||
{
|
||||
for (anode = symtab->first_asm_symbol (); anode; anode = anode->next)
|
||||
orders.safe_push (anode->order);
|
||||
}
|
||||
|
||||
orders.qsort (cmp_int);
|
||||
int ord = 0;
|
||||
int last_order = -1;
|
||||
for (i = 0; i < orders.length (); i++)
|
||||
{
|
||||
int order = orders[i];
|
||||
if (order != last_order)
|
||||
{
|
||||
last_order = order;
|
||||
encoder->order_remap->put (order, ord);
|
||||
ord++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Asm nodes are currently always output only into first partition.
|
||||
We can remap already here. */
|
||||
if (!asm_nodes_output)
|
||||
{
|
||||
for (anode = symtab->first_asm_symbol (); anode; anode = anode->next)
|
||||
anode->order = *encoder->order_remap->get (anode->order);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main entry point from the pass manager. */
|
||||
|
||||
void
|
||||
|
@ -2745,6 +2808,8 @@ lto_output (void)
|
|||
lto_symtab_encoder_t encoder = lto_get_out_decl_state ()->symtab_node_encoder;
|
||||
auto_vec<symtab_node *> symbols_to_copy;
|
||||
|
||||
create_order_remap (encoder);
|
||||
|
||||
prune_offload_funcs ();
|
||||
|
||||
if (flag_checking)
|
||||
|
@ -2807,6 +2872,8 @@ lto_output (void)
|
|||
cgraph_node *cnode;
|
||||
varpool_node *vnode;
|
||||
|
||||
int output_order = *encoder->order_remap->get (snode->order);
|
||||
|
||||
if (flag_checking)
|
||||
gcc_assert (bitmap_set_bit (output, DECL_UID (snode->decl)));
|
||||
|
||||
|
@ -2821,14 +2888,14 @@ lto_output (void)
|
|||
at WPA time. */
|
||||
|| DECL_ARGUMENTS (cnode->decl)
|
||||
|| cnode->declare_variant_alt))
|
||||
output_function (cnode);
|
||||
output_function (cnode, output_order);
|
||||
else if ((vnode = dyn_cast <varpool_node *> (snode))
|
||||
&& (DECL_INITIAL (vnode->decl) != error_mark_node
|
||||
|| (!flag_wpa
|
||||
&& flag_incremental_link != INCREMENTAL_LINK_LTO)))
|
||||
output_constructor (vnode);
|
||||
output_constructor (vnode, output_order);
|
||||
else
|
||||
copy_function_or_variable (snode);
|
||||
copy_function_or_variable (snode, output_order);
|
||||
gcc_assert (lto_get_out_decl_state () == decl_state);
|
||||
lto_pop_out_decl_state ();
|
||||
lto_record_function_out_decl_state (snode->decl, decl_state);
|
||||
|
|
|
@ -470,6 +470,9 @@ struct lto_symtab_encoder_d
|
|||
{
|
||||
vec<lto_encoder_entry> nodes;
|
||||
hash_map<symtab_node *, size_t> *map;
|
||||
|
||||
/* Mapping of input order of nodes onto output order. */
|
||||
hash_map<int_hash<int, -1, -2>, int> *order_remap;
|
||||
};
|
||||
|
||||
typedef struct lto_symtab_encoder_d *lto_symtab_encoder_t;
|
||||
|
@ -896,7 +899,7 @@ extern void lto_output_fn_decl_ref (struct lto_out_decl_state *,
|
|||
extern tree lto_input_var_decl_ref (lto_input_block *, lto_file_decl_data *);
|
||||
extern tree lto_input_fn_decl_ref (lto_input_block *, lto_file_decl_data *);
|
||||
extern void lto_output_toplevel_asms (void);
|
||||
extern void produce_asm (struct output_block *ob, tree fn);
|
||||
extern void produce_asm (struct output_block *ob);
|
||||
extern void lto_output ();
|
||||
extern void produce_asm_for_decls ();
|
||||
void lto_output_decl_state_streams (struct output_block *,
|
||||
|
|
Loading…
Add table
Reference in a new issue