summaryrefslogtreecommitdiff
path: root/gcc/ipa-profile.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-09-09 07:37:53 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-09-09 07:37:53 +0000
commite27f29dd2b9427e4213795ae892920c86e946e4e (patch)
treebf09a0700a2bcf2fd44b45cba67aa2fbf69d9130 /gcc/ipa-profile.c
parentd9ea4515ea28358084597612b5c86ddb3305faef (diff)
downloadgcc-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.c88
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)