/* LTO partitioning logic routines.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "stringpool.h"
#include "cgraph.h"
#include "lto-streamer.h"
-#include "params.h"
#include "symbol-summary.h"
#include "tree-vrp.h"
#include "ipa-prop.h"
if (symbol_partitioned_p (node))
{
node->in_other_partition = 1;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Symbol node %s now used in multiple partitions\n",
node->name ());
}
{
struct cgraph_edge *e;
if (!node->alias && c == SYMBOL_PARTITION)
- part->insns += ipa_fn_summaries->get (cnode)->size;
+ part->insns += ipa_size_summaries->get (cnode)->size;
/* Add all inline clones and callees that are duplicated. */
for (e = cnode->callees; e; e = e->next_callee)
/* Add all thunks associated with the function. */
for (e = cnode->callers; e; e = e->next_caller)
- if (e->caller->thunk.thunk_p && !e->caller->global.inlined_to)
+ if (e->caller->thunk.thunk_p && !e->caller->inlined_to)
add_symbol_to_partition_1 (part, e->caller);
}
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
{
cnode = cnode->function_symbol ();
- if (cnode->global.inlined_to)
- cnode = cnode->global.inlined_to;
+ if (cnode->inlined_to)
+ cnode = cnode->inlined_to;
return cnode;
}
else if (varpool_node *vnode = dyn_cast <varpool_node *> (node))
{
symtab_node *node1;
- /* Verify that we do not try to duplicate something that can not be. */
+ /* Verify that we do not try to duplicate something that cannot be. */
gcc_checking_assert (node->get_partitioning_class () == SYMBOL_DUPLICATE
|| !symbol_partitioned_p (node));
while ((node1 = contained_in_symbol (node)) != node)
node = node1;
- /* If we have duplicated symbol contained in something we can not duplicate,
+ /* If we have duplicated symbol contained in something we cannot duplicate,
we are very badly screwed. The other way is possible, so we do not
assert this in add_symbol_to_partition_1.
if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node))
&& node->get_partitioning_class () == SYMBOL_PARTITION)
- partition->insns -= ipa_fn_summaries->get (cnode)->size;
+ partition->insns -= ipa_size_summaries->get (cnode)->size;
lto_symtab_encoder_delete_node (partition->encoder, node);
node->aux = (void *)((size_t)node->aux - 1);
}
new_partition ("empty");
}
-/* Helper function for qsort; sort nodes by order. noreorder functions must have
- been removed earlier. */
-static int
-node_cmp (const void *pa, const void *pb)
-{
- const struct cgraph_node *a = *(const struct cgraph_node * const *) pa;
- const struct cgraph_node *b = *(const struct cgraph_node * const *) pb;
-
- /* Profile reorder flag enables function reordering based on first execution
- of a function. All functions with profile are placed in ascending
- order at the beginning. */
-
- if (flag_profile_reorder_functions)
- {
- /* Functions with time profile are sorted in ascending order. */
- if (a->tp_first_run && b->tp_first_run)
- return a->tp_first_run != b->tp_first_run
- ? a->tp_first_run - b->tp_first_run
- : a->order - b->order;
-
- /* Functions with time profile are sorted before the functions
- that do not have the profile. */
- if (a->tp_first_run || b->tp_first_run)
- return b->tp_first_run - a->tp_first_run;
- }
-
- return b->order - a->order;
-}
-
/* Helper function for qsort; sort nodes by order. */
static int
-varpool_node_cmp (const void *pa, const void *pb)
+node_cmp (const void *pa, const void *pb)
{
const symtab_node *a = *static_cast<const symtab_node * const *> (pa);
const symtab_node *b = *static_cast<const symtab_node * const *> (pb);
unsigned i;
symtab_node *node;
- next_nodes.qsort (varpool_node_cmp);
+ next_nodes.qsort (node_cmp);
FOR_EACH_VEC_ELT (next_nodes, i, node)
if (!symbol_partitioned_p (node))
add_symbol_to_partition (partition, node);
void
lto_balanced_map (int n_lto_partitions, int max_partition_size)
{
- int n_nodes = 0;
int n_varpool_nodes = 0, varpool_pos = 0, best_varpool_pos = 0;
- struct cgraph_node **order = XNEWVEC (cgraph_node *, symtab->cgraph_max_uid);
+ auto_vec <cgraph_node *> order (symtab->cgraph_count);
auto_vec<cgraph_node *> noreorder;
auto_vec<varpool_node *> varpool_order;
- int i;
struct cgraph_node *node;
int64_t original_total_size, total_size = 0;
int64_t partition_size;
int last_visited_node = 0;
varpool_node *vnode;
int64_t cost = 0, internal = 0;
- int best_n_nodes = 0, best_i = 0;
+ unsigned int best_n_nodes = 0, best_i = 0;
int64_t best_cost = -1, best_internal = 0, best_size = 0;
int npartitions;
int current_order = -1;
FOR_EACH_VARIABLE (vnode)
gcc_assert (!vnode->aux);
-
+
FOR_EACH_DEFINED_FUNCTION (node)
if (node->get_partitioning_class () == SYMBOL_PARTITION)
{
if (node->no_reorder)
noreorder.safe_push (node);
else
- order[n_nodes++] = node;
+ order.safe_push (node);
if (!node->alias)
- total_size += ipa_fn_summaries->get (node)->size;
+ total_size += ipa_size_summaries->get (node)->size;
}
original_total_size = total_size;
unit tends to import a lot of global trees defined there. We should
get better about minimizing the function bounday, but until that
things works smoother if we order in source order. */
- qsort (order, n_nodes, sizeof (struct cgraph_node *), node_cmp);
+ order.qsort (tp_first_run_node_cmp);
noreorder.qsort (node_cmp);
- if (symtab->dump_file)
+ if (dump_file)
{
- for(i = 0; i < n_nodes; i++)
- fprintf (symtab->dump_file, "Balanced map symbol order:%s:%u\n",
+ for (unsigned i = 0; i < order.length (); i++)
+ fprintf (dump_file, "Balanced map symbol order:%s:%u\n",
order[i]->name (), order[i]->tp_first_run);
- for(i = 0; i < (int)noreorder.length(); i++)
- fprintf (symtab->dump_file, "Balanced map symbol no_reorder:%s:%u\n",
+ for (unsigned i = 0; i < noreorder.length (); i++)
+ fprintf (dump_file, "Balanced map symbol no_reorder:%s:%u\n",
noreorder[i]->name (), noreorder[i]->tp_first_run);
}
&& vnode->no_reorder)
varpool_order.safe_push (vnode);
n_varpool_nodes = varpool_order.length ();
- varpool_order.qsort (varpool_node_cmp);
+ varpool_order.qsort (node_cmp);
/* Compute partition size and create the first partition. */
- if (PARAM_VALUE (MIN_PARTITION_SIZE) > max_partition_size)
+ if (param_min_partition_size > max_partition_size)
fatal_error (input_location, "min partition size cannot be greater "
"than max partition size");
partition_size = total_size / n_lto_partitions;
- if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
- partition_size = PARAM_VALUE (MIN_PARTITION_SIZE);
+ if (partition_size < param_min_partition_size)
+ partition_size = param_min_partition_size;
npartitions = 1;
partition = new_partition ("");
- if (symtab->dump_file)
- fprintf (symtab->dump_file, "Total unit size: %" PRId64 ", partition size: %" PRId64 "\n",
+ if (dump_file)
+ fprintf (dump_file, "Total unit size: %" PRId64 ", partition size: %" PRId64 "\n",
total_size, partition_size);
auto_vec<symtab_node *> next_nodes;
- for (i = 0; i < n_nodes; i++)
+ for (unsigned i = 0; i < order.length (); i++)
{
if (symbol_partitioned_p (order[i]))
continue;
best_n_nodes = lto_symtab_encoder_size (partition->encoder);
best_varpool_pos = varpool_pos;
}
- if (symtab->dump_file)
- fprintf (symtab->dump_file, "Step %i: added %s/%i, size %i, "
+ if (dump_file)
+ fprintf (dump_file, "Step %i: added %s/%i, size %i, "
"cost %" PRId64 "/%" PRId64 " "
"best %" PRId64 "/%" PRId64", step %i\n", i,
order[i]->name (), order[i]->order,
{
if (best_i != i)
{
- if (symtab->dump_file)
- fprintf (symtab->dump_file, "Unwinding %i insertions to step %i\n",
+ if (dump_file)
+ fprintf (dump_file, "Unwinding %i insertions to step %i\n",
i - best_i, best_i);
undo_partition (partition, best_n_nodes);
varpool_pos = best_varpool_pos;
}
gcc_assert (best_size == partition->insns);
i = best_i;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Partition insns: %i (want %" PRId64 ")\n",
partition->insns, partition_size);
/* When we are finished, avoid creating empty partition. */
- while (i < n_nodes - 1 && symbol_partitioned_p (order[i + 1]))
+ while (i < order.length () - 1 && symbol_partitioned_p (order[i + 1]))
i++;
- if (i == n_nodes - 1)
+ if (i == order.length () - 1)
break;
total_size -= partition->insns;
partition = new_partition ("");
last_visited_node = 0;
cost = 0;
- if (symtab->dump_file)
- fprintf (symtab->dump_file, "New partition\n");
+ if (dump_file)
+ fprintf (dump_file, "New partition\n");
best_n_nodes = 0;
best_cost = -1;
/* Watch for overflow. */
partition_size = INT_MAX / 16;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Total size: %" PRId64 " partition_size: %" PRId64 "\n",
total_size, partition_size);
- if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
- partition_size = PARAM_VALUE (MIN_PARTITION_SIZE);
+ if (partition_size < param_min_partition_size)
+ partition_size = param_min_partition_size;
npartitions ++;
}
}
gcc_assert (next_nodes.length () || npartitions != 1 || !best_cost || best_cost == -1);
add_sorted_nodes (next_nodes, partition);
- free (order);
-
- if (symtab->dump_file)
+ if (dump_file)
{
- fprintf (symtab->dump_file, "\nPartition sizes:\n");
+ fprintf (dump_file, "\nPartition sizes:\n");
unsigned partitions = ltrans_partitions.length ();
for (unsigned i = 0; i < partitions ; i++)
{
ltrans_partition p = ltrans_partitions[i];
- fprintf (symtab->dump_file, "partition %d contains %d (%2.2f%%)"
+ fprintf (dump_file, "partition %d contains %d (%2.2f%%)"
" symbols and %d (%2.2f%%) insns\n", i, p->symbols,
- 100.0 * p->symbols / n_nodes, p->insns,
+ 100.0 * p->symbols / order.length (), p->insns,
100.0 * p->insns / original_total_size);
}
- fprintf (symtab->dump_file, "\n");
+ fprintf (dump_file, "\n");
}
}
if (node->lto_file_data
&& lto_get_decl_name_mapping (node->lto_file_data, name) != name)
{
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Not privatizing symbol name: %s. It privatized already.\n",
name);
return true;
that are not really clones. */
if (node->unique_name)
{
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Not privatizing symbol name: %s. Has unique name.\n",
name);
return true;
}
}
+/* Maps symbol names to unique lto clone counters. */
+static hash_map<const char *, unsigned> *lto_clone_numbers;
+
/* Helper for privatize_symbol_name. Mangle NODE symbol name
represented by DECL. */
return false;
name = maybe_rewrite_identifier (name);
+ unsigned &clone_number = lto_clone_numbers->get_or_insert (name);
symtab->change_decl_assembler_name (decl,
- clone_function_name_1 (name,
- "lto_priv"));
+ clone_function_name (
+ name, "lto_priv", clone_number));
+ clone_number++;
if (node->lto_file_data)
lto_record_renamed_decl (node->lto_file_data, name,
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (decl)));
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Privatizing symbol name: %s -> %s\n",
name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
TREE_PUBLIC (node->decl) = 1;
DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
DECL_VISIBILITY_SPECIFIED (node->decl) = true;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Promoting as hidden: %s (%s)\n", node->name (),
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
TREE_PUBLIC (alias->decl) = 1;
DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN;
DECL_VISIBILITY_SPECIFIED (alias->decl) = true;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Promoting alias as hidden: %s\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
}
return;
/* Now walk symbols sharing the same name and see if there are any conflicts.
- (all types of symbols counts here, since we can not have static of the
+ (all types of symbols counts here, since we cannot have static of the
same name as external or public symbol.) */
for (s = symtab_node::get_for_asmname (name);
s; s = s->next_sharing_asm_name)
if (!s)
return;
- if (symtab->dump_file)
- fprintf (symtab->dump_file,
+ if (dump_file)
+ fprintf (dump_file,
"Renaming statics with asm name: %s\n", node->name ());
/* Assign every symbol in the set that shares the same ASM name an unique
part->encoder = compute_ltrans_boundary (part->encoder);
}
+ lto_clone_numbers = new hash_map<const char *, unsigned>;
+
/* Look at boundaries and promote symbols as needed. */
for (i = 0; i < n_sets; i++)
{
promote_symbol (node);
}
}
+ delete lto_clone_numbers;
}
/* Rename statics in the whole unit in the case that
lto_promote_statics_nonwpa (void)
{
symtab_node *node;
+
+ lto_clone_numbers = new hash_map<const char *, unsigned>;
FOR_EACH_SYMBOL (node)
{
rename_statics (NULL, node);
validize_symbol_for_target (node);
}
+ delete lto_clone_numbers;
}