Fix profile merging WRT speculative edges
Markus Trippelsdorf
markus@trippelsdorf.de
Tue Jan 20 21:30:00 GMT 2015
On 2015.01.20 at 21:04 +0100, Jan Hubicka wrote:
> this patch fixes ICE in ipa_merge_profiles on speculative edges.
>
> Bootstrapped/regtested x86_64-linux, comitted. Also tested by Markus on
> Firefox build.
This needs one additional fix. See below.
> PR ipa/63576
> * ipa-utils.c (ipa_merge_profiles): Merge speculative edges.
> Index: ipa-utils.c
> ===================================================================
> --- ipa-utils.c (revision 219871)
> +++ ipa-utils.c (working copy)
> @@ -539,7 +539,7 @@ ipa_merge_profiles (struct cgraph_node *
> }
> 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 *
> 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)
+ else if (e2 && e2->speculative)
Otherwise it will crash:
lto1: internal compiler error: Segmentation fault
0xa12f6f crash_signal
../../gcc/gcc/toplev.c:381
0x88b190 ipa_merge_profiles(cgraph_node*, cgraph_node*)
../../gcc/gcc/ipa-utils.c:637
0x603722 lto_cgraph_replace_node
../../gcc/gcc/lto/lto-symtab.c:124
0x604cf3 lto_symtab_merge_symbols_1
../../gcc/gcc/lto/lto-symtab.c:619
0x604cf3 lto_symtab_merge_symbols()
../../gcc/gcc/lto/lto-symtab.c:647
0x5fa52e read_cgraph_and_symbols
../../gcc/gcc/lto/lto.c:3109
0x5fa52e lto_main()
../../gcc/gcc/lto/lto.c:3436
Please submit a full bug report,
with preprocessed source if appropriate.
> + {
> + 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);
>
--
Markus
More information about the Gcc-patches
mailing list