diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2015-01-20 21:03:23 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2015-01-20 20:03:23 +0000 |
commit | befb1f36a71758c5fd645b1f08b8886e7f5808da (patch) | |
tree | e9d54a11212a674f38a2545167dedcd4148a8def /gcc/ipa-utils.c | |
parent | bb1e543c64ff31a2e5d6959b0e4260c507c45b5b (diff) | |
download | gcc-befb1f36a71758c5fd645b1f08b8886e7f5808da.zip gcc-befb1f36a71758c5fd645b1f08b8886e7f5808da.tar.gz gcc-befb1f36a71758c5fd645b1f08b8886e7f5808da.tar.bz2 |
re PR ipa/63576 (ICE : in ipa_merge_profiles, at ipa-utils.c:540 during Firefox LTO/PGO build)
PR ipa/63576
* ipa-utils.c (ipa_merge_profiles): Merge speculative edges.
From-SVN: r219910
Diffstat (limited to 'gcc/ipa-utils.c')
-rw-r--r-- | gcc/ipa-utils.c | 92 |
1 files changed, 84 insertions, 8 deletions
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c index bc538c5..7612548 100644 --- a/gcc/ipa-utils.c +++ b/gcc/ipa-utils.c @@ -539,7 +539,7 @@ ipa_merge_profiles (struct cgraph_node *dst, } if (match) { - struct cgraph_edge *e; + struct cgraph_edge *e, *e2; basic_block srcbb, dstbb; /* TODO: merge also statement histograms. */ @@ -562,19 +562,95 @@ ipa_merge_profiles (struct cgraph_node *dst, pop_cfun (); for (e = dst->callees; e; e = e->next_callee) { - gcc_assert (!e->speculative); + if (e->speculative) + continue; e->count = gimple_bb (e->call_stmt)->count; e->frequency = compute_call_stmt_bb_frequency (dst->decl, gimple_bb (e->call_stmt)); } - for (e = dst->indirect_calls; e; e = e->next_callee) + for (e = dst->indirect_calls, e2 = src->indirect_calls; e; + e2 = (e2 ? e2->next_callee : NULL), e = e->next_callee) { - gcc_assert (!e->speculative); - e->count = gimple_bb (e->call_stmt)->count; - e->frequency = compute_call_stmt_bb_frequency - (dst->decl, - gimple_bb (e->call_stmt)); + gcov_type count = gimple_bb (e->call_stmt)->count; + int freq = compute_call_stmt_bb_frequency + (dst->decl, + gimple_bb (e->call_stmt)); + /* When call is speculative, we need to re-distribute probabilities + the same way as they was. This is not really correct because + in the other copy the speculation may differ; but probably it + is not really worth the effort. */ + if (e->speculative) + { + cgraph_edge *direct, *indirect; + cgraph_edge *direct2 = NULL, *indirect2 = NULL; + ipa_ref *ref; + + e->speculative_call_info (direct, indirect, ref); + gcc_assert (e == indirect); + if (e2 && e2->speculative) + e2->speculative_call_info (direct2, indirect2, ref); + if (indirect->count || direct->count) + { + /* We should mismatch earlier if there is no matching + indirect edge. */ + if (!e2) + { + if (dump_file) + fprintf (dump_file, + "Mismatch in merging indirect edges\n"); + } + else if (!e2->speculative) + indirect->count += e2->count; + else if (e2->speculative) + { + if (DECL_ASSEMBLER_NAME (direct2->callee->decl) + != DECL_ASSEMBLER_NAME (direct->callee->decl)) + { + if (direct2->count >= direct->count) + { + direct->redirect_callee (direct2->callee); + indirect->count += indirect2->count + + direct->count; + direct->count = direct2->count; + } + else + indirect->count += indirect2->count + direct2->count; + } + else + { + direct->count += direct2->count; + indirect->count += indirect2->count; + } + } + int prob = RDIV (direct->count * REG_BR_PROB_BASE , + direct->count + indirect->count); + direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE); + indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob), + REG_BR_PROB_BASE); + } + else + /* At the moment we should have only profile feedback based + speculations when merging. */ + gcc_unreachable (); + } + else if (e2->speculative) + { + cgraph_edge *direct, *indirect; + ipa_ref *ref; + + e2->speculative_call_info (direct, indirect, ref); + e->count = count; + e->frequency = freq; + int prob = RDIV (direct->count * REG_BR_PROB_BASE, e->count); + e->make_speculative (direct->callee, direct->count, + RDIV (freq * prob, REG_BR_PROB_BASE)); + } + else + { + e->count = count; + e->frequency = freq; + } } src->release_body (); inline_update_overall_summary (dst); |