aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 77013b3..0d1f1c7 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2353,6 +2353,29 @@ redirect_all_calls (copy_body_data * id, basic_block bb)
}
}
+/* Convert estimated frequencies into counts for NODE, scaling COUNT
+ with each bb's frequency. Used when NODE has a 0-weight entry
+ but we are about to inline it into a non-zero count call bb.
+ See the comments for handle_missing_profiles() in predict.c for
+ when this can happen for COMDATs. */
+
+void
+freqs_to_counts (struct cgraph_node *node, gcov_type count)
+{
+ basic_block bb;
+ edge_iterator ei;
+ edge e;
+ struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
+
+ FOR_ALL_BB_FN(bb, fn)
+ {
+ bb->count = apply_scale (count,
+ GCOV_COMPUTE_SCALE (bb->frequency, BB_FREQ_MAX));
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->count = apply_probability (e->src->count, e->probability);
+ }
+}
+
/* Make a copy of the body of FN so that it can be inserted inline in
another function. Walks FN via CFG, returns new fndecl. */
@@ -2373,6 +2396,24 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
int incoming_frequency = 0;
gcov_type incoming_count = 0;
+ /* This can happen for COMDAT routines that end up with 0 counts
+ despite being called (see the comments for handle_missing_profiles()
+ in predict.c as to why). Apply counts to the blocks in the callee
+ before inlining, using the guessed edge frequencies, so that we don't
+ end up with a 0-count inline body which can confuse downstream
+ optimizations such as function splitting. */
+ if (!ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count && count)
+ {
+ /* Apply the larger of the call bb count and the total incoming
+ call edge count to the callee. */
+ gcov_type in_count = 0;
+ struct cgraph_edge *in_edge;
+ for (in_edge = id->src_node->callers; in_edge;
+ in_edge = in_edge->next_caller)
+ in_count += in_edge->count;
+ freqs_to_counts (id->src_node, count > in_count ? count : in_count);
+ }
+
if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
count_scale
= GCOV_COMPUTE_SCALE (count,