diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-09 07:37:53 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-09-09 07:37:53 +0000 |
commit | e27f29dd2b9427e4213795ae892920c86e946e4e (patch) | |
tree | bf09a0700a2bcf2fd44b45cba67aa2fbf69d9130 /gcc/ipa-profile.c | |
parent | d9ea4515ea28358084597612b5c86ddb3305faef (diff) | |
download | gcc-e27f29dd2b9427e4213795ae892920c86e946e4e.tar.gz |
* ipa-profile.c: Add toplevel comment.
(ipa_propagate_frequency_1): Be more conservative when profile is read.
(contains_hot_call_p): New function.
(ipa_propagate_frequency): Set frequencies based on counts when
profile is read.
* predict.c (compute_function_frequency): Use PROFILE_READ gueard for
profile; do not tamper with profile after inlining if it is read.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202382 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-profile.c')
-rw-r--r-- | gcc/ipa-profile.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index cb42c8f0f45..2b22333d1b9 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -17,6 +17,33 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* ipa-profile pass implements the following analysis propagating profille + inter-procedurally. + + - Count histogram construction. This is a histogram analyzing how much + time is spent executing statements with a given execution count read + from profile feedback. This histogram is complette only with LTO, + otherwise it contains information only about the current unit. + + Similar histogram is also estimated by coverage runtime. This histogram + is not dependent on LTO, but it suffers from various defects; first + gcov runtime is not weighting individual basic block by estimated execution + time and second the merging of multiple runs makes assumption that the + histogram distribution did not change. Consequentely histogram constructed + here may be more precise. + + The information is used to set hot/cold thresholds. + - Next speculative indirect call resolution is performed: the local + profile pass assigns profile-id to each function and provide us with a + histogram specifying the most common target. We look up the callgraph + node corresponding to the target and produce a speculative call. + + This call may or may not survive through IPA optimization based on decision + of inliner. + - Finally we propagate the following flags: unlikely executed, executed + once, executed at startup and executed at exit. These flags are used to + control code size/performance threshold and and code placement (by producing + .text.unlikely/.text.hot/.text.startup/.text.exit subsections). */ #include "config.h" #include "system.h" #include "coretypes.h" @@ -301,6 +328,18 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data) d->only_called_at_startup = 0; d->only_called_at_exit &= edge->caller->only_called_at_exit; } + + /* When profile feedback is available, do not try to propagate too hard; + counts are already good guide on function frequencies and roundoff + errors can make us to push function into unlikely section even when + it is executed by the train run. Transfer the function only if all + callers are unlikely executed. */ + if (profile_info && flag_branch_probabilities + && (edge->caller->frequency != NODE_FREQUENCY_UNLIKELY_EXECUTED + || (edge->caller->global.inlined_to + && edge->caller->global.inlined_to->frequency + != NODE_FREQUENCY_UNLIKELY_EXECUTED))) + d->maybe_unlikely_executed = false; if (!edge->frequency) continue; switch (edge->caller->frequency) @@ -332,6 +371,24 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data) return edge != NULL; } +/* Return ture if NODE contains hot calls. */ + +bool +contains_hot_call_p (struct cgraph_node *node) +{ + struct cgraph_edge *e; + for (e = node->callees; e; e = e->next_callee) + if (cgraph_maybe_hot_edge_p (e)) + return true; + else if (!e->inline_failed + && contains_hot_call_p (e->callee)) + return true; + for (e = node->indirect_calls; e; e = e->next_callee) + if (cgraph_maybe_hot_edge_p (e)) + return true; + return false; +} + /* See if the frequency of NODE can be updated based on frequencies of its callers. */ bool @@ -343,6 +400,7 @@ ipa_propagate_frequency (struct cgraph_node *node) /* We can not propagate anything useful about externally visible functions nor about virtuals. */ if (!node->local.local + || node->symbol.alias || (flag_devirtualize && DECL_VIRTUAL_P (node->symbol.decl))) return false; gcc_assert (node->symbol.analyzed); @@ -369,6 +427,36 @@ ipa_propagate_frequency (struct cgraph_node *node) cgraph_node_name (node)); changed = true; } + + /* With profile we can decide on hot/normal based on count. */ + if (node->count) + { + bool hot = false; + if (node->count >= get_hot_bb_threshold ()) + hot = true; + if (!hot) + hot |= contains_hot_call_p (node); + if (hot) + { + if (node->frequency != NODE_FREQUENCY_HOT) + { + if (dump_file) + fprintf (dump_file, "Node %s promoted to hot.\n", + cgraph_node_name (node)); + node->frequency = NODE_FREQUENCY_HOT; + return true; + } + return false; + } + else if (node->frequency == NODE_FREQUENCY_HOT) + { + if (dump_file) + fprintf (dump_file, "Node %s reduced to normal.\n", + cgraph_node_name (node)); + node->frequency = NODE_FREQUENCY_NORMAL; + 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) |