+2012-09-08 Jan Hubicka <jh@suse.cz>
+
+ Replace cgraph_node_set and varpool_node_set by symtab_node_encoder
+ in partitioning.
+ * tree-pass.h (cgraph_node_set_def, varpool_node_set_def): Remove
+ forward declaration.
+ (lto_symtab_encoder_d): Forward declare.
+ (ipa_write_optimization_summaries): Update.
+ * lto-cgraph.c (lto_symtab_encoder_new): Do not initialize
+ body, initializer and in_partition.
+ (lto_symtab_encoder_delete): Update.
+ (lto_symtab_encoder_encode): Update.
+ (lto_symtab_encoder_lookup): Move inline.
+ (lto_symtab_encoder_delete_node): New function.
+ (lto_symtab_encoder_encode_body_p, lto_set_symtab_encoder_encode_body,
+ lto_symtab_encoder_encode_initializer_p,
+ lto_set_symtab_encoder_encode_initializer, lto_symtab_encoder_in_partition_p,
+ lto_symtab_encoder_in_partition_p): Update.
+ (compute_ltrans_boundary): Take encoder as an input.
+ * passes.c (ipa_write_summaries_1): Update.
+ (ipa_write_summaries_1): Update.
+ (ipa_write_summaries): Update.
+ (ipa_write_optimization_summaries): Update.
+ * lto-streamer.c (print_lto_report): Report number of cgraph nodes.
+ * lto-streamer.h (lto_stats_d): Replace num_output_cgraph_nodes by
+ num_output_symtab_nodes.
+ (lto_encoder_entry): New structure.
+ (struct lto_symtab_encoder_d): Reorg.
+ (lto_symtab_encoder_delete_node): Declare.
+ (lto_symtab_encoder_lookup): Bring inline.
+ (compute_ltrans_boundary): Update.
+ (lto_symtab_encoder_size): Update.
+ (lsei_node, lsei_cgraph_node, lsei_varpool_node): Update.
+ (lto_symtab_encoder_deref): Update.
+
2012-09-08 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* config/pa/pa.c (hppa_rtx_costs): Update costs for large integer modes.
lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d);
encoder->map = pointer_map_create ();
encoder->nodes = NULL;
- encoder->body = pointer_set_create ();
- encoder->initializer = pointer_set_create ();
- encoder->in_partition = pointer_set_create ();
return encoder;
}
void
lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
{
- VEC_free (symtab_node, heap, encoder->nodes);
+ VEC_free (lto_encoder_entry, heap, encoder->nodes);
pointer_map_destroy (encoder->map);
- pointer_set_destroy (encoder->body);
- pointer_set_destroy (encoder->initializer);
- pointer_set_destroy (encoder->in_partition);
free (encoder);
}
void **slot;
slot = pointer_map_contains (encoder->map, node);
- if (!slot)
+ if (!slot || !*slot)
{
- ref = VEC_length (symtab_node, encoder->nodes);
- slot = pointer_map_insert (encoder->map, node);
- *slot = (void *) (intptr_t) ref;
- VEC_safe_push (symtab_node, heap, encoder->nodes, node);
+ lto_encoder_entry entry = {node, false, false, false};
+ ref = VEC_length (lto_encoder_entry, encoder->nodes);
+ if (!slot)
+ slot = pointer_map_insert (encoder->map, node);
+ *slot = (void *) (intptr_t) (ref + 1);
+ VEC_safe_push (lto_encoder_entry, heap, encoder->nodes, &entry);
}
else
- ref = (int) (intptr_t) *slot;
+ ref = (size_t) *slot - 1;
return ref;
}
+/* Remove NODE from encoder. */
-/* Look up NODE in encoder. Return NODE's reference if it has been encoded
- or LCC_NOT_FOUND if it is not there. */
-
-int
-lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder,
- symtab_node node)
+bool
+lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder,
+ symtab_node node)
{
- void **slot = pointer_map_contains (encoder->map, node);
- return (slot ? (int) (intptr_t) *slot : LCC_NOT_FOUND);
+ void **slot, **last_slot;
+ int index;
+ lto_encoder_entry last_node;
+
+ slot = pointer_map_contains (encoder->map, node);
+ if (slot == NULL || !*slot)
+ return false;
+
+ index = (size_t) *slot - 1;
+ gcc_checking_assert (VEC_index (lto_encoder_entry,
+ encoder->nodes, index).node
+ == node);
+
+ /* Remove from vector. We do this by swapping node with the last element
+ of the vector. */
+ last_node = VEC_pop (lto_encoder_entry, encoder->nodes);
+ if (last_node.node != node)
+ {
+ last_slot = pointer_map_contains (encoder->map, last_node.node);
+ gcc_checking_assert (last_slot && *last_slot);
+ *last_slot = (void *)(size_t) (index + 1);
+
+ /* Move the last element to the original spot of NODE. */
+ VEC_replace (lto_encoder_entry, encoder->nodes, index,
+ last_node);
+ }
+
+ /* Remove element from hash table. */
+ *slot = NULL;
+ return true;
}
lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- return pointer_set_contains (encoder->body, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).body;
}
/* Return TRUE if we should encode body of NODE (if any). */
lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
struct cgraph_node *node)
{
- pointer_set_insert (encoder->body, node);
+ int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ gcc_checking_assert (VEC_index (lto_encoder_entry, encoder->nodes,
+ index).node == (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).body = true;
}
/* Return TRUE if we should encode initializer of NODE (if any). */
lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder,
struct varpool_node *node)
{
- return pointer_set_contains (encoder->initializer, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ if (index == LCC_NOT_FOUND)
+ return false;
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).initializer;
}
/* Return TRUE if we should encode initializer of NODE (if any). */
lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
struct varpool_node *node)
{
- pointer_set_insert (encoder->initializer, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).initializer = true;
}
/* Return TRUE if we should encode initializer of NODE (if any). */
lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
symtab_node node)
{
- return pointer_set_contains (encoder->in_partition, node);
+ int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+ if (index == LCC_NOT_FOUND)
+ return false;
+ return VEC_index (lto_encoder_entry, encoder->nodes, index).in_partition;
}
/* Return TRUE if we should encode body of NODE (if any). */
lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder,
symtab_node node)
{
- lto_symtab_encoder_encode (encoder, (symtab_node)node);
- pointer_set_insert (encoder->in_partition, node);
+ int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+ VEC_index (lto_encoder_entry, encoder->nodes, index).in_partition = true;
}
/* Output the cgraph EDGE to OB using ENCODER. */
and insert them to encoders. */
void
compute_ltrans_boundary (struct lto_out_decl_state *state,
- cgraph_node_set set, varpool_node_set vset)
+ lto_symtab_encoder_t in_encoder)
{
struct cgraph_node *node;
- cgraph_node_set_iterator csi;
- varpool_node_set_iterator vsi;
struct cgraph_edge *edge;
int i;
lto_symtab_encoder_t encoder;
+ lto_symtab_encoder_iterator lsei;
encoder = state->symtab_node_encoder = lto_symtab_encoder_new ();
- /* Go over all the nodes in SET and assign references. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ /* Go over all entries in the IN_ENCODER and duplicate them to
+ ENCODER. At the same time insert masters of clones so
+ every master appears before clone. */
+ for (lsei = lsei_start_function_in_partition (in_encoder);
+ !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{
- node = csi_node (csi);
+ node = lsei_cgraph_node (lsei);
add_node_to (encoder, node, true);
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
add_references (encoder, &node->symbol.ref_list);
}
- for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
+ for (lsei = lsei_start_variable_in_partition (in_encoder);
+ !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
{
- struct varpool_node *vnode = vsi_node (vsi);
+ struct varpool_node *vnode = lsei_varpool_node (lsei);
gcc_assert (!vnode->alias || vnode->alias_of);
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
/* Go over all the nodes again to include callees that are not in
SET. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_function_in_partition (encoder);
+ !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{
- node = csi_node (csi);
+ node = lsei_cgraph_node (lsei);
for (edge = node->callees; edge; edge = edge->next_callee)
{
struct cgraph_node *callee = edge->callee;
- if (!cgraph_node_in_set_p (callee, set))
+ if (!lto_symtab_encoder_in_partition_p (encoder, (symtab_node)callee))
{
/* We should have moved all the inlines. */
gcc_assert (!callee->global.inlined_to);
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
lto_stats.num_output_files);
- fprintf (stderr, "[%s] # of output cgraph nodes: "
+ fprintf (stderr, "[%s] # of output symtab nodes: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
- lto_stats.num_output_cgraph_nodes);
+ lto_stats.num_output_symtab_nodes);
fprintf (stderr, "[%s] # callgraph partitions: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
struct lto_stats_d
{
unsigned HOST_WIDE_INT num_input_cgraph_nodes;
- unsigned HOST_WIDE_INT num_output_cgraph_nodes;
+ unsigned HOST_WIDE_INT num_output_symtab_nodes;
unsigned HOST_WIDE_INT num_input_files;
unsigned HOST_WIDE_INT num_output_files;
unsigned HOST_WIDE_INT num_cgraph_partitions;
unsigned HOST_WIDE_INT num_uncompressed_il_bytes;
};
+/* Entry of LTO symtab encoder. */
+typedef struct
+{
+ symtab_node node;
+ /* Is the node in this partition (i.e. ltrans of this partition will
+ be responsible for outputting it)? */
+ unsigned int in_partition:1;
+ /* Do we encode body in this partition? */
+ unsigned int body:1;
+ /* Do we encode initializer in this partition?
+ For example the readonly variable initializers are encoded to aid
+ constant folding even if they are not in the partition. */
+ unsigned int initializer:1;
+} lto_encoder_entry;
+
+DEF_VEC_O(lto_encoder_entry);
+DEF_VEC_ALLOC_O(lto_encoder_entry, heap);
+
/* Encoder data structure used to stream callgraph nodes. */
struct lto_symtab_encoder_d
{
- /* Map nodes to reference number. */
- struct pointer_map_t *map;
-
- /* Map reference number to node. */
- VEC(symtab_node,heap) *nodes;
-
- /* Map of nodes where we want to output body. */
- struct pointer_set_t *body;
- /* Map of nodes where we want to output initializer. */
- struct pointer_set_t *initializer;
- /* Map of nodes in this partition. */
- struct pointer_set_t *in_partition;
+ VEC(lto_encoder_entry,gc) *nodes;
+ pointer_map_t *map;
};
typedef struct lto_symtab_encoder_d *lto_symtab_encoder_t;
/* In lto-cgraph.c */
-int lto_symtab_encoder_lookup (lto_symtab_encoder_t, symtab_node);
lto_symtab_encoder_t lto_symtab_encoder_new (void);
int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node);
void lto_symtab_encoder_delete (lto_symtab_encoder_t);
+bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node);
bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t,
struct cgraph_node *);
bool lto_symtab_encoder_in_partition_p (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,
- cgraph_node_set, varpool_node_set);
+ lto_symtab_encoder_t encoder);
/* In lto-symtab.c. */
static inline int
lto_symtab_encoder_size (lto_symtab_encoder_t encoder)
{
- return VEC_length (symtab_node, encoder->nodes);
+ return VEC_length (lto_encoder_entry, encoder->nodes);
+}
+
+/* Value used to represent failure of lto_symtab_encoder_lookup. */
+#define LCC_NOT_FOUND (-1)
+
+/* Look up NODE in encoder. Return NODE's reference if it has been encoded
+ or LCC_NOT_FOUND if it is not there. */
+
+static inline int
+lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder,
+ symtab_node node)
+{
+ void **slot = pointer_map_contains (encoder->map, node);
+ return (slot && *slot ? (size_t) *(slot) - 1 : LCC_NOT_FOUND);
}
/* Return true if iterator LSE points to nothing. */
static inline symtab_node
lsei_node (lto_symtab_encoder_iterator lsei)
{
- return VEC_index (symtab_node, lsei.encoder->nodes, lsei.index);
+ return VEC_index (lto_encoder_entry,
+ lsei.encoder->nodes, lsei.index).node;
}
/* Return the node pointed to by LSI. */
static inline struct cgraph_node *
lsei_cgraph_node (lto_symtab_encoder_iterator lsei)
{
- return cgraph (VEC_index (symtab_node, lsei.encoder->nodes, lsei.index));
+ return cgraph (VEC_index (lto_encoder_entry,
+ lsei.encoder->nodes, lsei.index).node);
}
/* Return the node pointed to by LSI. */
static inline struct varpool_node *
lsei_varpool_node (lto_symtab_encoder_iterator lsei)
{
- return varpool (VEC_index (symtab_node, lsei.encoder->nodes, lsei.index));
+ return varpool (VEC_index (lto_encoder_entry,
+ lsei.encoder->nodes, lsei.index).node);
}
-/* Value used to represent failure of lto_symtab_encoder_lookup. */
-#define LCC_NOT_FOUND (-1)
-
/* Return the cgraph node corresponding to REF using ENCODER. */
static inline symtab_node
if (ref == LCC_NOT_FOUND)
return NULL;
- return VEC_index (symtab_node, encoder->nodes, ref);
+ return VEC_index (lto_encoder_entry, encoder->nodes, ref).node;
}
/* Return an iterator to the first node in LSI. */
2012-08-12 Jan Hubicka <jh@suse.cz>
+ Replace cgraph_node_set and varpool_node_set by symtab_node_encoder
+ in partitioning.
+ * lto-partition.h (ltrans_partition_def): Replace cgraph_set and varpool_set
+ by encoder.
+ * lto-partition.c (new_partition): Update.
+ * lto.c (cmp_partitions_order): Update.
+ (lto_wpa_write_files): Update.
+ (free_ltrans_partitions): Update.
+ (add_references_to_partition): Update.
+ (add_cgraph_node_to_partition_1): Update.
+ (add_cgraph_node_to_partition): Update.
+ (add_varpool_node_to_partition): Update.
+ (undo_partition): Update.
+ (lto_balanced_map): Update.
+ (set_referenced_from_other_partition_p, set_reachable_from_other_partition_p,
+ set_referenced_from_this_partition_p): Update.
+ (lto_promote_cross_file_statics): Update.
+
+2012-08-12 Jan Hubicka <jh@suse.cz>
+
* lto-partition.c (set_referenced_from_other_partition_p,
set_reachable_from_other_partition_p, set_referenced_from_this_partition_p):
New functions.
new_partition (const char *name)
{
ltrans_partition part = XCNEW (struct ltrans_partition_def);
- part->cgraph_set = cgraph_node_set_new ();
- part->varpool_set = varpool_node_set_new ();
+ part->encoder = lto_symtab_encoder_new ();
part->name = name;
part->insns = 0;
VEC_safe_push (ltrans_partition, heap, ltrans_partitions, part);
ltrans_partition part;
for (idx = 0; VEC_iterate (ltrans_partition, ltrans_partitions, idx, part); idx++)
{
- free_cgraph_node_set (part->cgraph_set);
+ /* Symtab encoder is freed after streaming. */
free (part);
}
VEC_free (ltrans_partition, heap, ltrans_partitions);
NULL)->symbol.decl)
|| (ref->use == IPA_REF_ALIAS
&& lookup_attribute
- ("weakref", DECL_ATTRIBUTES (ipa_ref_node (ref)->symbol.decl))))
- && !cgraph_node_in_set_p (ipa_ref_node (ref), part->cgraph_set))
+ ("weakref", DECL_ATTRIBUTES (ref->referred->symbol.decl))))
+ && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
add_cgraph_node_to_partition (part, ipa_ref_node (ref));
else
if (symtab_variable_p (ref->referred)
- && (DECL_COMDAT (ipa_ref_varpool_node (ref)->symbol.decl)
- || DECL_EXTERNAL (ipa_ref_varpool_node (ref)->symbol.decl)
+ && (DECL_COMDAT (ref->referred->symbol.decl)
+ || DECL_EXTERNAL (ref->referred->symbol.decl)
|| (ref->use == IPA_REF_ALIAS
&& lookup_attribute
("weakref",
- DECL_ATTRIBUTES (ipa_ref_varpool_node (ref)->symbol.decl))))
- && !varpool_node_in_set_p (ipa_ref_varpool_node (ref),
- part->varpool_set))
+ DECL_ATTRIBUTES (ref->referred->symbol.decl))))
+ && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
add_varpool_node_to_partition (part, ipa_ref_varpool_node (ref));
}
for (i = 0; ipa_ref_list_referring_iterate (refs, i, ref); i++)
{
if (symtab_function_p (ref->referring)
&& ref->use == IPA_REF_ALIAS
- && !cgraph_node_in_set_p (ipa_ref_referring_node (ref),
- part->cgraph_set)
+ && !lto_symtab_encoder_in_partition_p (part->encoder,
+ ref->referring)
&& !lookup_attribute ("weakref",
DECL_ATTRIBUTES
- (ipa_ref_referring_node (ref)->symbol.decl)))
+ (ref->referring->symbol.decl)))
add_cgraph_node_to_partition (part, ipa_ref_referring_node (ref));
else
if (symtab_variable_p (ref->referring)
&& ref->use == IPA_REF_ALIAS
- && !varpool_node_in_set_p (ipa_ref_referring_varpool_node (ref),
- part->varpool_set)
+ && !lto_symtab_encoder_in_partition_p (part->encoder,
+ ref->referring)
&& !lookup_attribute ("weakref",
DECL_ATTRIBUTES
- (ipa_ref_referring_varpool_node (ref)->symbol.decl)))
+ (ref->referring->symbol.decl)))
add_varpool_node_to_partition (part,
ipa_ref_referring_varpool_node (ref));
}
cgraph_node_name (node), node->uid);
}
node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
- cgraph_node_set_add (part->cgraph_set, node);
+ lto_set_symtab_encoder_in_partition (part->encoder, (symtab_node)node);
return false;
}
add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node)
{
struct cgraph_edge *e;
- cgraph_node_set_iterator csi;
struct cgraph_node *n;
/* If NODE is already there, we have nothing to do. */
- csi = cgraph_node_set_find (part->cgraph_set, node);
- if (!csi_end_p (csi))
+ if (lto_symtab_encoder_in_partition_p (part->encoder, (symtab_node) node))
return;
cgraph_for_node_thunks_and_aliases (node, add_cgraph_node_to_partition_1, part, true);
part->insns += inline_summary (node)->self_size;
- cgraph_node_set_add (part->cgraph_set, node);
+ lto_set_symtab_encoder_in_partition (part->encoder, (symtab_node) node);
for (e = node->callees; e; e = e->next_callee)
if ((!e->inline_failed
- || DECL_COMDAT (cgraph_function_node (e->callee, NULL)->symbol.decl))
- && !cgraph_node_in_set_p (e->callee, part->cgraph_set))
+ || DECL_COMDAT (cgraph_function_node (e->callee, NULL)->symbol.decl)))
add_cgraph_node_to_partition (part, e->callee);
/* The only way to assemble non-weakref alias is to add the aliased object into
static void
add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode)
{
- varpool_node_set_iterator vsi;
struct varpool_node *v;
/* If NODE is already there, we have nothing to do. */
- vsi = varpool_node_set_find (part->varpool_set, vnode);
- if (!vsi_end_p (vsi))
+ if (lto_symtab_encoder_in_partition_p (part->encoder, (symtab_node) vnode))
return;
- varpool_node_set_add (part->varpool_set, vnode);
+ lto_set_symtab_encoder_in_partition (part->encoder, (symtab_node) vnode);
if (vnode->symbol.aux)
{
add_references_to_partition (part, &vnode->symbol.ref_list);
if (vnode->symbol.same_comdat_group
- && !varpool_node_in_set_p (varpool (vnode->symbol.same_comdat_group),
- part->varpool_set))
+ && !lto_symtab_encoder_in_partition_p (part->encoder,
+ vnode->symbol.same_comdat_group))
add_varpool_node_to_partition (part, varpool (vnode->symbol.same_comdat_group));
}
and number of varpool nodes is N_VARPOOL_NODES. */
static void
-undo_partition (ltrans_partition partition, unsigned int n_cgraph_nodes,
- unsigned int n_varpool_nodes)
+undo_partition (ltrans_partition partition, unsigned int n_nodes)
{
- while (VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes) >
- n_cgraph_nodes)
+ while (lto_symtab_encoder_size (partition->encoder) > (int)n_nodes)
{
- struct cgraph_node *node = VEC_index (cgraph_node_ptr,
- partition->cgraph_set->nodes,
- n_cgraph_nodes);
- partition->insns -= inline_summary (node)->self_size;
- cgraph_node_set_remove (partition->cgraph_set, node);
- node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
- }
- while (VEC_length (varpool_node_ptr, partition->varpool_set->nodes) >
- n_varpool_nodes)
- {
- struct varpool_node *node = VEC_index (varpool_node_ptr,
- partition->varpool_set->nodes,
- n_varpool_nodes);
- varpool_node_set_remove (partition->varpool_set, node);
+ symtab_node node = lto_symtab_encoder_deref (partition->encoder,
+ n_nodes);
+ if (symtab_function_p (node))
+ partition->insns -= inline_summary (cgraph (node))->self_size;
+ lto_symtab_encoder_delete_node (partition->encoder, node);
node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
}
}
int total_size = 0, best_total_size = 0;
int partition_size;
ltrans_partition partition;
- unsigned int last_visited_cgraph_node = 0, last_visited_varpool_node = 0;
+ int last_visited_node = 0;
struct varpool_node *vnode;
int cost = 0, internal = 0;
- int best_n_nodes = 0, best_n_varpool_nodes = 0, best_i = 0, best_cost =
+ int best_n_nodes = 0, best_i = 0, best_cost =
INT_MAX, best_internal = 0;
int npartitions;
int current_order = -1;
callgraph or IPA reference edge leaving the partition contributes into
COST. Every edge inside partition was earlier computed as one leaving
it and thus we need to subtract it from COST. */
- while (last_visited_cgraph_node <
- VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes)
- || last_visited_varpool_node < VEC_length (varpool_node_ptr,
- partition->varpool_set->
- nodes))
+ while (last_visited_node < lto_symtab_encoder_size (partition->encoder))
{
struct ipa_ref_list *refs;
int j;
struct ipa_ref *ref;
- bool cgraph_p = false;
+ symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
+ last_visited_node);
- if (last_visited_cgraph_node <
- VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes))
+ if (symtab_function_p (snode))
{
struct cgraph_edge *edge;
- cgraph_p = true;
- node = VEC_index (cgraph_node_ptr, partition->cgraph_set->nodes,
- last_visited_cgraph_node);
+ node = cgraph (snode);
refs = &node->symbol.ref_list;
- last_visited_cgraph_node++;
+ last_visited_node++;
gcc_assert (node->analyzed);
if (edge->callee->analyzed)
{
int edge_cost = edge->frequency;
- cgraph_node_set_iterator csi;
+ int index;
if (!edge_cost)
edge_cost = 1;
gcc_assert (edge_cost > 0);
- csi = cgraph_node_set_find (partition->cgraph_set, edge->callee);
- if (!csi_end_p (csi)
- && csi.index < last_visited_cgraph_node - 1)
- cost -= edge_cost, internal+= edge_cost;
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)edge->callee);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
+ cost -= edge_cost, internal += edge_cost;
else
cost += edge_cost;
}
for (edge = node->callers; edge; edge = edge->next_caller)
{
int edge_cost = edge->frequency;
- cgraph_node_set_iterator csi;
+ int index;
gcc_assert (edge->caller->analyzed);
if (!edge_cost)
edge_cost = 1;
gcc_assert (edge_cost > 0);
- csi = cgraph_node_set_find (partition->cgraph_set, edge->caller);
- if (!csi_end_p (csi)
- && csi.index < last_visited_cgraph_node)
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)edge->caller);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
cost -= edge_cost;
else
cost += edge_cost;
}
else
{
- refs =
- &VEC_index (varpool_node_ptr, partition->varpool_set->nodes,
- last_visited_varpool_node)->symbol.ref_list;
- last_visited_varpool_node++;
+ refs = &snode->symbol.ref_list;
+ last_visited_node++;
}
/* Compute boundary cost of IPA REF edges and at the same time look into
for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
if (symtab_variable_p (ref->referred))
{
- varpool_node_set_iterator vsi;
+ int index;
vnode = ipa_ref_varpool_node (ref);
if (!vnode->finalized)
if (!vnode->symbol.aux && flag_toplevel_reorder
&& partition_varpool_node_p (vnode))
add_varpool_node_to_partition (partition, vnode);
- vsi = varpool_node_set_find (partition->varpool_set, vnode);
- if (!vsi_end_p (vsi)
- && vsi.index < last_visited_varpool_node - !cgraph_p)
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)vnode);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
cost--, internal++;
else
cost++;
}
else
{
- cgraph_node_set_iterator csi;
+ int index;
node = ipa_ref_node (ref);
if (!node->analyzed)
continue;
- csi = cgraph_node_set_find (partition->cgraph_set, node);
- if (!csi_end_p (csi)
- && csi.index < last_visited_cgraph_node - cgraph_p)
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)node);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
cost--, internal++;
else
cost++;
for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
if (symtab_variable_p (ref->referring))
{
- varpool_node_set_iterator vsi;
+ int index;
vnode = ipa_ref_referring_varpool_node (ref);
gcc_assert (vnode->finalized);
if (!vnode->symbol.aux && flag_toplevel_reorder
&& partition_varpool_node_p (vnode))
add_varpool_node_to_partition (partition, vnode);
- vsi = varpool_node_set_find (partition->varpool_set, vnode);
- if (!vsi_end_p (vsi)
- && vsi.index < last_visited_varpool_node)
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)vnode);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
cost--;
else
cost++;
}
else
{
- cgraph_node_set_iterator csi;
+ int index;
node = ipa_ref_referring_node (ref);
gcc_assert (node->analyzed);
- csi = cgraph_node_set_find (partition->cgraph_set, node);
- if (!csi_end_p (csi)
- && csi.index < last_visited_cgraph_node)
+ index = lto_symtab_encoder_lookup (partition->encoder,
+ (symtab_node)node);
+ if (index != LCC_NOT_FOUND
+ && index < last_visited_node - 1)
cost--;
else
cost++;
best_cost = cost;
best_internal = internal;
best_i = i;
- best_n_nodes = VEC_length (cgraph_node_ptr,
- partition->cgraph_set->nodes);
- best_n_varpool_nodes = VEC_length (varpool_node_ptr,
- partition->varpool_set->nodes);
+ best_n_nodes = lto_symtab_encoder_size (partition->encoder);
best_total_size = total_size;
}
if (cgraph_dump_file)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Unwinding %i insertions to step %i\n",
i - best_i, best_i);
- undo_partition (partition, best_n_nodes, best_n_varpool_nodes);
+ undo_partition (partition, best_n_nodes);
}
i = best_i;
/* When we are finished, avoid creating empty partition. */
if (i == n_nodes - 1)
break;
partition = new_partition ("");
- last_visited_cgraph_node = 0;
- last_visited_varpool_node = 0;
+ last_visited_node = 0;
total_size = best_total_size;
cost = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "New partition\n");
best_n_nodes = 0;
- best_n_varpool_nodes = 0;
best_cost = INT_MAX;
/* Since the size of partitions is just approximate, update the size after
return true;
}
-/* Return if LIST contain references from other partitions.
- TODO: remove this once lto partitioning is using encoders. */
-
-static bool
-set_referenced_from_other_partition_p (struct ipa_ref_list *list, cgraph_node_set set,
- varpool_node_set vset)
-{
- int i;
- struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
- {
- if (symtab_function_p (ref->referring))
- {
- if (ipa_ref_referring_node (ref)->symbol.in_other_partition
- || !cgraph_node_in_set_p (ipa_ref_referring_node (ref), set))
- return true;
- }
- else
- {
- if (ipa_ref_referring_varpool_node (ref)->symbol.in_other_partition
- || !varpool_node_in_set_p (ipa_ref_referring_varpool_node (ref),
- vset))
- return true;
- }
- }
- return false;
-}
-
-/* Return true when node is reachable from other partition.
- TODO: remove this once lto partitioning is using encoders. */
-
-static bool
-set_reachable_from_other_partition_p (struct cgraph_node *node, cgraph_node_set set)
-{
- struct cgraph_edge *e;
- if (!node->analyzed)
- return false;
- if (node->global.inlined_to)
- return false;
- for (e = node->callers; e; e = e->next_caller)
- if (e->caller->symbol.in_other_partition
- || !cgraph_node_in_set_p (e->caller, set))
- return true;
- return false;
-}
-
-
-/* Return if LIST contain references from other partitions.
- TODO: remove this once lto partitioning is using encoders. */
-
-static bool
-set_referenced_from_this_partition_p (struct ipa_ref_list *list, cgraph_node_set set,
- varpool_node_set vset)
-{
- int i;
- struct ipa_ref *ref;
- for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
- {
- if (symtab_function_p (ref->referring))
- {
- if (cgraph_node_in_set_p (ipa_ref_referring_node (ref), set))
- return true;
- }
- else
- {
- if (varpool_node_in_set_p (ipa_ref_referring_varpool_node (ref),
- vset))
- return true;
- }
- }
- return false;
-}
-
/* 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. */
{
struct varpool_node *vnode;
unsigned i, n_sets;
- cgraph_node_set set;
- varpool_node_set vset;
- cgraph_node_set_iterator csi;
- varpool_node_set_iterator vsi;
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);
{
ltrans_partition part
= VEC_index (ltrans_partition, ltrans_partitions, i);
- set = part->cgraph_set;
- vset = part->varpool_set;
+ encoder = part->encoder;
/* If node called or referred to from other partition, it needs to be
globalized. */
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
+ lsei_next_in_partition (&lsei))
{
- struct cgraph_node *node = csi_node (csi);
+ symtab_node node = lsei_node (lsei);
if (node->symbol.externally_visible)
continue;
- if (node->global.inlined_to)
- continue;
- if ((!DECL_EXTERNAL (node->symbol.decl)
- && !DECL_COMDAT (node->symbol.decl))
- && (set_referenced_from_other_partition_p (&node->symbol.ref_list, set, vset)
- || set_reachable_from_other_partition_p (node, set)))
- promote_fn (node);
- }
- for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi))
- {
- vnode = vsi_node (vsi);
- /* 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->symbol.decl)
- && !DECL_EXTERNAL (vnode->symbol.decl)
- && !DECL_COMDAT (vnode->symbol.decl)
- && !vnode->symbol.externally_visible && vnode->analyzed
- && set_referenced_from_other_partition_p (&vnode->symbol.ref_list,
- set, vset))
- promote_var (vnode);
+ 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
FOR_EACH_VARIABLE (vnode)
if (const_value_known_p (vnode->symbol.decl)
&& DECL_INITIAL (vnode->symbol.decl)
- && !varpool_node_in_set_p (vnode, vset)
- && set_referenced_from_this_partition_p (&vnode->symbol.ref_list, set, vset)
+ && !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);
struct cgraph_node *n = ipa_ref_node (ref);
gcc_assert (!n->global.inlined_to);
if (!n->symbol.externally_visible
- && !cgraph_node_in_set_p (n, set))
+ && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)n))
promote_fn (n);
}
else
{
struct varpool_node *v = ipa_ref_varpool_node (ref);
- if (varpool_node_in_set_p (v, vset))
+ if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)v))
continue;
/* Constant pool references use internal labels and thus
struct ltrans_partition_def
{
- cgraph_node_set cgraph_set;
- varpool_node_set varpool_set;
+ lto_symtab_encoder_t encoder;
const char * name;
int insns;
};
= *(struct ltrans_partition_def *const *)b;
int ordera = -1, orderb = -1;
- if (VEC_length (cgraph_node_ptr, pa->cgraph_set->nodes))
- ordera = VEC_index (cgraph_node_ptr, pa->cgraph_set->nodes, 0)->symbol.order;
- else if (VEC_length (varpool_node_ptr, pa->varpool_set->nodes))
- ordera = VEC_index (varpool_node_ptr, pa->varpool_set->nodes, 0)->symbol.order;
- if (VEC_length (cgraph_node_ptr, pb->cgraph_set->nodes))
- orderb = VEC_index (cgraph_node_ptr, pb->cgraph_set->nodes, 0)->symbol.order;
- else if (VEC_length (varpool_node_ptr, pb->varpool_set->nodes))
- orderb = VEC_index (varpool_node_ptr, pb->varpool_set->nodes, 0)->symbol.order;
+ if (lto_symtab_encoder_size (pa->encoder))
+ ordera = lto_symtab_encoder_deref (pa->encoder, 0)->symbol.order;
+ if (lto_symtab_encoder_size (pb->encoder))
+ orderb = lto_symtab_encoder_deref (pb->encoder, 0)->symbol.order;
return orderb - ordera;
}
{
unsigned i, n_sets;
lto_file *file;
- cgraph_node_set set;
- varpool_node_set vset;
ltrans_partition part;
FILE *ltrans_output_list_stream;
char *temp_filename;
timevar_push (TV_WHOPR_WPA);
FOR_EACH_VEC_ELT (ltrans_partition, ltrans_partitions, i, part)
- lto_stats.num_output_cgraph_nodes += VEC_length (cgraph_node_ptr,
- part->cgraph_set->nodes);
+ lto_stats.num_output_symtab_nodes += lto_symtab_encoder_size (part->encoder);
/* Find out statics that need to be promoted
to globals with hidden visibility because they are accessed from multiple
size_t len;
ltrans_partition part = VEC_index (ltrans_partition, ltrans_partitions, i);
- set = part->cgraph_set;
- vset = part->varpool_set;
-
/* Write all the nodes in SET. */
sprintf (temp_filename + blen, "%u.o", i);
file = lto_obj_file_open (temp_filename, true);
fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns);
if (cgraph_dump_file)
{
+ lto_symtab_encoder_iterator lsei;
+
fprintf (cgraph_dump_file, "Writing partition %s to file %s, %i insns\n",
part->name, temp_filename, part->insns);
- fprintf (cgraph_dump_file, "cgraph nodes:");
- dump_cgraph_node_set (cgraph_dump_file, set);
- fprintf (cgraph_dump_file, "varpool nodes:");
- dump_varpool_node_set (cgraph_dump_file, vset);
+ for (lsei = lsei_start_in_partition (part->encoder); !lsei_end_p (lsei);
+ lsei_next_in_partition (&lsei))
+ {
+ symtab_node node = lsei_node (lsei);
+ fprintf (cgraph_dump_file, "%s ", symtab_node_name (node));
+ }
+ fprintf (cgraph_dump_file, "\n");
}
- gcc_checking_assert (cgraph_node_set_nonempty_p (set)
- || varpool_node_set_nonempty_p (vset) || !i);
+ gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i);
lto_set_current_out_file (file);
- ipa_write_optimization_summaries (set, vset);
+ ipa_write_optimization_summaries (part->encoder);
lto_set_current_out_file (NULL);
lto_obj_file_close (file);
+ lto_symtab_encoder_delete (part->encoder);
+ part->encoder = NULL;
len = strlen (temp_filename);
if (fwrite (temp_filename, 1, len, ltrans_output_list_stream) < len
summaries. SET is the set of nodes to be written. */
static void
-ipa_write_summaries_1 (cgraph_node_set set, varpool_node_set vset)
+ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
{
struct lto_out_decl_state *state = lto_new_out_decl_state ();
- compute_ltrans_boundary (state, set, vset);
+ compute_ltrans_boundary (state, encoder);
lto_push_out_decl_state (state);
void
ipa_write_summaries (void)
{
- cgraph_node_set set;
- varpool_node_set vset;
- struct cgraph_node **order;
- struct varpool_node *vnode;
+ lto_symtab_encoder_t encoder;
int i, order_pos;
+ struct varpool_node *vnode;
+ struct cgraph_node **order;
if (!flag_generate_lto || seen_error ())
return;
- set = cgraph_node_set_new ();
+ encoder = lto_symtab_encoder_new ();
/* Create the callgraph set in the same order used in
cgraph_expand_all_functions. This mostly facilitates debugging,
pop_cfun ();
}
if (node->analyzed)
- cgraph_node_set_add (set, node);
+ lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
}
- vset = varpool_node_set_new ();
FOR_EACH_DEFINED_VARIABLE (vnode)
if ((!vnode->alias || vnode->alias_of))
- varpool_node_set_add (vset, vnode);
+ lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
- ipa_write_summaries_1 (set, vset);
+ ipa_write_summaries_1 (encoder);
free (order);
- free_cgraph_node_set (set);
- free_varpool_node_set (vset);
}
/* Same as execute_pass_list but assume that subpasses of IPA passes
NULL, write out all summaries of all nodes. */
void
-ipa_write_optimization_summaries (cgraph_node_set set, varpool_node_set vset)
+ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
{
struct lto_out_decl_state *state = lto_new_out_decl_state ();
- cgraph_node_set_iterator csi;
- compute_ltrans_boundary (state, set, vset);
+ lto_symtab_encoder_iterator lsei;
+ compute_ltrans_boundary (state, encoder);
lto_push_out_decl_state (state);
- for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ for (lsei = lsei_start_function_in_partition (encoder);
+ !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{
- struct cgraph_node *node = csi_node (csi);
+ struct cgraph_node *node = lsei_cgraph_node (lsei);
/* When streaming out references to statements as part of some IPA
pass summary, the statements need to have uids assigned.
struct varpool_node;
struct cgraph_node;
-struct cgraph_node_set_def;
-struct varpool_node_set_def;
+struct lto_symtab_encoder_d;
/* Description of IPA pass with generate summary, write, execute, read and
transform stages. */
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 *,
- struct varpool_node_set_def *);
+extern void ipa_write_optimization_summaries (struct lto_symtab_encoder_d *);
extern void ipa_read_summaries (void);
extern void ipa_read_optimization_summaries (void);
extern void register_one_dump_file (struct opt_pass *);