aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2010-10-16 18:59:07 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2010-10-16 16:59:07 +0000
commit844db5d09eb972e4f9188b77854d76ce345ca9ee (patch)
tree729e8daec41bc5163de53301f1aa679b1c2fadf7
parent6eb6875d7ec398935d3ae76f805e33db0c3773dd (diff)
downloadgcc-844db5d09eb972e4f9188b77854d76ce345ca9ee.zip
gcc-844db5d09eb972e4f9188b77854d76ce345ca9ee.tar.gz
gcc-844db5d09eb972e4f9188b77854d76ce345ca9ee.tar.bz2
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
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cgraph.c86
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/lto-cgraph.c4
-rw-r--r--gcc/predict.c5
5 files changed, 91 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 375404c..7c3dc3b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 465e9af..342ad63 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -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
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index d7ca67c..ea95f70 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index b61e5d1..85a7c40 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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;
}
diff --git a/gcc/predict.c b/gcc/predict.c
index 1b61ee4..eb91b87 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -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)
{