cgraph.c (dump_cgraph_node): Dump same_comdat_group, only_called_at_startup and only_called_at_exit.

* cgraph.c (dump_cgraph_node): Dump same_comdat_group,
	only_called_at_startup and only_called_at_exit.
	(cgraph_propagate_frequency): Compute only_called_at_startup and 
	only_called_at_exit.
	* cgraph.h (struct cgraph_node): New fileds only_called_at_startup and
	only_called_at_exit.
	* lto-cgraph.c (lto_output_node, input_overwrite_node): Stream the new
	flags.
	* predict.c (compute_function_frequency): Initialize the new flags.

From-SVN: r165560
This commit is contained in:
Jan Hubicka 2010-10-16 18:59:07 +02:00 committed by Jan Hubicka
parent 6eb6875d7e
commit 844db5d09e
5 changed files with 91 additions and 20 deletions

View File

@ -1,3 +1,15 @@
2010-10-16 Jan Hubicka <jh@suse.cz>
* cgraph.c (dump_cgraph_node): Dump same_comdat_group,
only_called_at_startup and only_called_at_exit.
(cgraph_propagate_frequency): Compute only_called_at_startup and
only_called_at_exit.
* cgraph.h (struct cgraph_node): New fileds only_called_at_startup and
only_called_at_exit.
* lto-cgraph.c (lto_output_node, input_overwrite_node): Stream the new
flags.
* predict.c (compute_function_frequency): Initialize the new flags.
2010-10-16 Eric Botcazou <ebotcazou@adacore.com>
* gimplify.c (gimplify_type_sizes) <ARRAY_TYPE>: If the type is to be

View File

@ -1816,6 +1816,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " (inline copy in %s/%i)",
cgraph_node_name (node->global.inlined_to),
node->global.inlined_to->uid);
if (node->same_comdat_group)
fprintf (f, " (same comdat group as %s/%i)",
cgraph_node_name (node->same_comdat_group),
node->same_comdat_group->uid);
if (node->clone_of)
fprintf (f, " (clone of %s/%i)",
cgraph_node_name (node->clone_of),
@ -1876,6 +1880,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " redefined_extern_inline");
if (TREE_ASM_WRITTEN (node->decl))
fprintf (f, " asm_written");
if (node->only_called_at_startup)
fprintf (f, " only_called_at_startup");
if (node->only_called_at_exit)
fprintf (f, " only_called_at_exit");
fprintf (f, "\n called by: ");
for (edge = node->callers; edge; edge = edge->next_caller)
@ -2627,20 +2635,32 @@ bool
cgraph_propagate_frequency (struct cgraph_node *node)
{
bool maybe_unlikely_executed = true, maybe_executed_once = true;
bool only_called_at_startup = true;
bool only_called_at_exit = true;
bool changed = false;
struct cgraph_edge *edge;
if (!node->local.local)
return false;
gcc_assert (node->analyzed);
if (node->frequency == NODE_FREQUENCY_HOT)
return false;
if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
return false;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
for (edge = node->callers;
edge && (maybe_unlikely_executed || maybe_executed_once);
edge && (maybe_unlikely_executed || maybe_executed_once
|| only_called_at_startup || only_called_at_exit);
edge = edge->next_caller)
{
if (edge->caller != node)
{
only_called_at_startup &= edge->caller->only_called_at_startup;
/* It makes snese to put main() together with the static constructors.
It will be executed for sure, but rest of functions called from
main are definitly not at startup only. */
if (MAIN_NAME_P (DECL_NAME (edge->caller->decl)))
only_called_at_startup = 0;
only_called_at_exit &= edge->caller->only_called_at_exit;
}
if (!edge->frequency)
continue;
switch (edge->caller->frequency)
@ -2649,7 +2669,8 @@ cgraph_propagate_frequency (struct cgraph_node *node)
break;
case NODE_FREQUENCY_EXECUTED_ONCE:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Called by %s that is executed once\n", cgraph_node_name (node));
fprintf (dump_file, " Called by %s that is executed once\n",
cgraph_node_name (node));
maybe_unlikely_executed = false;
if (edge->loop_nest)
{
@ -2661,27 +2682,52 @@ cgraph_propagate_frequency (struct cgraph_node *node)
case NODE_FREQUENCY_HOT:
case NODE_FREQUENCY_NORMAL:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Called by %s that is normal or hot\n", cgraph_node_name (node));
fprintf (dump_file, " Called by %s that is normal or hot\n",
cgraph_node_name (node));
maybe_unlikely_executed = false;
maybe_executed_once = false;
break;
}
}
if (maybe_unlikely_executed)
{
node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
if ((only_called_at_startup && !only_called_at_exit)
&& !node->only_called_at_startup)
{
node->only_called_at_startup = true;
if (dump_file)
fprintf (dump_file, "Node %s promoted to unlikely executed.\n", cgraph_node_name (node));
return true;
}
if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
{
node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
fprintf (dump_file, "Node %s promoted to only called at startup.\n",
cgraph_node_name (node));
changed = true;
}
if ((only_called_at_exit && !only_called_at_startup)
&& !node->only_called_at_exit)
{
node->only_called_at_exit = true;
if (dump_file)
fprintf (dump_file, "Node %s promoted to executed once.\n", cgraph_node_name (node));
return true;
}
return false;
fprintf (dump_file, "Node %s promoted to only called at exit.\n",
cgraph_node_name (node));
changed = true;
}
/* These come either from profile or user hints; never update them. */
if (node->frequency == NODE_FREQUENCY_HOT
|| node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
return changed;
if (maybe_unlikely_executed)
{
node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
if (dump_file)
fprintf (dump_file, "Node %s promoted to unlikely executed.\n",
cgraph_node_name (node));
changed = true;
}
if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
{
node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
if (dump_file)
fprintf (dump_file, "Node %s promoted to executed once.\n",
cgraph_node_name (node));
changed = true;
}
return changed;
}
/* Return true when NODE can not return or throw and thus

View File

@ -298,6 +298,10 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
/* How commonly executed the node is. Initialized during branch
probabilities pass. */
ENUM_BITFIELD (node_frequency) frequency : 2;
/* True when function can only be called at startup (from static ctor). */
unsigned only_called_at_startup : 1;
/* True when function can only be called at startup (from static dtor). */
unsigned only_called_at_exit : 1;
};
typedef struct cgraph_node *cgraph_node_ptr;

View File

@ -518,6 +518,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->finalized_by_frontend, 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1);
lto_output_bitpack (&bp);
lto_output_uleb128_stream (ob->main_stream, node->resolution);
@ -978,6 +980,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->alias = bp_unpack_value (bp, 1);
node->finalized_by_frontend = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1);
node->resolution = resolution;
}

View File

@ -2187,6 +2187,11 @@ compute_function_frequency (void)
{
basic_block bb;
struct cgraph_node *node = cgraph_node (current_function_decl);
if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
|| MAIN_NAME_P (DECL_NAME (current_function_decl)))
node->only_called_at_startup = true;
if (DECL_STATIC_DESTRUCTOR (current_function_decl))
node->only_called_at_exit = true;
if (!profile_info || !flag_branch_probabilities)
{