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.c91
1 files changed, 50 insertions, 41 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 2197769..5b0050a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2181,47 +2181,51 @@ copy_bb (copy_body_data *id, basic_block bb,
if (edge)
{
struct cgraph_edge *old_edge = edge;
- profile_count old_cnt = edge->count;
- edge = edge->clone (id->dst_node, call_stmt,
- gimple_uid (stmt),
- num, den,
- true);
-
- /* A speculative call is consist of edges - indirect edge
- and direct edges (one indirect edeg may has multiple
- direct edges). Duplicate the whole thing and
- distribute frequencies accordingly. */
+
+ /* A speculative call is consist of multiple
+ edges - indirect edge and one or more direct edges
+ Duplicate the whole thing and distribute frequencies
+ accordingly. */
if (edge->speculative)
{
- struct cgraph_edge *direct, *indirect;
- struct ipa_ref *ref;
-
- gcc_assert (!edge->indirect_unknown_callee);
- old_edge->speculative_call_info (direct, indirect, ref);
- while (old_edge->next_callee
- && old_edge->next_callee->speculative
- && indirect->num_speculative_call_targets_p ()
- > 1)
+ int n = 0;
+ profile_count direct_cnt
+ = profile_count::zero ();
+
+ /* First figure out the distribution of counts
+ so we can re-scale BB profile accordingly. */
+ for (cgraph_edge *e = old_edge; e;
+ e = e->next_speculative_call_target ())
+ direct_cnt = direct_cnt + e->count;
+
+ cgraph_edge *indirect
+ = old_edge->speculative_call_indirect_edge ();
+ profile_count indir_cnt = indirect->count;
+
+ /* Next iterate all direct edges, clone it and its
+ corresponding reference and update profile. */
+ for (cgraph_edge *e = old_edge;
+ e;
+ e = e->next_speculative_call_target ())
{
- id->dst_node->clone_reference (ref, stmt);
-
- edge = old_edge->next_callee;
- edge = edge->clone (id->dst_node, call_stmt,
- gimple_uid (stmt), num, den,
- true);
- old_edge = old_edge->next_callee;
- gcc_assert (!edge->indirect_unknown_callee);
-
- /* If the indirect edge has multiple speculative
- calls, iterate through all direct calls
- associated to the speculative call and clone
- all related direct edges before cloning the
- related indirect edge. */
- old_edge->speculative_call_info (direct, indirect,
- ref);
+ profile_count cnt = e->count;
+
+ id->dst_node->clone_reference
+ (e->speculative_call_target_ref (), stmt);
+ edge = e->clone (id->dst_node, call_stmt,
+ gimple_uid (stmt), num, den,
+ true);
+ profile_probability prob
+ = cnt.probability_in (direct_cnt
+ + indir_cnt);
+ edge->count
+ = copy_basic_block->count.apply_probability
+ (prob);
+ n++;
}
-
- profile_count indir_cnt = indirect->count;
+ gcc_checking_assert
+ (indirect->num_speculative_call_targets_p ()
+ == n);
/* Duplicate the indirect edge after all direct edges
cloned. */
@@ -2231,14 +2235,19 @@ copy_bb (copy_body_data *id, basic_block bb,
true);
profile_probability prob
- = indir_cnt.probability_in (old_cnt + indir_cnt);
+ = indir_cnt.probability_in (direct_cnt
+ + indir_cnt);
indirect->count
= copy_basic_block->count.apply_probability (prob);
- edge->count = copy_basic_block->count - indirect->count;
- id->dst_node->clone_reference (ref, stmt);
}
else
- edge->count = copy_basic_block->count;
+ {
+ edge = edge->clone (id->dst_node, call_stmt,
+ gimple_uid (stmt),
+ num, den,
+ true);
+ edge->count = copy_basic_block->count;
+ }
}
break;