ipa-profile.c: Add toplevel comment.
* 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. From-SVN: r202382
This commit is contained in:
parent
a12cd2db29
commit
daf5c7705f
|
@ -1,3 +1,13 @@
|
|||
2013-09-08 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* 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.
|
||||
|
||||
2013-09-08 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* ipa-prop.c (try_make_edge_direct_simple_call): Do not special case
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -2871,13 +2871,14 @@ compute_function_frequency (void)
|
|||
{
|
||||
basic_block bb;
|
||||
struct cgraph_node *node = cgraph_get_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_status != PROFILE_READ)
|
||||
{
|
||||
int flags = flags_from_decl_or_type (current_function_decl);
|
||||
if (lookup_attribute ("cold", DECL_ATTRIBUTES (current_function_decl))
|
||||
|
@ -2895,7 +2896,13 @@ compute_function_frequency (void)
|
|||
node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
|
||||
return;
|
||||
}
|
||||
node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
|
||||
|
||||
/* Only first time try to drop function into unlikely executed.
|
||||
After inlining the roundoff errors may confuse us.
|
||||
Ipa-profile pass will drop functions only called from unlikely
|
||||
functions to unlikely and that is most of what we care about. */
|
||||
if (!cfun->after_inlining)
|
||||
node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
if (maybe_hot_bb_p (cfun, bb))
|
||||
|
|
Loading…
Reference in New Issue