aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2017-06-04 20:55:08 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2017-06-04 18:55:08 +0000
commit3995f3a2207fbde0c31341d79bf49563d681ca9a (patch)
tree51458cb1039eb15cb224e5b7de48d9e17703b737 /gcc/predict.c
parenta7e8f816bd09adc24013b5fd3a43128778f6581b (diff)
downloadgcc-3995f3a2207fbde0c31341d79bf49563d681ca9a.zip
gcc-3995f3a2207fbde0c31341d79bf49563d681ca9a.tar.gz
gcc-3995f3a2207fbde0c31341d79bf49563d681ca9a.tar.bz2
i386.c (make_resolver_func): Update.
2017-05-23 Jan Hubicka <hubicka@ucw.cz> * config/i386/i386.c (make_resolver_func): Update. * Makefile.in: Add profile-count.h and profile-count.o * auto-profile.c (afdo_indirect_call): Update to new API. (afdo_set_bb_count): Update. (afdo_propagate_edge): Update. (afdo_propagate_circuit): Update. (afdo_calculate_branch_prob): Update. (afdo_annotate_cfg): Update. * basic-block.h: Include profile-count.h (struct edge_def): Turn count to profile_count. (struct basic_block_def): Likewie. (REG_BR_PROB_BASE): Move to profile-count.h (RDIV): Move to profile-count.h * bb-reorder.c (max_entry_count): Turn to profile_count. (find_traces): Update. (rotate_loop):Update. (connect_traces):Update. (sanitize_hot_paths):Update. * bt-load.c (migrate_btr_defs): Update. * cfg.c (RDIV): Remove. (init_flow): Use alloc_block. (alloc_block): Uninitialize count. (unchecked_make_edge): Uninitialize count. (check_bb_profile): Update. (dump_edge_info): Update. (dump_bb_info): Update. (update_bb_profile_for_threading): Update. (scale_bbs_frequencies_int): Update. (scale_bbs_frequencies_gcov_type): Update. (scale_bbs_frequencies_profile_count): New. * cfg.h (update_bb_profile_for_threading): Update. (scale_bbs_frequencies_profile_count): Declare. * cfgbuild.c (compute_outgoing_frequencies): Update. (find_many_sub_basic_blocks): Update. * cfgcleanup.c (try_forward_edges): Update. (try_crossjump_to_edge): Update. * cfgexpand.c (expand_gimple_tailcall): Update. (construct_exit_block): Update. * cfghooks.c (verify_flow_info): Update. (dump_bb_for_graph): Update. (split_edge): Update. (make_forwarder_block): Update. (duplicate_block): Update. (account_profile_record): Update. * cfgloop.c (find_subloop_latch_edge_by_profile): Update. (get_estimated_loop_iterations): Update. * cfgloopanal.c (expected_loop_iterations_unbounded): Update. (single_likely_exit): Update. * cfgloopmanip.c (scale_loop_profile): Update. (loopify): Update. (set_zero_probability): Update. (lv_adjust_loop_entry_edge): Update. * cfgrtl.c (force_nonfallthru_and_redirect): Update. (purge_dead_edges): Update. (rtl_account_profile_record): Update. * cgraph.c (cgraph_node::create): Uninitialize count. (symbol_table::create_edge): Uninitialize count. (cgraph_update_edges_for_call_stmt_node): Update. (cgraph_edge::dump_edge_flags): Update. (cgraph_node::dump): Update. (cgraph_edge::maybe_hot_p): Update. * cgraph.h: Include profile-count.h (create_clone), create_edge, create_indirect_edge): Update. (cgraph_node): Turn count to profile_count. (cgraph_edge0: Likewise. (make_speculative, clone): Update. (create_edge): Update. (init_lowered_empty_function): Update. * cgraphclones.c (cgraph_edge::clone): Update. (duplicate_thunk_for_node): Update. (cgraph_node::create_clone): Update. * cgraphunit.c (cgraph_node::analyze): Update. (cgraph_node::expand_thunk): Update. * final.c (dump_basic_block_info): Update. * gimple-streamer-in.c (input_bb): Update. * gimple-streamer-out.c (output_bb): Update. * graphite.c (print_global_statistics): Update. (print_graphite_scop_statistics): Update. * hsa-brig.c: Include basic-block.h. * hsa-dump.c: Include basic-block.h. * hsa-gen.c (T sum_slice): Update. (convert_switch_statements):Update. * hsa-regalloc.c: Include basic-block.h. * ipa-chkp.c (chkp_produce_thunks): Update. * ipa-cp.c (struct caller_statistics): Update. (init_caller_stats): Update. (gather_caller_stats): Update. (ipcp_cloning_candidate_p): Update. (good_cloning_opportunity_p): Update. (get_info_about_necessary_edges): Update. (dump_profile_updates): Update. (update_profiling_info): Update. (update_specialized_profile): Update. (perhaps_add_new_callers): Update. (decide_about_value): Update. (ipa_cp_c_finalize): Update. * ipa-devirt.c (struct odr_type_warn_count): Update. (struct decl_warn_count): Update. (struct final_warning_record): Update. (possible_polymorphic_call_targets): Update. (ipa_devirt): Update. * ipa-fnsummary.c (redirect_to_unreachable): Update. * ipa-icf.c (sem_function::merge): Update. * ipa-inline-analysis.c (do_estimate_edge_time): Update. * ipa-inline.c (compute_uninlined_call_time): Update. (compute_inlined_call_time): Update. (want_inline_small_function_p): Update. (want_inline_self_recursive_call_p): Update. (edge_badness): Update. (lookup_recursive_calls): Update. (recursive_inlining): Update. (inline_small_functions): Update. (dump_overall_stats): Update. (dump_inline_stats): Update. * ipa-profile.c (ipa_profile_generate_summary): Update. (ipa_propagate_frequency): Update. (ipa_profile): Update. * ipa-prop.c (ipa_make_edge_direct_to_target): Update. * ipa-utils.c (ipa_merge_profiles): Update. * loop-doloop.c (doloop_modify): Update. * loop-unroll.c (report_unroll): Update. (unroll_loop_runtime_iterations): Update. * lto-cgraph.c (lto_output_edge): Update. (lto_output_node): Update. (input_node): Update. (input_edge): Update. (merge_profile_summaries): Update. * lto-streamer-in.c (input_cfg): Update. * lto-streamer-out.c (output_cfg): Update. * mcf.c (create_fixup_graph): Update. (adjust_cfg_counts): Update. (sum_edge_counts): Update. * modulo-sched.c (sms_schedule): Update. * postreload-gcse.c (eliminate_partially_redundant_load): Update. * predict.c (maybe_hot_count_p): Update. (probably_never_executed): Update. (dump_prediction): Update. (combine_predictions_for_bb): Update. (propagate_freq): Update. (handle_missing_profiles): Update. (counts_to_freqs): Update. (rebuild_frequencies): Update. (force_edge_cold): Update. * predict.h: Include profile-count.h (maybe_hot_count_p, counts_to_freqs): UPdate. * print-rtl-function.c: Do not include cfg.h * print-rtl.c: Include basic-block.h * profile-count.c: New file. * profile-count.h: New file. * profile.c (is_edge_inconsistent): Update. (correct_negative_edge_counts): Update. (is_inconsistent): Update. (set_bb_counts): Update. (read_profile_edge_counts): Update. (compute_frequency_overlap): Update. (compute_branch_probabilities): Update; Initialize and deinitialize gcov_count tables. (branch_prob): Update. * profile.h (bb_gcov_counts, edge_gcov_counts): New. (edge_gcov_count): New. (bb_gcov_count): New. * shrink-wrap.c (try_shrink_wrapping): Update. * tracer.c (better_p): Update. * trans-mem.c (expand_transaction): Update. (ipa_tm_insert_irr_call): Update. (ipa_tm_insert_gettmclone_call): Update. * tree-call-cdce.c: Update. * tree-cfg.c (gimple_duplicate_sese_region): Update. (gimple_duplicate_sese_tail): Update. (gimple_account_profile_record): Update. (execute_fixup_cfg): Update. * tree-inline.c (copy_bb): Update. (copy_edges_for_bb): Update. (initialize_cfun): Update. (freqs_to_counts): Update. (copy_cfg_body): Update. (expand_call_inline): Update. * tree-ssa-ifcombine.c (update_profile_after_ifcombine): Update. * tree-ssa-loop-ivcanon.c (unloop_loops): Update. (try_unroll_loop_completely): Update. (try_peel_loop): Update. * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update. * tree-ssa-loop-niter.c (estimate_numbers_of_iterations_loop): Update. * tree-ssa-loop-split.c (connect_loops): Update. * tree-ssa-loop-unswitch.c (hoist_guard): Update. * tree-ssa-reassoc.c (branch_fixup): Update. * tree-ssa-tail-merge.c (replace_block_by): Update. * tree-ssa-threadupdate.c (create_block_for_threading): Update. (compute_path_counts): Update. (update_profile): Update. (recompute_probabilities): Update. (update_joiner_offpath_counts): Update. (estimated_freqs_path): Update. (freqs_to_counts_path): Update. (clear_counts_path): Update. (ssa_fix_duplicate_block_edges): Update. (duplicate_thread_path): Update. * tree-switch-conversion.c (case_bit_test_cmp): Update. (struct switch_conv_info): Update. * tree-tailcall.c (decrease_profile): Update. * tree-vect-loop-manip.c (slpeel_add_loop_guard): Update. * tree-vect-loop.c (scale_profile_for_vect_loop): Update. * value-prof.c (check_counter): Update. (gimple_divmod_fixed_value): Update. (gimple_mod_pow2): Update. (gimple_mod_subtract): Update. (gimple_ic_transform): Update. (gimple_stringop_fixed_value): Update. * value-prof.h (gimple_ic): Update. * gcc.dg/tree-ssa/attr-hotcold-2.c: Update template. From-SVN: r248863
Diffstat (limited to 'gcc/predict.c')
-rw-r--r--gcc/predict.c146
1 files changed, 70 insertions, 76 deletions
diff --git a/gcc/predict.c b/gcc/predict.c
index ac35fa4..8eb2863 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -172,14 +172,14 @@ set_hot_bb_threshold (gcov_type min)
/* Return TRUE if frequency FREQ is considered to be hot. */
bool
-maybe_hot_count_p (struct function *fun, gcov_type count)
+maybe_hot_count_p (struct function *, profile_count count)
{
- if (fun && profile_status_for_fn (fun) != PROFILE_READ)
+ if (!count.initialized_p ())
return true;
/* Code executed at most once is not hot. */
- if (profile_info->runs >= count)
+ if (count <= MAX (profile_info ? profile_info->runs : 1, 1))
return false;
- return (count >= get_hot_bb_threshold ());
+ return (count.to_gcov_type () >= get_hot_bb_threshold ());
}
/* Return true in case BB can be CPU intensive and should be optimized
@@ -210,42 +210,17 @@ maybe_hot_edge_p (edge e)
static bool
probably_never_executed (struct function *fun,
- gcov_type count, int frequency)
+ profile_count count, int)
{
gcc_checking_assert (fun);
- if (profile_status_for_fn (fun) == PROFILE_READ)
+ if (count.initialized_p () && profile_status_for_fn (fun) == PROFILE_READ)
{
- int unlikely_count_fraction = PARAM_VALUE (UNLIKELY_BB_COUNT_FRACTION);
- if (count * unlikely_count_fraction >= profile_info->runs)
- return false;
- if (!frequency)
+ if (count == profile_count::zero ())
return true;
- if (!ENTRY_BLOCK_PTR_FOR_FN (fun)->frequency)
+
+ int unlikely_count_fraction = PARAM_VALUE (UNLIKELY_BB_COUNT_FRACTION);
+ if (count.apply_scale (unlikely_count_fraction, 1) >= profile_info->runs)
return false;
- if (ENTRY_BLOCK_PTR_FOR_FN (fun)->count)
- {
- gcov_type computed_count;
- /* Check for possibility of overflow, in which case entry bb count
- is large enough to do the division first without losing much
- precision. */
- if (ENTRY_BLOCK_PTR_FOR_FN (fun)->count < REG_BR_PROB_BASE *
- REG_BR_PROB_BASE)
- {
- gcov_type scaled_count
- = frequency * ENTRY_BLOCK_PTR_FOR_FN (fun)->count *
- unlikely_count_fraction;
- computed_count = RDIV (scaled_count,
- ENTRY_BLOCK_PTR_FOR_FN (fun)->frequency);
- }
- else
- {
- computed_count = RDIV (ENTRY_BLOCK_PTR_FOR_FN (fun)->count,
- ENTRY_BLOCK_PTR_FOR_FN (fun)->frequency);
- computed_count *= frequency * unlikely_count_fraction;
- }
- if (computed_count >= profile_info->runs)
- return false;
- }
return true;
}
if ((!profile_info || !(opt_for_fn (fun->decl, flag_branch_probabilities)))
@@ -772,13 +747,16 @@ dump_prediction (FILE *file, enum br_predictor predictor, int probability,
edge_info_str, reason_messages[reason],
probability * 100.0 / REG_BR_PROB_BASE);
- if (bb->count)
+ if (bb->count.initialized_p ())
{
- fprintf (file, " exec %" PRId64, bb->count);
+ fprintf (file, " exec ");
+ bb->count.dump (file);
if (e)
{
- fprintf (file, " hit %" PRId64, e->count);
- fprintf (file, " (%.1f%%)", e->count * 100.0 / bb->count);
+ fprintf (file, " hit ");
+ e->count.dump (file);
+ fprintf (file, " (%.1f%%)", e->count.to_gcov_type() * 100.0
+ / bb->count.to_gcov_type ());
}
}
@@ -1113,7 +1091,7 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
if (pred->ep_probability <= PROB_VERY_UNLIKELY)
unlikely_edges.add (pred->ep_edge);
- if (!bb->count && !dry_run)
+ if (!bb->count.initialized_p () && !dry_run)
set_even_probabilities (bb, &unlikely_edges);
clear_bb_predictions (bb);
if (dump_file)
@@ -1239,7 +1217,7 @@ combine_predictions_for_bb (basic_block bb, bool dry_run)
}
clear_bb_predictions (bb);
- if (!bb->count && !dry_run)
+ if (!bb->count.initialized_p () && !dry_run)
{
first->probability = combined_probability;
second->probability = REG_BR_PROB_BASE - combined_probability;
@@ -3011,7 +2989,10 @@ propagate_freq (basic_block head, bitmap tovisit)
BLOCK_INFO (bb)->npredecessors = count;
/* When function never returns, we will never process exit block. */
if (!count && bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
- bb->count = bb->frequency = 0;
+ {
+ bb->count = profile_count::zero ();
+ bb->frequency = 0;
+ }
}
BLOCK_INFO (head)->frequency = 1;
@@ -3152,7 +3133,7 @@ estimate_loops (void)
whether it is expected to be hot given the CALL_COUNT. */
static void
-drop_profile (struct cgraph_node *node, gcov_type call_count)
+drop_profile (struct cgraph_node *node, profile_count call_count)
{
struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
/* In the case where this was called by another function with a
@@ -3220,18 +3201,21 @@ handle_missing_profiles (void)
FOR_EACH_DEFINED_FUNCTION (node)
{
struct cgraph_edge *e;
- gcov_type call_count = 0;
+ profile_count call_count = profile_count::zero ();
gcov_type max_tp_first_run = 0;
struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
- if (node->count)
+ if (!(node->count == profile_count::zero ()))
continue;
for (e = node->callers; e; e = e->next_caller)
{
- call_count += e->count;
+ if (e->count.initialized_p () > 0)
+ {
+ call_count = call_count + e->count;
- if (e->caller->tp_first_run > max_tp_first_run)
- max_tp_first_run = e->caller->tp_first_run;
+ if (e->caller->tp_first_run > max_tp_first_run)
+ max_tp_first_run = e->caller->tp_first_run;
+ }
}
/* If time profile is missing, let assign the maximum that comes from
@@ -3239,9 +3223,9 @@ handle_missing_profiles (void)
if (!node->tp_first_run && max_tp_first_run)
node->tp_first_run = max_tp_first_run + 1;
- if (call_count
+ if (call_count > 0
&& fn && fn->cfg
- && (call_count * unlikely_count_fraction >= profile_info->runs))
+ && (call_count.apply_scale (unlikely_count_fraction, 1) >= profile_info->runs))
{
drop_profile (node, call_count);
worklist.safe_push (node);
@@ -3265,7 +3249,7 @@ handle_missing_profiles (void)
if (DECL_COMDAT (callee->decl) && fn && fn->cfg
&& profile_status_for_fn (fn) == PROFILE_READ)
{
- drop_profile (node, 0);
+ drop_profile (node, profile_count::zero ());
worklist.safe_push (callee);
}
}
@@ -3275,26 +3259,31 @@ handle_missing_profiles (void)
/* Convert counts measured by profile driven feedback to frequencies.
Return nonzero iff there was any nonzero execution count. */
-int
+bool
counts_to_freqs (void)
{
- gcov_type count_max, true_count_max = 0;
+ gcov_type count_max;
+ profile_count true_count_max = profile_count::zero ();
basic_block bb;
/* Don't overwrite the estimated frequencies when the profile for
the function is missing. We may drop this function PROFILE_GUESSED
later in drop_profile (). */
- if (!flag_auto_profile && !ENTRY_BLOCK_PTR_FOR_FN (cfun)->count)
+ if (!ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.initialized_p ()
+ || ENTRY_BLOCK_PTR_FOR_FN (cfun)->count == profile_count::zero ())
return 0;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
- true_count_max = MAX (bb->count, true_count_max);
+ if (bb->count > true_count_max)
+ true_count_max = bb->count;
+
+ count_max = MAX (true_count_max.to_gcov_type (), 1);
- count_max = MAX (true_count_max, 1);
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
- bb->frequency = (bb->count * BB_FREQ_MAX + count_max / 2) / count_max;
+ if (bb->count.initialized_p ())
+ bb->frequency = RDIV (bb->count.to_gcov_type () * BB_FREQ_MAX, count_max);
- return true_count_max;
+ return !(true_count_max == profile_count::zero ());
}
/* Return true if function is likely to be expensive, so there is no point to
@@ -3657,14 +3646,15 @@ rebuild_frequencies (void)
which may also lead to frequencies incorrectly reduced to 0. There
is less precision in the probabilities, so we only do this for small
max counts. */
- gcov_type count_max = 0;
+ profile_count count_max = profile_count::zero ();
basic_block bb;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
- count_max = MAX (bb->count, count_max);
+ if (bb->count > count_max)
+ count_max = bb->count;
if (profile_status_for_fn (cfun) == PROFILE_GUESSED
|| (!flag_auto_profile && profile_status_for_fn (cfun) == PROFILE_READ
- && count_max < REG_BR_PROB_BASE/10))
+ && count_max < REG_BR_PROB_BASE / 10))
{
loop_optimizer_init (0);
add_noreturn_fake_exit_edges ();
@@ -3725,23 +3715,23 @@ report_predictor_hitrates (void)
void
force_edge_cold (edge e, bool impossible)
{
- gcov_type count_sum = 0;
+ profile_count count_sum = profile_count::zero ();
int prob_sum = 0;
edge_iterator ei;
edge e2;
- gcov_type old_count = e->count;
+ profile_count old_count = e->count;
int old_probability = e->probability;
- gcov_type gcov_scale = REG_BR_PROB_BASE;
int prob_scale = REG_BR_PROB_BASE;
/* If edge is already improbably or cold, just return. */
if (e->probability <= (impossible ? PROB_VERY_UNLIKELY : 0)
- && (!impossible || !e->count))
+ && (!impossible || e->count == profile_count::zero ()))
return;
FOR_EACH_EDGE (e2, ei, e->src->succs)
if (e2 != e)
{
- count_sum += e2->count;
+ if (e2->count.initialized_p ())
+ count_sum += e2->count;
prob_sum += e2->probability;
}
@@ -3751,14 +3741,13 @@ force_edge_cold (edge e, bool impossible)
{
e->probability
= MIN (e->probability, impossible ? 0 : PROB_VERY_UNLIKELY);
+ if (impossible)
+ e->count = profile_count::zero ();
if (old_probability)
- e->count = RDIV (e->count * e->probability, old_probability);
+ e->count = e->count.apply_scale (e->probability, old_probability);
else
- e->count = MIN (e->count, impossible ? 0 : 1);
+ e->count = e->count.apply_scale (1, REG_BR_PROB_BASE);
- if (count_sum)
- gcov_scale = RDIV ((count_sum + old_count - e->count) * REG_BR_PROB_BASE,
- count_sum);
prob_scale = RDIV ((REG_BR_PROB_BASE - e->probability) * REG_BR_PROB_BASE,
prob_sum);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3766,10 +3755,12 @@ force_edge_cold (edge e, bool impossible)
"probability to other edges.\n",
e->src->index, e->dest->index,
impossible ? "impossible" : "cold");
+ profile_count count_sum2 = count_sum + old_count - e->count;
FOR_EACH_EDGE (e2, ei, e->src->succs)
if (e2 != e)
{
- e2->count = RDIV (e2->count * gcov_scale, REG_BR_PROB_BASE);
+ if (count_sum > 0)
+ e2->count.apply_scale (count_sum2, count_sum);
e2->probability = RDIV (e2->probability * prob_scale,
REG_BR_PROB_BASE);
}
@@ -3785,16 +3776,19 @@ force_edge_cold (edge e, bool impossible)
This in general is difficult task to do, but handle special case when
BB has only one predecestor. This is common case when we are updating
after loop transforms. */
- if (!prob_sum && !count_sum && single_pred_p (e->src)
- && e->src->frequency > (impossible ? 0 : 1))
+ if (!prob_sum && count_sum == profile_count::zero ()
+ && single_pred_p (e->src) && e->src->frequency > (impossible ? 0 : 1))
{
int old_frequency = e->src->frequency;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Making bb %i %s.\n", e->src->index,
impossible ? "impossible" : "cold");
e->src->frequency = MIN (e->src->frequency, impossible ? 0 : 1);
- e->src->count = e->count = RDIV (e->src->count * e->src->frequency,
- old_frequency);
+ if (impossible)
+ e->src->count = e->count = profile_count::zero ();
+ else
+ e->src->count = e->count = e->count.apply_scale (e->src->frequency,
+ old_frequency);
force_edge_cold (single_pred_edge (e->src), impossible);
}
else if (dump_file && (dump_flags & TDF_DETAILS)