mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-17 09:13:49 +08:00
passes.c (ipa_write_summaries_1): Set state; do not call compute_ltrans_boundary.
* passes.c (ipa_write_summaries_1): Set state; do not call compute_ltrans_boundary. (ipa_write_optimization_summaries): Likewise. (ipa_write_summaries): compute_ltrans_boundary here. * lto-streamer.h (lto_symtab_encoder_d): NODES are allocated in heap. (compute_ltrans_boundary): Update prototype. * lto.c (lto_wpa_write_files): Do not delete partition encoder; it is deleted after streaming. * lto-partition.c (partition_symbol_p): New function. (promote_var, promote_fn): Remove. (promote_symbol): New function. (lto_promote_cross_file_statics): First compute boundaries; rewrite to lookup the actual boundaries instead of computing them ad-hoc. From-SVN: r191113
This commit is contained in:
parent
3ca6351daa
commit
b4661bfe21
@ -1,3 +1,12 @@
|
||||
2012-09-09 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* passes.c (ipa_write_summaries_1): Set state;
|
||||
do not call compute_ltrans_boundary.
|
||||
(ipa_write_optimization_summaries): Likewise.
|
||||
(ipa_write_summaries): compute_ltrans_boundary here.
|
||||
* lto-streamer.h (lto_symtab_encoder_d): NODES are allocated in heap.
|
||||
(compute_ltrans_boundary): Update prototype.
|
||||
|
||||
2012-09-09 Ulrich Drepper <drepper@gmail.com>
|
||||
|
||||
* config/i386/cpuid.h: Define signature_*_e[bcd]x macros for
|
||||
|
@ -588,38 +588,6 @@ output_profile_summary (struct lto_simple_output_block *ob)
|
||||
streamer_write_uhwi_stream (ob->main_stream, 0);
|
||||
}
|
||||
|
||||
/* Add NODE into encoder as well as nodes it is cloned from.
|
||||
Do it in a way so clones appear first. */
|
||||
|
||||
static void
|
||||
add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
|
||||
bool include_body)
|
||||
{
|
||||
if (node->clone_of)
|
||||
add_node_to (encoder, node->clone_of, include_body);
|
||||
else if (include_body)
|
||||
lto_set_symtab_encoder_encode_body (encoder, node);
|
||||
lto_symtab_encoder_encode (encoder, (symtab_node)node);
|
||||
}
|
||||
|
||||
/* Add all references in LIST to encoders. */
|
||||
|
||||
static void
|
||||
add_references (lto_symtab_encoder_t encoder,
|
||||
struct ipa_ref_list *list)
|
||||
{
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
|
||||
if (symtab_function_p (ref->referred))
|
||||
add_node_to (encoder, ipa_ref_node (ref), false);
|
||||
else
|
||||
{
|
||||
struct varpool_node *vnode = ipa_ref_varpool_node (ref);
|
||||
lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output all callees or indirect outgoing edges. EDGE must be the first such
|
||||
edge. */
|
||||
|
||||
@ -674,11 +642,48 @@ output_refs (lto_symtab_encoder_t encoder)
|
||||
lto_destroy_simple_output_block (ob);
|
||||
}
|
||||
|
||||
/* Find out all cgraph and varpool nodes we want to encode in current unit
|
||||
and insert them to encoders. */
|
||||
void
|
||||
compute_ltrans_boundary (struct lto_out_decl_state *state,
|
||||
lto_symtab_encoder_t in_encoder)
|
||||
/* Add NODE into encoder as well as nodes it is cloned from.
|
||||
Do it in a way so clones appear first. */
|
||||
|
||||
static void
|
||||
add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
|
||||
bool include_body)
|
||||
{
|
||||
if (node->clone_of)
|
||||
add_node_to (encoder, node->clone_of, include_body);
|
||||
else if (include_body)
|
||||
lto_set_symtab_encoder_encode_body (encoder, node);
|
||||
lto_symtab_encoder_encode (encoder, (symtab_node)node);
|
||||
}
|
||||
|
||||
/* Add all references in LIST to encoders. */
|
||||
|
||||
static void
|
||||
add_references (lto_symtab_encoder_t encoder,
|
||||
struct ipa_ref_list *list)
|
||||
{
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
|
||||
if (symtab_function_p (ref->referred))
|
||||
add_node_to (encoder, ipa_ref_node (ref), false);
|
||||
else
|
||||
{
|
||||
struct varpool_node *vnode = ipa_ref_varpool_node (ref);
|
||||
lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find all symbols we want to stream into given partition and insert them
|
||||
to encoders.
|
||||
|
||||
The function actually replaces IN_ENCODER by new one. The reason is that
|
||||
streaming code needs clone's origin to be streamed before clone. This
|
||||
means that we need to insert the nodes in specific order. This order is
|
||||
ignored by the partitioning logic earlier. */
|
||||
|
||||
lto_symtab_encoder_t
|
||||
compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *edge;
|
||||
@ -686,7 +691,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state,
|
||||
lto_symtab_encoder_t encoder;
|
||||
lto_symtab_encoder_iterator lsei;
|
||||
|
||||
encoder = state->symtab_node_encoder = lto_symtab_encoder_new ();
|
||||
encoder = lto_symtab_encoder_new ();
|
||||
|
||||
/* Go over all entries in the IN_ENCODER and duplicate them to
|
||||
ENCODER. At the same time insert masters of clones so
|
||||
@ -747,6 +752,8 @@ compute_ltrans_boundary (struct lto_out_decl_state *state,
|
||||
}
|
||||
}
|
||||
}
|
||||
lto_symtab_encoder_delete (in_encoder);
|
||||
return encoder;
|
||||
}
|
||||
|
||||
/* Output the part of the symtab in SET and VSET. */
|
||||
|
@ -441,7 +441,7 @@ DEF_VEC_ALLOC_O(lto_encoder_entry, heap);
|
||||
/* Encoder data structure used to stream callgraph nodes. */
|
||||
struct lto_symtab_encoder_d
|
||||
{
|
||||
VEC(lto_encoder_entry,gc) *nodes;
|
||||
VEC(lto_encoder_entry,heap) *nodes;
|
||||
pointer_map_t *map;
|
||||
};
|
||||
|
||||
@ -856,8 +856,7 @@ bool referenced_from_this_partition_p (struct ipa_ref_list *,
|
||||
lto_symtab_encoder_t);
|
||||
bool reachable_from_this_partition_p (struct cgraph_node *,
|
||||
lto_symtab_encoder_t);
|
||||
void compute_ltrans_boundary (struct lto_out_decl_state *state,
|
||||
lto_symtab_encoder_t encoder);
|
||||
lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
|
||||
|
||||
|
||||
/* In lto-symtab.c. */
|
||||
|
@ -1,3 +1,13 @@
|
||||
2012-08-12 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto.c (lto_wpa_write_files): Do not delete partition encoder;
|
||||
it is deleted after streaming.
|
||||
* lto-partition.c (partition_symbol_p): New function.
|
||||
(promote_var, promote_fn): Remove.
|
||||
(promote_symbol): New function.
|
||||
(lto_promote_cross_file_statics): First compute boundaries; rewrite
|
||||
to lookup the actual boundaries instead of computing them ad-hoc.
|
||||
|
||||
2012-08-12 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
Replace cgraph_node_set and varpool_node_set by symtab_node_encoder
|
||||
|
@ -280,6 +280,18 @@ partition_varpool_node_p (struct varpool_node *vnode)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true if NODE should be partitioned.
|
||||
This means that partitioning algorithm should put NODE into one of partitions. */
|
||||
|
||||
static bool
|
||||
partition_symbol_p (symtab_node node)
|
||||
{
|
||||
if (symtab_function_p (node))
|
||||
return partition_cgraph_node_p (cgraph (node));
|
||||
else
|
||||
return partition_varpool_node_p (varpool (node));
|
||||
}
|
||||
|
||||
/* Group cgrah nodes by input files. This is used mainly for testing
|
||||
right now. */
|
||||
|
||||
@ -739,39 +751,26 @@ lto_balanced_map (void)
|
||||
|
||||
/* Promote variable VNODE to be static. */
|
||||
|
||||
static bool
|
||||
promote_var (struct varpool_node *vnode)
|
||||
static void
|
||||
promote_symbol (symtab_node node)
|
||||
{
|
||||
if (TREE_PUBLIC (vnode->symbol.decl) || DECL_EXTERNAL (vnode->symbol.decl))
|
||||
return false;
|
||||
gcc_assert (flag_wpa);
|
||||
TREE_PUBLIC (vnode->symbol.decl) = 1;
|
||||
DECL_VISIBILITY (vnode->symbol.decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (vnode->symbol.decl) = true;
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Promoting var as hidden: %s\n", varpool_node_name (vnode));
|
||||
return true;
|
||||
}
|
||||
/* We already promoted ... */
|
||||
if (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
|
||||
&& DECL_VISIBILITY_SPECIFIED (node->symbol.decl)
|
||||
&& TREE_PUBLIC (node->symbol.decl))
|
||||
return;
|
||||
|
||||
/* Promote function NODE to be static. */
|
||||
|
||||
static bool
|
||||
promote_fn (struct cgraph_node *node)
|
||||
{
|
||||
gcc_assert (flag_wpa);
|
||||
if (TREE_PUBLIC (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
|
||||
return false;
|
||||
gcc_checking_assert (!TREE_PUBLIC (node->symbol.decl)
|
||||
&& !DECL_EXTERNAL (node->symbol.decl));
|
||||
TREE_PUBLIC (node->symbol.decl) = 1;
|
||||
DECL_VISIBILITY (node->symbol.decl) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (node->symbol.decl) = true;
|
||||
if (cgraph_dump_file)
|
||||
fprintf (cgraph_dump_file,
|
||||
"Promoting function as hidden: %s/%i\n",
|
||||
cgraph_node_name (node), node->uid);
|
||||
return true;
|
||||
"Promoting as hidden: %s\n", symtab_node_name (node));
|
||||
}
|
||||
|
||||
|
||||
/* Find out all static decls that need to be promoted to global because
|
||||
of cross file sharing. This function must be run in the WPA mode after
|
||||
all inlinees are added. */
|
||||
@ -779,118 +778,43 @@ promote_fn (struct cgraph_node *node)
|
||||
void
|
||||
lto_promote_cross_file_statics (void)
|
||||
{
|
||||
struct varpool_node *vnode;
|
||||
unsigned i, n_sets;
|
||||
VEC(varpool_node_ptr, heap) *promoted_initializers = NULL;
|
||||
struct pointer_set_t *inserted = pointer_set_create ();
|
||||
lto_symtab_encoder_iterator lsei;
|
||||
lto_symtab_encoder_t encoder;
|
||||
|
||||
gcc_assert (flag_wpa);
|
||||
|
||||
/* First compute boundaries. */
|
||||
n_sets = VEC_length (ltrans_partition, ltrans_partitions);
|
||||
for (i = 0; i < n_sets; i++)
|
||||
{
|
||||
ltrans_partition part
|
||||
= VEC_index (ltrans_partition, ltrans_partitions, i);
|
||||
encoder = part->encoder;
|
||||
|
||||
/* If node called or referred to from other partition, it needs to be
|
||||
globalized. */
|
||||
for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
|
||||
lsei_next_in_partition (&lsei))
|
||||
{
|
||||
symtab_node node = lsei_node (lsei);
|
||||
if (node->symbol.externally_visible)
|
||||
continue;
|
||||
if (symtab_function_p (node))
|
||||
{
|
||||
struct cgraph_node *cnode = cgraph (node);
|
||||
if (partition_cgraph_node_p (cnode)
|
||||
&& (referenced_from_other_partition_p (&cnode->symbol.ref_list, encoder)
|
||||
|| reachable_from_other_partition_p (cnode, encoder)))
|
||||
promote_fn (cnode);
|
||||
}
|
||||
else if (symtab_variable_p (node))
|
||||
{
|
||||
vnode = varpool (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 (partition_varpool_node_p (vnode)
|
||||
&& referenced_from_other_partition_p (&vnode->symbol.ref_list,
|
||||
encoder))
|
||||
promote_var (vnode);
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* We export the initializer of a read-only var into each partition
|
||||
referencing the var. Folding might take declarations from the
|
||||
initializer and use them, so everything referenced from the
|
||||
initializer can be accessed from this partition after folding.
|
||||
|
||||
This means that we need to promote all variables and functions
|
||||
referenced from all initializers of read-only vars referenced
|
||||
from this partition that are not in this partition. This needs
|
||||
to be done recursively. */
|
||||
FOR_EACH_VARIABLE (vnode)
|
||||
if (const_value_known_p (vnode->symbol.decl)
|
||||
&& DECL_INITIAL (vnode->symbol.decl)
|
||||
&& !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)vnode)
|
||||
&& referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder)
|
||||
&& !pointer_set_insert (inserted, vnode))
|
||||
VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, vnode);
|
||||
|
||||
while (!VEC_empty (varpool_node_ptr, promoted_initializers))
|
||||
{
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
||||
vnode = VEC_pop (varpool_node_ptr, promoted_initializers);
|
||||
for (i = 0;
|
||||
ipa_ref_list_reference_iterate (&vnode->symbol.ref_list, i, ref);
|
||||
i++)
|
||||
{
|
||||
if (symtab_function_p (ref->referred))
|
||||
{
|
||||
struct cgraph_node *n = ipa_ref_node (ref);
|
||||
gcc_assert (!n->global.inlined_to);
|
||||
if (!n->symbol.externally_visible
|
||||
&& !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)n))
|
||||
promote_fn (n);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct varpool_node *v = ipa_ref_varpool_node (ref);
|
||||
if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)v))
|
||||
continue;
|
||||
|
||||
/* Constant pool references use internal labels and thus
|
||||
cannot be made global. It is sensible to keep those
|
||||
ltrans local to allow better optimization.
|
||||
Similarly we ship external vars initializers into
|
||||
every ltrans unit possibly referring to it. */
|
||||
if (DECL_IN_CONSTANT_POOL (v->symbol.decl)
|
||||
|| DECL_EXTERNAL (v->symbol.decl))
|
||||
{
|
||||
if (!pointer_set_insert (inserted, vnode))
|
||||
VEC_safe_push (varpool_node_ptr, heap,
|
||||
promoted_initializers, v);
|
||||
}
|
||||
else if (!v->symbol.externally_visible && v->analyzed)
|
||||
{
|
||||
if (promote_var (v)
|
||||
&& DECL_INITIAL (v->symbol.decl)
|
||||
&& const_value_known_p (v->symbol.decl)
|
||||
&& !pointer_set_insert (inserted, vnode))
|
||||
VEC_safe_push (varpool_node_ptr, heap,
|
||||
promoted_initializers, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
part->encoder = compute_ltrans_boundary (part->encoder);
|
||||
}
|
||||
|
||||
/* Look at boundaries and promote symbols as needed. */
|
||||
for (i = 0; i < n_sets; i++)
|
||||
{
|
||||
lto_symtab_encoder_iterator lsei;
|
||||
lto_symtab_encoder_t encoder;
|
||||
ltrans_partition part
|
||||
= VEC_index (ltrans_partition, ltrans_partitions, i);
|
||||
|
||||
encoder = part->encoder;
|
||||
for (lsei = lsei_start (encoder); !lsei_end_p (lsei);
|
||||
lsei_next (&lsei))
|
||||
{
|
||||
symtab_node node = lsei_node (lsei);
|
||||
|
||||
/* No need to promote if symbol already is externally visible ... */
|
||||
if (node->symbol.externally_visible
|
||||
/* ... or if it is part of current partition ... */
|
||||
|| 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. */
|
||||
|| !partition_symbol_p (node))
|
||||
continue;
|
||||
|
||||
promote_symbol (node);
|
||||
}
|
||||
}
|
||||
pointer_set_destroy (inserted);
|
||||
}
|
||||
|
@ -1514,7 +1514,6 @@ lto_wpa_write_files (void)
|
||||
|
||||
lto_set_current_out_file (NULL);
|
||||
lto_obj_file_close (file);
|
||||
lto_symtab_encoder_delete (part->encoder);
|
||||
part->encoder = NULL;
|
||||
|
||||
len = strlen (temp_filename);
|
||||
|
@ -2264,7 +2264,7 @@ static void
|
||||
ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
|
||||
{
|
||||
struct lto_out_decl_state *state = lto_new_out_decl_state ();
|
||||
compute_ltrans_boundary (state, encoder);
|
||||
state->symtab_node_encoder = encoder;
|
||||
|
||||
lto_push_out_decl_state (state);
|
||||
|
||||
@ -2324,7 +2324,7 @@ ipa_write_summaries (void)
|
||||
if ((!vnode->alias || vnode->alias_of))
|
||||
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
|
||||
|
||||
ipa_write_summaries_1 (encoder);
|
||||
ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
|
||||
|
||||
free (order);
|
||||
}
|
||||
@ -2376,7 +2376,7 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
|
||||
{
|
||||
struct lto_out_decl_state *state = lto_new_out_decl_state ();
|
||||
lto_symtab_encoder_iterator lsei;
|
||||
compute_ltrans_boundary (state, encoder);
|
||||
state->symtab_node_encoder = encoder;
|
||||
|
||||
lto_push_out_decl_state (state);
|
||||
for (lsei = lsei_start_function_in_partition (encoder);
|
||||
|
Loading…
Reference in New Issue
Block a user