From 844db5d09eb972e4f9188b77854d76ce345ca9ee Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sat, 16 Oct 2010 18:59:07 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 ++++++++ gcc/cgraph.c | 86 +++++++++++++++++++++++++++++++++++++++++++------------- gcc/cgraph.h | 4 +++ gcc/lto-cgraph.c | 4 +++ gcc/predict.c | 5 ++++ 5 files changed, 91 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 375404c8264..7c3dc3ba2fb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2010-10-16 Jan Hubicka + + * 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 * gimplify.c (gimplify_type_sizes) : If the type is to be diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 465e9afbf79..342ad63562f 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 d7ca67c692f..ea95f70bba7 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 b61e5d16761..85a7c4035c5 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 1b61ee47322..eb91b87819d 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) { -- 2.11.4.GIT