Commit 844db5d0 by Jan Hubicka Committed by Jan Hubicka

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

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
parent 6eb6875d
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> 2010-10-16 Eric Botcazou <ebotcazou@adacore.com>
* gimplify.c (gimplify_type_sizes) <ARRAY_TYPE>: If the type is to be * gimplify.c (gimplify_type_sizes) <ARRAY_TYPE>: If the type is to be
...@@ -1816,6 +1816,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) ...@@ -1816,6 +1816,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " (inline copy in %s/%i)", fprintf (f, " (inline copy in %s/%i)",
cgraph_node_name (node->global.inlined_to), cgraph_node_name (node->global.inlined_to),
node->global.inlined_to->uid); 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) if (node->clone_of)
fprintf (f, " (clone of %s/%i)", fprintf (f, " (clone of %s/%i)",
cgraph_node_name (node->clone_of), cgraph_node_name (node->clone_of),
...@@ -1876,6 +1880,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) ...@@ -1876,6 +1880,10 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " redefined_extern_inline"); fprintf (f, " redefined_extern_inline");
if (TREE_ASM_WRITTEN (node->decl)) if (TREE_ASM_WRITTEN (node->decl))
fprintf (f, " asm_written"); 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: "); fprintf (f, "\n called by: ");
for (edge = node->callers; edge; edge = edge->next_caller) for (edge = node->callers; edge; edge = edge->next_caller)
...@@ -2627,20 +2635,32 @@ bool ...@@ -2627,20 +2635,32 @@ bool
cgraph_propagate_frequency (struct cgraph_node *node) cgraph_propagate_frequency (struct cgraph_node *node)
{ {
bool maybe_unlikely_executed = true, maybe_executed_once = true; 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; struct cgraph_edge *edge;
if (!node->local.local) if (!node->local.local)
return false; return false;
gcc_assert (node->analyzed); 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)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
for (edge = node->callers; 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) 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) if (!edge->frequency)
continue; continue;
switch (edge->caller->frequency) switch (edge->caller->frequency)
...@@ -2649,7 +2669,8 @@ cgraph_propagate_frequency (struct cgraph_node *node) ...@@ -2649,7 +2669,8 @@ cgraph_propagate_frequency (struct cgraph_node *node)
break; break;
case NODE_FREQUENCY_EXECUTED_ONCE: case NODE_FREQUENCY_EXECUTED_ONCE:
if (dump_file && (dump_flags & TDF_DETAILS)) 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; maybe_unlikely_executed = false;
if (edge->loop_nest) if (edge->loop_nest)
{ {
...@@ -2661,27 +2682,52 @@ cgraph_propagate_frequency (struct cgraph_node *node) ...@@ -2661,27 +2682,52 @@ cgraph_propagate_frequency (struct cgraph_node *node)
case NODE_FREQUENCY_HOT: case NODE_FREQUENCY_HOT:
case NODE_FREQUENCY_NORMAL: case NODE_FREQUENCY_NORMAL:
if (dump_file && (dump_flags & TDF_DETAILS)) 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_unlikely_executed = false;
maybe_executed_once = false; maybe_executed_once = false;
break; break;
} }
} }
if (maybe_unlikely_executed) if ((only_called_at_startup && !only_called_at_exit)
{ && !node->only_called_at_startup)
node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED; {
node->only_called_at_startup = true;
if (dump_file) if (dump_file)
fprintf (dump_file, "Node %s promoted to unlikely executed.\n", cgraph_node_name (node)); fprintf (dump_file, "Node %s promoted to only called at startup.\n",
return true; cgraph_node_name (node));
} changed = true;
if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE) }
{ if ((only_called_at_exit && !only_called_at_startup)
node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; && !node->only_called_at_exit)
{
node->only_called_at_exit = true;
if (dump_file) if (dump_file)
fprintf (dump_file, "Node %s promoted to executed once.\n", cgraph_node_name (node)); fprintf (dump_file, "Node %s promoted to only called at exit.\n",
return true; cgraph_node_name (node));
} changed = true;
return false; }
/* 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 /* Return true when NODE can not return or throw and thus
......
...@@ -298,6 +298,10 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node { ...@@ -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 /* How commonly executed the node is. Initialized during branch
probabilities pass. */ probabilities pass. */
ENUM_BITFIELD (node_frequency) frequency : 2; 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; typedef struct cgraph_node *cgraph_node_ptr;
......
...@@ -518,6 +518,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, ...@@ -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->alias, 1);
bp_pack_value (&bp, node->finalized_by_frontend, 1); bp_pack_value (&bp, node->finalized_by_frontend, 1);
bp_pack_value (&bp, node->frequency, 2); 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_bitpack (&bp);
lto_output_uleb128_stream (ob->main_stream, node->resolution); lto_output_uleb128_stream (ob->main_stream, node->resolution);
...@@ -978,6 +980,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data, ...@@ -978,6 +980,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->alias = bp_unpack_value (bp, 1); node->alias = bp_unpack_value (bp, 1);
node->finalized_by_frontend = 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->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; node->resolution = resolution;
} }
......
...@@ -2187,6 +2187,11 @@ compute_function_frequency (void) ...@@ -2187,6 +2187,11 @@ compute_function_frequency (void)
{ {
basic_block bb; basic_block bb;
struct cgraph_node *node = cgraph_node (current_function_decl); 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) if (!profile_info || !flag_branch_probabilities)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment