* Convert profile probabilities to new type
@ 2017-06-29 12:28 Jan Hubicka
2017-06-29 18:28 ` Christophe Lyon
` (4 more replies)
0 siblings, 5 replies; 19+ messages in thread
From: Jan Hubicka @ 2017-06-29 12:28 UTC (permalink / raw)
To: gcc-patches, jakub, mliska
Hi,
this is second step of the profile maintenance revamp. It implements
profile_probability type which is pretty much symmetric to profile_count
except that it implements fixed point arithmetics for values 0...1.
It is used to maintain probabilities of edges out of basic blocks.
In addition it tracks information about quality of the estimate which can
later be used for optimization.
Large patch is symmetric just updating existing code to new API. Because
probabilities are not just integers, some changes are needed. In particular
1) I have introduced names for common probabilities, which corresponds to
PROB_* macros. A lot of code however used explicit calcuation of
REG_BR_PROB_BASE.
2) There is now difference between probability of 0 and uninitialized
probability. There are a lot of places where we forget to set edge
probabilities after updating CFG which originally went unnoticed.
Now we can see ICE when such missing probabilities are intorudced between
profile estimation and inlning. Rest of code now accepts missing
probabilities and I will implement checker and fix bugs incremetnally.
Before inlining however I need probabilities to exist because inliner
redoes probability->frequency computation and for that one can not have
missing info.
This noticed few erorrs which I knew how to fix, and some I added fixmes
for:
omp-simd-clone.c:
- in simd_clone_adjust for edge incr_bb->new_exit_bb
tree-parloops.c:
- in create_parallel_loop for guard edge
- in oacc_entry_exit_single_gang for e3 edge.
tree-ssa-loop-split.c
- loop profile updating seems just completely wrong here.
I the first two files I would welcome some suggestions what to do.
To make conversion possible, sometimes I still go to old representation of
counts via to_reg_br_prob_base/from_reg_br_prob_base. I plan to eliminate most
of uses of this incrementaly (there are 60 of them).
Bootstrapped/regtested x86_64-linux, will commit it later today after bit
more testing.
Honza
2017-06-28 Jan Hubicka <hubicka@ucw.cz>
* asan.c (asan_emit_stack_protection): Update.
(create_cond_insert_point): Update.
* auto-profile.c (afdo_propagate_circuit): Update.
* basic-block.h (struct edge_def): Turn probability to
profile_probability.
(EDGE_FREQUENCY): Update.
* bb-reorder.c (find_traces_1_round): Update.
(better_edge_p): Update.
(sanitize_hot_paths): Update.
* cfg.c (unchecked_make_edge): Initialize probability to uninitialized.
(make_single_succ_edge): Update.
(check_bb_profile): Update.
(dump_edge_info): Update.
(update_bb_profile_for_threading): Update.
* cfganal.c (connect_infinite_loops_to_exit): Initialize new edge
probabilitycount to 0.
* cfgbuild.c (compute_outgoing_frequencies): Update.
* cfgcleanup.c (try_forward_edges): Update.
(outgoing_edges_match): Update.
(try_crossjump_to_edge): Update.
* cfgexpand.c (expand_gimple_cond): Update make_single_succ_edge.
(expand_gimple_tailcall): Update.
(construct_init_block): Use make_single_succ_edge.
(construct_exit_block): Use make_single_succ_edge.
* cfghooks.c (verify_flow_info): Update.
(redirect_edge_succ_nodup): Update.
(split_edge): Update.
(account_profile_record): Update.
* cfgloopanal.c (single_likely_exit): Update.
* cfgloopmanip.c (scale_loop_profile): Update.
(set_zero_probability): Remove.
(duplicate_loop_to_header_edge): Update.
* cfgloopmanip.h (loop_version): Update prototype.
* cfgrtl.c (try_redirect_by_replacing_jump): Update.
(force_nonfallthru_and_redirect): Update.
(update_br_prob_note): Update.
(rtl_verify_edges): Update.
(purge_dead_edges): Update.
(rtl_lv_add_condition_to_bb): Update.
* cgraph.c: (cgraph_edge::redirect_call_stmt_to_calle): Update.
* cgraphunit.c (init_lowered_empty_function): Update.
(cgraph_node::expand_thunk): Update.
* cilk-common.c: Include profile-count.h
* dojump.c (inv): Remove.
(jumpifnot): Update.
(jumpifnot_1): Update.
(do_jump_1): Update.
(do_jump): Update.
(do_jump_by_parts_greater_rtx): Update.
(do_compare_rtx_and_jump): Update.
* dojump.h (jumpifnot, jumpifnot_1, jumpif_1, jumpif, do_jump,
do_jump_1. do_compare_rtx_and_jump): Update prototype.
* dwarf2cfi.c: Include profile-count.h
* except.c (dw2_build_landing_pads): Use make_single_succ_edge.
(sjlj_emit_dispatch_table): Likewise.
* explow.c: Include profile-count.h
* expmed.c (emit_store_flag_force): Update.
(do_cmp_and_jump): Update.
* expr.c (compare_by_pieces_d::generate): Update.
(compare_by_pieces_d::finish_mode): Update.
(emit_block_move_via_loop): Update.
(store_expr_with_bounds): Update.
(store_constructor): Update.
(expand_expr_real_2): Update.
(expand_expr_real_1): Update.
* expr.h (try_casesi, try_tablejump): Update prototypes.
* gimple-pretty-print.c (dump_probability): Update.
(dump_profile): New.
(dump_gimple_label): Update.
(dump_gimple_bb_header): Update.
* graph.c (draw_cfg_node_succ_edges): Update.
* hsa-gen.c (convert_switch_statements): Update.
* ifcvt.c (cheap_bb_rtx_cost_p): Update.
(find_if_case_1): Update.
(find_if_case_2): Update.
* internal-fn.c (expand_arith_overflow_result_store): Update.
(expand_addsub_overflow): Update.
(expand_neg_overflow): Update.
(expand_mul_overflow): Update.
(expand_vector_ubsan_overflow): Update.
* ipa-cp.c (good_cloning_opportunity_p): Update.
* ipa-split.c (split_function): Use make_single_succ_edge.
* ipa-utils.c (ipa_merge_profiles): Update.
* loop-doloop.c (add_test): Update.
(doloop_modify): Update.
* loop-unroll.c (compare_and_jump_seq): Update.
(unroll_loop_runtime_iterations): Update.
* lra-constraints.c (lra_inheritance): Update.
* lto-streamer-in.c (input_cfg): Update.
* lto-streamer-out.c (output_cfg): Update.
* mcf.c (adjust_cfg_counts): Update.
* modulo-sched.c (sms_schedule): Update.
* omp-expand.c (expand_omp_for_init_counts): Update.
(extract_omp_for_update_vars): Update.
(expand_omp_ordered_sink): Update.
(expand_omp_for_ordered_loops): Update.
(expand_omp_for_generic): Update.
(expand_omp_for_static_nochunk): Update.
(expand_omp_for_static_chunk): Update.
(expand_cilk_for): Update.
(expand_omp_simd): Update.
(expand_omp_taskloop_for_outer): Update.
(expand_omp_taskloop_for_inner): Update.
* omp-simd-clone.c (simd_clone_adjust): Update.
* optabs.c (expand_doubleword_shift): Update.
(expand_abs): Update.
(emit_cmp_and_jump_insn_1): Update.
(expand_compare_and_swap_loop): Update.
* optabs.h (emit_cmp_and_jump_insns): Update prototype.
* predict.c (predictable_edge_p): Update.
(edge_probability_reliable_p): Update.
(set_even_probabilities): Update.
(combine_predictions_for_insn): Update.
(combine_predictions_for_bb): Update.
(propagate_freq): Update.
(estimate_bb_frequencies): Update.
(force_edge_cold): Update.
* profile-count.c (profile_count::dump): Add missing space into dump.
(profile_count::debug): Add newline.
(profile_count::differs_from_p): Explicitly convert to unsigned.
(profile_count::stream_in): Update.
(profile_probability::dump): New member function.
(profile_probability::debug): New member function.
(profile_probability::differs_from_p): New member function.
(profile_probability::differs_lot_from_p): New member function.
(profile_probability::stream_in): New member function.
(profile_probability::stream_out): New member function.
* profile-count.h (profile_count_quality): Rename to ...
(profile_quality): ... this one.
(profile_probability): New.
(profile_count): Update.
* profile.c (compute_branch_probabilities): Update.
* recog.c (peep2_attempt): Update.
* sched-ebb.c (schedule_ebbs): Update.
* sched-rgn.c (find_single_block_region): Update.
(compute_dom_prob_ps): Update.
(schedule_region): Update.
* sel-sched-ir.c (compute_succs_info): Update.
* stmt.c (struct case_node): Update.
(do_jump_if_equal): Update.
(get_outgoing_edge_probs): Update.
(conditional_probability): Update.
(emit_case_dispatch_table): Update.
(expand_case): Update.
(expand_sjlj_dispatch_table): Update.
(emit_case_nodes): Update.
* targhooks.c: Update.
* tracer.c (better_p): Update.
(find_best_successor): Update.
* trans-mem.c (expand_transaction): Update.
* tree-call-cdce.c: Update.
* tree-cfg.c (gimple_split_edge): Upate.
(move_sese_region_to_fn): Upate.
* tree-cfgcleanup.c (cleanup_control_expr_graph): Upate.
* tree-eh.c (lower_resx): Upate.
(cleanup_empty_eh_move_lp): Upate.
* tree-if-conv.c (version_loop_for_if_conversion): Update.
* tree-inline.c (copy_edges_for_bb): Update.
(copy_cfg_body): Update.
* tree-parloops.c (gen_parallel_loop): Update.
* tree-profile.c (gimple_gen_ic_func_profiler): Update.
(gimple_gen_time_profiler): Update.
* tree-ssa-dce.c (remove_dead_stmt): Update.
* tree-ssa-ifcombine.c (update_profile_after_ifcombine): Update.
* tree-ssa-loop-im.c (execute_sm_if_changed): Update.
* tree-ssa-loop-ivcanon.c (remove_exits_and_undefined_stmts): Update.
(unloop_loops): Update.
(try_peel_loop): Update.
* tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update.
* tree-ssa-loop-split.c (connect_loops): Update.
(split_loop): Update.
* tree-ssa-loop-unswitch.c (tree_unswitch_loop): Update.
(hoist_guard): Update.
* tree-ssa-phionlycprop.c (propagate_rhs_into_lhs): Update.
* tree-ssa-phiopt.c (replace_phi_edge_with_variable): Update.
(value_replacement): Update.
* tree-ssa-reassoc.c (branch_fixup): Update.
* tree-ssa-tail-merge.c (replace_block_by): Update.
* tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges): Update.
(create_edge_and_update_destination_phis): Update.
(compute_path_counts): Update.
(recompute_probabilities): Update.
(update_joiner_offpath_counts): Update.
(freqs_to_counts_path): Update.
(duplicate_thread_path): Update.
* tree-switch-conversion.c (hoist_edge_and_branch_if_true): Update.
(struct switch_conv_info): Update.
(gen_inbound_check): Update.
* tree-vect-loop-manip.c (slpeel_add_loop_guard): Update.
(vect_do_peeling): Update.
(vect_loop_versioning): Update.
* tree-vect-loop.c (scale_profile_for_vect_loop): Update.
(optimize_mask_stores): Update.
* ubsan.c (ubsan_expand_null_ifn): Update.
* value-prof.c (gimple_divmod_fixed_value): Update.
(gimple_divmod_fixed_value_transform): Update.
(gimple_mod_pow2): Update.
(gimple_mod_pow2_value_transform): Update.
(gimple_mod_subtract): Update.
(gimple_mod_subtract_transform): Update.
(gimple_ic): Update.
(gimple_stringop_fixed_value): Update.
(gimple_stringops_transform): Update.
* value-prof.h: Update.
Index: asan.c
===================================================================
--- asan.c (revision 249769)
+++ asan.c (working copy)
@@ -1145,9 +1145,9 @@ asan_emit_stack_protection (rtx base, rt
emit_move_insn (orig_base, base);
ret = expand_normal (asan_detect_stack_use_after_return);
lab = gen_label_rtx ();
- int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
- VOIDmode, 0, lab, very_likely);
+ VOIDmode, 0, lab,
+ profile_probability::very_likely ());
snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
use_after_return_class);
ret = init_one_libfunc (buf);
@@ -1158,9 +1158,9 @@ asan_emit_stack_protection (rtx base, rt
/* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
and NULL otherwise. Check RET value is NULL here and jump over the
BASE reassignment in this case. Otherwise, reassign BASE to RET. */
- int very_unlikely = REG_BR_PROB_BASE / 2000 - 1;
emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
- VOIDmode, 0, lab, very_unlikely);
+ VOIDmode, 0, lab,
+ profile_probability:: very_unlikely ());
ret = convert_memory_address (Pmode, ret);
emit_move_insn (base, ret);
emit_label (lab);
@@ -1255,9 +1255,9 @@ asan_emit_stack_protection (rtx base, rt
{
rtx_code_label *lab2 = gen_label_rtx ();
char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
- int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
- VOIDmode, 0, lab2, very_likely);
+ VOIDmode, 0, lab2,
+ profile_probability::very_likely ());
shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
set_mem_alias_set (shadow_mem, asan_shadow_set);
mem = gen_rtx_MEM (ptr_mode, base);
@@ -1588,7 +1588,8 @@ create_cond_insert_point (gimple_stmt_it
= then_more_likely_p
? PROB_VERY_UNLIKELY
: PROB_ALWAYS - PROB_VERY_UNLIKELY;
- e->probability = PROB_ALWAYS - fallthrough_probability;
+ e->probability = profile_probability::from_reg_br_prob_base
+ (PROB_ALWAYS - fallthrough_probability);
if (create_then_fallthru_edge)
make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
@@ -1596,7 +1597,8 @@ create_cond_insert_point (gimple_stmt_it
e = find_edge (cond_bb, fallthru_bb);
e->flags = EDGE_FALSE_VALUE;
e->count = cond_bb->count;
- e->probability = fallthrough_probability;
+ e->probability
+ = profile_probability::from_reg_br_prob_base (fallthrough_probability);
/* Update dominance info for the newly created then_bb; note that
fallthru_bb's dominance info has already been updated by
Index: auto-profile.c
===================================================================
--- auto-profile.c (revision 249769)
+++ auto-profile.c (working copy)
@@ -1346,9 +1346,10 @@ afdo_propagate_circuit (const bb_set &an
continue;
total++;
only_one = ep;
- if (e->probability == 0 && !is_edge_annotated (ep, *annotated_edge))
+ if (!e->probability.initialized_p ()
+ && !is_edge_annotated (ep, *annotated_edge))
{
- ep->probability = 0;
+ ep->probability = profile_probability::never ();
ep->count = profile_count::zero ();
set_edge_annotated (ep, annotated_edge);
}
Index: basic-block.h
===================================================================
--- basic-block.h (revision 249769)
+++ basic-block.h (working copy)
@@ -45,7 +45,7 @@ struct GTY((user)) edge_def {
unsigned int dest_idx;
int flags; /* see cfg-flags.def */
- int probability; /* biased by REG_BR_PROB_BASE */
+ profile_probability probability;
profile_count count; /* Expected number of executions calculated
in profile.c */
};
@@ -300,8 +300,7 @@ enum cfg_bb_flags
? EDGE_SUCC ((bb), 1) : EDGE_SUCC ((bb), 0))
/* Return expected execution frequency of the edge E. */
-#define EDGE_FREQUENCY(e) RDIV ((e)->src->frequency * (e)->probability, \
- REG_BR_PROB_BASE)
+#define EDGE_FREQUENCY(e) e->probability.apply (e->src->frequency)
/* Compute a scale factor (or probability) suitable for scaling of
gcov_type values via apply_probability() and apply_scale(). */
Index: bb-reorder.c
===================================================================
--- bb-reorder.c (revision 249769)
+++ bb-reorder.c (working copy)
@@ -206,8 +206,8 @@ static void find_traces_1_round (int, in
int, bb_heap_t **, int);
static basic_block copy_bb (basic_block, edge, basic_block, int);
static long bb_to_key (basic_block);
-static bool better_edge_p (const_basic_block, const_edge, int, int, int, int,
- const_edge);
+static bool better_edge_p (const_basic_block, const_edge, profile_probability,
+ int, profile_probability, int, const_edge);
static bool connect_better_edge_p (const_edge, bool, int, const_edge,
struct trace *);
static void connect_traces (int, struct trace *);
@@ -513,11 +513,12 @@ find_traces_1_round (int branch_th, int
do
{
- int prob, freq;
+ profile_probability prob;
+ int freq;
bool ends_in_call;
/* The probability and frequency of the best edge. */
- int best_prob = INT_MIN / 2;
+ profile_probability best_prob = profile_probability::uninitialized ();
int best_freq = INT_MIN / 2;
best_edge = NULL;
@@ -565,7 +566,9 @@ find_traces_1_round (int branch_th, int
successor (i.e. it is unsuitable successor). When optimizing
for size, ignore the probability and frequency. */
if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX)
- || ((prob < branch_th || EDGE_FREQUENCY (e) < exec_th
+ || !prob.initialized_p ()
+ || ((prob.to_reg_br_prob_base () < branch_th
+ || EDGE_FREQUENCY (e) < exec_th
|| e->count < count_th) && (!for_size)))
continue;
@@ -648,7 +651,9 @@ find_traces_1_round (int branch_th, int
if (!(e->flags & EDGE_CAN_FALLTHRU)
|| (e->flags & EDGE_COMPLEX)
- || prob < branch_th || freq < exec_th
+ || !prob.initialized_p ()
+ || prob.to_reg_br_prob_base () < branch_th
+ || freq < exec_th
|| e->count < count_th)
{
/* When partitioning hot/cold basic blocks, make sure
@@ -936,14 +941,15 @@ bb_to_key (basic_block bb)
BEST_PROB; similarly for frequency. */
static bool
-better_edge_p (const_basic_block bb, const_edge e, int prob, int freq,
- int best_prob, int best_freq, const_edge cur_best_edge)
+better_edge_p (const_basic_block bb, const_edge e, profile_probability prob,
+ int freq, profile_probability best_prob, int best_freq,
+ const_edge cur_best_edge)
{
bool is_better_edge;
/* The BEST_* values do not have to be best, but can be a bit smaller than
maximum values. */
- int diff_prob = best_prob / 10;
+ profile_probability diff_prob = best_prob.apply_scale (1, 10);
int diff_freq = best_freq / 10;
/* The smaller one is better to keep the original order. */
@@ -1494,7 +1500,8 @@ sanitize_hot_paths (bool walk_up, unsign
vec<edge, va_gc> *edges = walk_up ? bb->preds : bb->succs;
edge e;
edge_iterator ei;
- int highest_probability = 0;
+ profile_probability highest_probability
+ = profile_probability::uninitialized ();
int highest_freq = 0;
profile_count highest_count = profile_count::uninitialized ();
bool found = false;
@@ -1517,12 +1524,13 @@ sanitize_hot_paths (bool walk_up, unsign
/* The following loop will look for the hottest edge via
the edge count, if it is non-zero, then fallback to the edge
frequency and finally the edge probability. */
- if (e->count > highest_count)
+ if (!highest_count.initialized_p () || e->count > highest_count)
highest_count = e->count;
int edge_freq = EDGE_FREQUENCY (e);
if (edge_freq > highest_freq)
highest_freq = edge_freq;
- if (e->probability > highest_probability)
+ if (!highest_probability.initialized_p ()
+ || e->probability > highest_probability)
highest_probability = e->probability;
}
Index: cfg.c
===================================================================
--- cfg.c (revision 249769)
+++ cfg.c (working copy)
@@ -264,6 +264,7 @@ unchecked_make_edge (basic_block src, ba
n_edges_for_fn (cfun)++;
e->count = profile_count::uninitialized ();
+ e->probability = profile_probability::uninitialized ();
e->src = src;
e->dest = dst;
e->flags = flags;
@@ -332,7 +333,7 @@ make_single_succ_edge (basic_block src,
{
edge e = make_edge (src, dest, flags);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = src->count;
return e;
}
@@ -400,7 +401,6 @@ static void
check_bb_profile (basic_block bb, FILE * file, int indent)
{
edge e;
- int sum = 0;
edge_iterator ei;
struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
char *s_indent = (char *) alloca ((size_t) indent + 1);
@@ -413,21 +413,38 @@ check_bb_profile (basic_block bb, FILE *
if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
{
bool found = false;
+ profile_probability sum = profile_probability::never ();
+ int isum = 0;
+
FOR_EACH_EDGE (e, ei, bb->succs)
{
- if (!(e->flags & EDGE_EH))
+ if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
found = true;
sum += e->probability;
+ if (e->probability.initialized_p ())
+ isum += e->probability.to_reg_br_prob_base ();
}
/* Only report mismatches for non-EH control flow. If there are only EH
edges it means that the BB ends by noreturn call. Here the control
flow may just terminate. */
if (found)
{
- if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
- fprintf (file,
- ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
- s_indent, sum * 100.0 / REG_BR_PROB_BASE);
+ if (sum.differs_from_p (profile_probability::always ()))
+ {
+ fprintf (file,
+ ";; %sInvalid sum of outgoing probabilities ",
+ s_indent);
+ sum.dump (file);
+ fprintf (file, "\n");
+ }
+ /* Probabilities caps to 100% and thus the previous test will never
+ fire if the sum of probabilities is too large. */
+ else if (isum > REG_BR_PROB_BASE + 100)
+ {
+ fprintf (file,
+ ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
+ s_indent, isum * 100.0 / REG_BR_PROB_BASE);
+ }
profile_count lsum = profile_count::zero ();
FOR_EACH_EDGE (e, ei, bb->succs)
lsum += e->count;
@@ -442,9 +459,9 @@ check_bb_profile (basic_block bb, FILE *
}
}
}
- if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
+ if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
{
- sum = 0;
+ int sum = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
sum += EDGE_FREQUENCY (e);
if (abs (sum - bb->frequency) > 100)
@@ -498,8 +515,12 @@ dump_edge_info (FILE *file, edge e, dump
else
fprintf (file, " %d", side->index);
- if (e->probability && do_details)
- fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
+ if (e->probability.initialized_p () && do_details)
+ {
+ fprintf (file, " [");
+ e->probability.dump (file);
+ fprintf (file, "] ");
+ }
if (e->count.initialized_p () && do_details)
{
@@ -860,7 +881,7 @@ update_bb_profile_for_threading (basic_b
profile_count count, edge taken_edge)
{
edge c;
- int prob;
+ profile_probability prob;
edge_iterator ei;
if (bb->count < count)
@@ -878,59 +899,51 @@ update_bb_profile_for_threading (basic_b
/* Compute the probability of TAKEN_EDGE being reached via threaded edge.
Watch for overflows. */
if (bb->frequency)
- prob = GCOV_COMPUTE_SCALE (edge_frequency, bb->frequency);
+ /* FIXME: We should get edge frequency as count. */
+ prob = profile_probability::probability_in_gcov_type
+ (edge_frequency, bb->frequency);
else
- prob = 0;
+ prob = profile_probability::never ();
if (prob > taken_edge->probability)
{
if (dump_file)
- fprintf (dump_file, "Jump threading proved probability of edge "
- "%i->%i too small (it is %i, should be %i).\n",
- taken_edge->src->index, taken_edge->dest->index,
- taken_edge->probability, prob);
- prob = taken_edge->probability * 6 / 8;
+ {
+ fprintf (dump_file, "Jump threading proved probability of edge "
+ "%i->%i too small (it is ",
+ taken_edge->src->index, taken_edge->dest->index);
+ taken_edge->probability.dump (dump_file);
+ fprintf (dump_file, " should be ");
+ prob.dump (dump_file);
+ fprintf (dump_file, ")\n");
+ }
+ prob = taken_edge->probability.apply_scale (6, 8);
}
/* Now rescale the probabilities. */
taken_edge->probability -= prob;
- prob = REG_BR_PROB_BASE - prob;
- if (prob <= 0)
+ prob = prob.invert ();
+ if (prob == profile_probability::never ())
{
if (dump_file)
fprintf (dump_file, "Edge frequencies of bb %i has been reset, "
"frequency of block should end up being 0, it is %i\n",
bb->index, bb->frequency);
- EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (bb, 0)->probability = profile_probability::guessed_always ();
ei = ei_start (bb->succs);
ei_next (&ei);
for (; (c = ei_safe_edge (ei)); ei_next (&ei))
- c->probability = 0;
+ c->probability = profile_probability::guessed_never ();
}
- else if (prob != REG_BR_PROB_BASE)
+ else if (!(prob == profile_probability::always ()))
{
- int scale = RDIV (65536 * REG_BR_PROB_BASE, prob);
-
FOR_EACH_EDGE (c, ei, bb->succs)
- {
- /* Protect from overflow due to additional scaling. */
- if (c->probability > prob)
- c->probability = REG_BR_PROB_BASE;
- else
- {
- c->probability = RDIV (c->probability * scale, 65536);
- if (c->probability > REG_BR_PROB_BASE)
- c->probability = REG_BR_PROB_BASE;
- }
- }
+ c->probability /= prob;
}
gcc_assert (bb == taken_edge->src);
- if (taken_edge->count < count)
- {
- if (dump_file)
- fprintf (dump_file, "edge %i->%i count became negative after threading",
- taken_edge->src->index, taken_edge->dest->index);
- }
+ if (dump_file && taken_edge->count < count)
+ fprintf (dump_file, "edge %i->%i count became negative after threading",
+ taken_edge->src->index, taken_edge->dest->index);
taken_edge->count -= count;
}
Index: cfganal.c
===================================================================
--- cfganal.c (revision 249769)
+++ cfganal.c (working copy)
@@ -610,7 +610,10 @@ connect_infinite_loops_to_exit (void)
break;
basic_block deadend_block = dfs_find_deadend (unvisited_block);
- make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
+ edge e = make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FAKE);
+ e->count = profile_count::zero ();
+ e->probability = profile_probability::never ();
dfs.add_bb (deadend_block);
}
}
Index: cfgbuild.c
===================================================================
--- cfgbuild.c (revision 249769)
+++ cfgbuild.c (working copy)
@@ -545,10 +545,13 @@ compute_outgoing_frequencies (basic_bloc
{
probability = XINT (note, 0);
e = BRANCH_EDGE (b);
- e->probability = probability;
+ e->probability
+ = profile_probability::from_reg_br_prob_base (probability);
e->count = b->count.apply_probability (probability);
f = FALLTHRU_EDGE (b);
- f->probability = REG_BR_PROB_BASE - probability;
+ f->probability
+ = profile_probability::from_reg_br_prob_base (REG_BR_PROB_BASE
+ - probability);
f->count = b->count - e->count;
return;
}
@@ -560,7 +563,7 @@ compute_outgoing_frequencies (basic_bloc
else if (single_succ_p (b))
{
e = single_succ_edge (b);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = b->count;
return;
}
@@ -656,7 +659,8 @@ find_many_sub_basic_blocks (sbitmap bloc
}
else
uninitialized_src = true;
- bb->frequency += EDGE_FREQUENCY (e);
+ if (e->probability.initialized_p ())
+ bb->frequency += EDGE_FREQUENCY (e);
}
/* When some edges are missing with read profile, this is
most likely because RTL expansion introduced loop.
Index: cfgcleanup.c
===================================================================
--- cfgcleanup.c (revision 249769)
+++ cfgcleanup.c (working copy)
@@ -559,7 +559,7 @@ try_forward_edges (int mode, basic_block
{
/* Save the values now, as the edge may get removed. */
profile_count edge_count = e->count;
- int edge_probability = e->probability;
+ profile_probability edge_probability = e->probability;
int edge_frequency;
int n = 0;
@@ -585,7 +585,7 @@ try_forward_edges (int mode, basic_block
/* We successfully forwarded the edge. Now update profile
data: for each edge we traversed in the chain, remove
the original edge's execution count. */
- edge_frequency = apply_probability (b->frequency, edge_probability);
+ edge_frequency = edge_probability.apply (b->frequency);
do
{
@@ -1710,24 +1710,28 @@ outgoing_edges_match (int mode, basic_bl
&& optimize_bb_for_speed_p (bb1)
&& optimize_bb_for_speed_p (bb2))
{
- int prob2;
+ profile_probability prob2;
if (b1->dest == b2->dest)
prob2 = b2->probability;
else
/* Do not use f2 probability as f2 may be forwarded. */
- prob2 = REG_BR_PROB_BASE - b2->probability;
+ prob2 = b2->probability.invert ();
/* Fail if the difference in probabilities is greater than 50%.
This rules out two well-predicted branches with opposite
outcomes. */
- if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
+ if (b1->probability.differs_lot_from_p (prob2))
{
if (dump_file)
- fprintf (dump_file,
- "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
- bb1->index, bb2->index, b1->probability, prob2);
-
+ {
+ fprintf (dump_file,
+ "Outcomes of branch in bb %i and %i differ too"
+ " much (", bb1->index, bb2->index);
+ b1->probability.dump (dump_file);
+ prob2.dump (dump_file);
+ fprintf (dump_file, ")\n");
+ }
return false;
}
}
@@ -2149,12 +2153,9 @@ try_crossjump_to_edge (int mode, edge e1
}
if (!redirect_edges_to->frequency && !src1->frequency)
- s->probability = (s->probability + s2->probability) / 2;
- else
- s->probability
- = ((s->probability * redirect_edges_to->frequency +
- s2->probability * src1->frequency)
- / (redirect_edges_to->frequency + src1->frequency));
+ s->probability = s->probability.combine_with_freq
+ (redirect_edges_to->frequency,
+ s2->probability, src1->frequency);
}
/* Adjust count and frequency for the block. An earlier jump
Index: cfgexpand.c
===================================================================
--- cfgexpand.c (revision 249769)
+++ cfgexpand.c (working copy)
@@ -2389,7 +2389,6 @@ static basic_block
expand_gimple_cond (basic_block bb, gcond *stmt)
{
basic_block new_bb, dest;
- edge new_edge;
edge true_edge;
edge false_edge;
rtx_insn *last2, *last;
@@ -2508,9 +2507,7 @@ expand_gimple_cond (basic_block bb, gcon
if (loop->latch == bb
&& loop->header == dest)
loop->latch = new_bb;
- new_edge = make_edge (new_bb, dest, 0);
- new_edge->probability = REG_BR_PROB_BASE;
- new_edge->count = new_bb->count;
+ make_single_succ_edge (new_bb, dest, 0);
if (BARRIER_P (BB_END (new_bb)))
BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
update_bb_for_insn (new_bb);
@@ -3782,7 +3779,7 @@ expand_gimple_tailcall (basic_block bb,
rtx_insn *last2, *last;
edge e;
edge_iterator ei;
- int probability;
+ profile_probability probability;
last2 = last = expand_gimple_stmt (stmt);
@@ -3807,7 +3804,7 @@ expand_gimple_tailcall (basic_block bb,
all edges here, or redirecting the existing fallthru edge to
the exit block. */
- probability = 0;
+ probability = profile_probability::never ();
profile_count count = profile_count::zero ();
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
@@ -5833,12 +5830,11 @@ construct_init_block (void)
{
first_block = e->dest;
redirect_edge_succ (e, init_block);
- e = make_edge (init_block, first_block, flags);
+ e = make_single_succ_edge (init_block, first_block, flags);
}
else
- e = make_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+ e = make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FALLTHRU);
update_bb_for_insn (init_block);
return init_block;
@@ -5918,9 +5914,8 @@ construct_exit_block (void)
ix++;
}
- e = make_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = EXIT_BLOCK_PTR_FOR_FN (cfun)->count;
+ e = make_single_succ_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FALLTHRU);
FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
if (e2 != e)
{
Index: cfghooks.c
===================================================================
--- cfghooks.c (revision 249769)
+++ cfghooks.c (working copy)
@@ -160,10 +160,10 @@ verify_flow_info (void)
e->src->index, e->dest->index);
err = 1;
}
- if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
+ if (!e->probability.verify ())
{
- error ("verify_flow_info: Wrong probability of edge %i->%i %i",
- e->src->index, e->dest->index, e->probability);
+ error ("verify_flow_info: Wrong probability of edge %i->%i",
+ e->src->index, e->dest->index);
err = 1;
}
if (!e->count.verify ())
@@ -443,8 +443,6 @@ redirect_edge_succ_nodup (edge e, basic_
{
s->flags |= e->flags;
s->probability += e->probability;
- if (s->probability > REG_BR_PROB_BASE)
- s->probability = REG_BR_PROB_BASE;
s->count += e->count;
/* FIXME: This should be called via a hook and only for IR_GIMPLE. */
redirect_edge_var_map_dup (s, e);
@@ -640,7 +638,7 @@ split_edge (edge e)
ret = cfg_hooks->split_edge (e);
ret->count = count;
ret->frequency = freq;
- single_succ_edge (ret)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (ret)->probability = profile_probability::always ();
single_succ_edge (ret)->count = count;
if (irr)
@@ -1451,17 +1449,17 @@ account_profile_record (struct profile_r
basic_block bb;
edge_iterator ei;
edge e;
- int sum;
FOR_ALL_BB_FN (bb, cfun)
{
if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
&& profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
- sum = 0;
+ profile_probability sum = profile_probability::never ();
FOR_EACH_EDGE (e, ei, bb->succs)
sum += e->probability;
- if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
+ if (EDGE_COUNT (bb->succs)
+ && sum.differs_from_p (profile_probability::always ()))
record->num_mismatched_freq_out[after_pass]++;
profile_count lsum = profile_count::zero ();
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1472,7 +1470,7 @@ account_profile_record (struct profile_r
if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
&& profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
- sum = 0;
+ int sum = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
sum += EDGE_FREQUENCY (e);
if (abs (sum - bb->frequency) > 100
Index: cfgloopanal.c
===================================================================
--- cfgloopanal.c (revision 249769)
+++ cfgloopanal.c (working copy)
@@ -477,7 +477,7 @@ single_likely_exit (struct loop *loop)
reasons.
FIXME: Turn to likely_never_executed */
if ((profile_status_for_fn (cfun) != PROFILE_ABSENT
- && ex->probability < 5)
+ && ex->probability < profile_probability::from_reg_br_prob_base (5))
|| ex->count == profile_count::zero ())
continue;
if (!found)
Index: cfgloopmanip.c
===================================================================
--- cfgloopmanip.c (revision 249769)
+++ cfgloopmanip.c (working copy)
@@ -542,8 +542,9 @@ scale_loop_profile (struct loop *loop, i
/* Probability of exit must be 1/iterations. */
freq_delta = EDGE_FREQUENCY (e);
- e->probability = REG_BR_PROB_BASE / iteration_bound;
- other_e->probability = inverse_probability (e->probability);
+ e->probability = profile_probability::from_reg_br_prob_base
+ (REG_BR_PROB_BASE / iteration_bound);
+ other_e->probability = e->probability.invert ();
freq_delta -= EDGE_FREQUENCY (e);
/* Adjust counts accordingly. */
@@ -1101,43 +1102,6 @@ can_duplicate_loop_p (const struct loop
return ret;
}
-/* Sets probability and count of edge E to zero. The probability and count
- is redistributed evenly to the remaining edges coming from E->src. */
-
-static void
-set_zero_probability (edge e)
-{
- basic_block bb = e->src;
- edge_iterator ei;
- edge ae, last = NULL;
- unsigned n = EDGE_COUNT (bb->succs);
- profile_count cnt = e->count, cnt1;
- unsigned prob = e->probability, prob1;
-
- gcc_assert (n > 1);
- cnt1 = cnt.apply_scale (1, (n - 1));
- prob1 = prob / (n - 1);
-
- FOR_EACH_EDGE (ae, ei, bb->succs)
- {
- if (ae == e)
- continue;
-
- ae->probability += prob1;
- ae->count += cnt1;
- last = ae;
- }
-
- /* Move the rest to one of the edges. */
- last->probability += prob % (n - 1);
- /* TODO: Remove once we have fractional counts. */
- if (cnt.initialized_p ())
- last->count += profile_count::from_gcov_type (cnt.to_gcov_type () % (n - 1));
-
- e->probability = 0;
- e->count = profile_count::zero ();
-}
-
/* Duplicates body of LOOP to given edge E NDUPL times. Takes care of updating
loop structure and dominators. E's destination must be LOOP header for
this to work, i.e. it must be entry or latch edge of this loop; these are
@@ -1224,14 +1188,18 @@ duplicate_loop_to_header_edge (struct lo
prob_pass_wont_exit =
RDIV (REG_BR_PROB_BASE * (freq_le + freq_out_orig), freq_in);
- if (orig
- && REG_BR_PROB_BASE - orig->probability != 0)
+ if (orig && orig->probability.initialized_p ()
+ && !(orig->probability == profile_probability::always ()))
{
/* The blocks that are dominated by a removed exit edge ORIG have
frequencies scaled by this. */
- scale_after_exit
- = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
- REG_BR_PROB_BASE - orig->probability);
+ if (orig->probability.initialized_p ())
+ scale_after_exit
+ = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
+ REG_BR_PROB_BASE
+ - orig->probability.to_reg_br_prob_base ());
+ else
+ scale_after_exit = REG_BR_PROB_BASE;
bbs_to_scale = BITMAP_ALLOC (NULL);
for (i = 0; i < n; i++)
{
@@ -1387,7 +1355,7 @@ duplicate_loop_to_header_edge (struct lo
{
if (to_remove)
to_remove->safe_push (new_spec_edges[SE_ORIG]);
- set_zero_probability (new_spec_edges[SE_ORIG]);
+ force_edge_cold (new_spec_edges[SE_ORIG], true);
/* Scale the frequencies of the blocks dominated by the exit. */
if (bbs_to_scale)
@@ -1423,7 +1391,7 @@ duplicate_loop_to_header_edge (struct lo
{
if (to_remove)
to_remove->safe_push (orig);
- set_zero_probability (orig);
+ force_edge_cold (orig, true);
/* Scale the frequencies of the blocks dominated by the exit. */
if (bbs_to_scale)
@@ -1657,8 +1625,9 @@ force_single_succ_latches (void)
static basic_block
lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
- edge e, void *cond_expr, unsigned then_prob,
- unsigned else_prob)
+ edge e, void *cond_expr,
+ profile_probability then_prob,
+ profile_probability else_prob)
{
basic_block new_head = NULL;
edge e1;
@@ -1713,7 +1682,7 @@ lv_adjust_loop_entry_edge (basic_block f
struct loop *
loop_version (struct loop *loop,
void *cond_expr, basic_block *condition_bb,
- unsigned then_prob, unsigned else_prob,
+ profile_probability then_prob, profile_probability else_prob,
unsigned then_scale, unsigned else_scale,
bool place_after)
{
Index: cfgloopmanip.h
===================================================================
--- cfgloopmanip.h (revision 249769)
+++ cfgloopmanip.h (working copy)
@@ -58,7 +58,8 @@ basic_block create_preheader (struct loo
extern void create_preheaders (int);
extern void force_single_succ_latches (void);
struct loop * loop_version (struct loop *, void *,
- basic_block *, unsigned, unsigned,
+ basic_block *,
+ profile_probability, profile_probability,
unsigned, unsigned, bool);
#endif /* GCC_CFGLOOPMANIP_H */
Index: cfgrtl.c
===================================================================
--- cfgrtl.c (revision 249769)
+++ cfgrtl.c (working copy)
@@ -1155,7 +1155,7 @@ try_redirect_by_replacing_jump (edge e,
else
e->flags = 0;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = src->count;
if (e->dest != target)
@@ -1504,12 +1504,10 @@ force_nonfallthru_and_redirect (edge e,
{
int prob = XINT (note, 0);
- b->probability = prob;
+ b->probability = profile_probability::from_reg_br_prob_base (prob);
b->count = e->count.apply_probability (prob);
e->probability -= e->probability;
e->count -= b->count;
- if (e->probability < 0)
- e->probability = 0;
}
}
@@ -1618,7 +1616,7 @@ force_nonfallthru_and_redirect (edge e,
{
rtx_insn *new_head;
profile_count count = e->count;
- int probability = e->probability;
+ profile_probability probability = e->probability;
/* Create the new structures. */
/* If the old block ended with a tablejump, skip its table
@@ -1646,7 +1644,7 @@ force_nonfallthru_and_redirect (edge e,
/* Redirect old edge. */
redirect_edge_pred (e, jump_block);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
/* If e->src was previously region crossing, it no longer is
and the reg crossing note should be removed. */
@@ -1656,7 +1654,7 @@ force_nonfallthru_and_redirect (edge e,
add also edge from asm goto bb to target. */
if (asm_goto_edge)
{
- new_edge->probability /= 2;
+ new_edge->probability = new_edge->probability.apply_scale (1, 2);
new_edge->count = new_edge->count.apply_scale (1, 2);
jump_block->count = jump_block->count.apply_scale (1, 2);
jump_block->frequency /= 2;
@@ -2251,12 +2249,13 @@ void
update_br_prob_note (basic_block bb)
{
rtx note;
- if (!JUMP_P (BB_END (bb)))
+ if (!JUMP_P (BB_END (bb)) || !BRANCH_EDGE (bb)->probability.initialized_p ())
return;
note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
- if (!note || XINT (note, 0) == BRANCH_EDGE (bb)->probability)
+ if (!note
+ || XINT (note, 0) == BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ())
return;
- XINT (note, 0) = BRANCH_EDGE (bb)->probability;
+ XINT (note, 0) = BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ();
}
/* Get the last insn associated with block BB (that includes barriers and
@@ -2447,11 +2446,19 @@ rtl_verify_edges (void)
&& EDGE_COUNT (bb->succs) >= 2
&& any_condjump_p (BB_END (bb)))
{
- if (XINT (note, 0) != BRANCH_EDGE (bb)->probability
- && profile_status_for_fn (cfun) != PROFILE_ABSENT)
+ if (!BRANCH_EDGE (bb)->probability.initialized_p ())
+ {
+ error ("verify_flow_info: "
+ "REG_BR_PROB is set but cfg probability is not");
+ err = 1;
+ }
+ else if (XINT (note, 0)
+ != BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ()
+ && profile_status_for_fn (cfun) != PROFILE_ABSENT)
{
error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
- XINT (note, 0), BRANCH_EDGE (bb)->probability);
+ XINT (note, 0),
+ BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ());
err = 1;
}
}
@@ -3143,7 +3150,7 @@ purge_dead_edges (basic_block bb)
/* Redistribute probabilities. */
if (single_succ_p (bb))
{
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
single_succ_edge (bb)->count = bb->count;
}
else
@@ -3154,8 +3161,9 @@ purge_dead_edges (basic_block bb)
b = BRANCH_EDGE (bb);
f = FALLTHRU_EDGE (bb);
- b->probability = XINT (note, 0);
- f->probability = REG_BR_PROB_BASE - b->probability;
+ b->probability = profile_probability::from_reg_br_prob_base
+ (XINT (note, 0));
+ f->probability = profile_probability::always () - b->probability;
b->count = bb->count.apply_probability (b->probability);
f->count = bb->count.apply_probability (f->probability);
}
@@ -3208,7 +3216,7 @@ purge_dead_edges (basic_block bb)
gcc_assert (single_succ_p (bb));
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
single_succ_edge (bb)->count = bb->count;
if (dump_file)
@@ -4931,7 +4939,8 @@ rtl_lv_add_condition_to_bb (basic_block
start_sequence ();
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
- do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label, -1);
+ do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
jump = get_last_insn ();
JUMP_LABEL (jump) = label;
LABEL_NUSES (label)++;
Index: cgraph.c
===================================================================
--- cgraph.c (revision 249769)
+++ cgraph.c (working copy)
@@ -20,8 +20,9 @@ along with GCC; see the file COPYING3.
/* This file contains basic routines manipulating call graph
- The call-graph is a data structure designed for intra-procedural optimization.
- It represents a multi-graph where nodes are functions and edges are call sites. */
+ The call-graph is a data structure designed for inter-procedural
+ optimization. It represents a multi-graph where nodes are functions
+ (symbols within symbol table) and edges are call sites. */
#include "config.h"
#include "system.h"
@@ -1316,13 +1317,16 @@ cgraph_edge::redirect_call_stmt_to_calle
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
new_stmt = gimple_ic (e->call_stmt,
dyn_cast<cgraph_node *> (ref->referred),
+ /* FIXME: cleanup. */
+ profile_probability::from_reg_br_prob_base (
e->count > profile_count::zero ()
|| e2->count > profile_count::zero ()
- ? e->count.probability_in (e->count + e2->count)
+ ? e->count.probability_in
+ (e->count + e2->count).to_reg_br_prob_base ()
: e->frequency || e2->frequency
? RDIV (e->frequency * REG_BR_PROB_BASE,
e->frequency + e2->frequency)
- : REG_BR_PROB_BASE / 2,
+ : REG_BR_PROB_BASE / 2),
e->count, e->count + e2->count);
e->speculative = false;
e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
Index: cgraphunit.c
===================================================================
--- cgraphunit.c (revision 249769)
+++ cgraphunit.c (working copy)
@@ -1506,18 +1506,18 @@ init_lowered_empty_function (tree decl,
/* Create BB for body of the function and connect it properly. */
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = count;
- ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
+ ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
EXIT_BLOCK_PTR_FOR_FN (cfun)->count = count;
- EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
+ EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
bb = create_basic_block (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun));
bb->count = count;
bb->frequency = BB_FREQ_MAX;
e = make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, EDGE_FALLTHRU);
e->count = count;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
e->count = count;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
add_bb_to_loop (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father);
return bb;
@@ -1891,19 +1891,18 @@ cgraph_node::expand_thunk (bool output_a
NULL_TREE, NULL_TREE);
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
e = make_edge (bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 16;
+ e->probability = profile_probability::guessed_always ()
+ .apply_scale (1, 16);
e->count = count - count.apply_scale (1, 16);
e = make_edge (bb, else_bb, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE / 16;
+ e->probability = profile_probability::guessed_always ()
+ .apply_scale (1, 16);
e->count = count.apply_scale (1, 16);
- e = make_edge (return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- e->count = count;
- e = make_edge (then_bb, return_bb, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
- e->count = count - count.apply_scale (1, 16);
+ make_single_succ_edge (return_bb,
+ EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ make_single_succ_edge (then_bb, return_bb, EDGE_FALLTHRU);
e = make_edge (else_bb, return_bb, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = count.apply_scale (1, 16);
bsi = gsi_last_bb (then_bb);
}
Index: cilk-common.c
===================================================================
--- cilk-common.c (revision 249769)
+++ cilk-common.c (working copy)
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.
#include "stor-layout.h"
#include "langhooks.h"
#include "explow.h"
+#include "profile-count.h"
#include "expr.h"
#include "tree-iterator.h"
#include "gimplify.h"
Index: dojump.c
===================================================================
--- dojump.c (revision 249769)
+++ dojump.c (working copy)
@@ -39,19 +39,13 @@ along with GCC; see the file COPYING3.
static bool prefer_and_bit_test (machine_mode, int);
static void do_jump_by_parts_greater (tree, tree, int,
- rtx_code_label *, rtx_code_label *, int);
+ rtx_code_label *, rtx_code_label *,
+ profile_probability);
static void do_jump_by_parts_equality (tree, tree, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
static void do_compare_and_jump (tree, tree, enum rtx_code, enum rtx_code,
- rtx_code_label *, rtx_code_label *, int);
-
-/* Invert probability if there is any. -1 stands for unknown. */
-
-static inline int
-inv (int prob)
-{
- return prob == -1 ? -1 : REG_BR_PROB_BASE - prob;
-}
+ rtx_code_label *, rtx_code_label *,
+ profile_probability);
/* At the start of a function, record that we have no previously-pushed
arguments waiting to be popped. */
@@ -128,29 +122,29 @@ restore_pending_stack_adjust (saved_pend
/* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
void
-jumpifnot (tree exp, rtx_code_label *label, int prob)
+jumpifnot (tree exp, rtx_code_label *label, profile_probability prob)
{
- do_jump (exp, label, NULL, inv (prob));
+ do_jump (exp, label, NULL, prob.invert ());
}
void
jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx_code_label *label,
- int prob)
+ profile_probability prob)
{
- do_jump_1 (code, op0, op1, label, NULL, inv (prob));
+ do_jump_1 (code, op0, op1, label, NULL, prob.invert ());
}
/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
void
-jumpif (tree exp, rtx_code_label *label, int prob)
+jumpif (tree exp, rtx_code_label *label, profile_probability prob)
{
do_jump (exp, NULL, label, prob);
}
void
jumpif_1 (enum tree_code code, tree op0, tree op1,
- rtx_code_label *label, int prob)
+ rtx_code_label *label, profile_probability prob)
{
do_jump_1 (code, op0, op1, NULL, label, prob);
}
@@ -200,12 +194,12 @@ prefer_and_bit_test (machine_mode mode,
/* Subroutine of do_jump, dealing with exploded comparisons of the type
OP0 CODE OP1 . IF_FALSE_LABEL and IF_TRUE_LABEL like in do_jump.
- PROB is probability of jump to if_true_label, or -1 if unknown. */
+ PROB is probability of jump to if_true_label. */
void
do_jump_1 (enum tree_code code, tree op0, tree op1,
rtx_code_label *if_false_label, rtx_code_label *if_true_label,
- int prob)
+ profile_probability prob)
{
machine_mode mode;
rtx_code_label *drop_through_label = 0;
@@ -222,7 +216,8 @@ do_jump_1 (enum tree_code code, tree op0
!= MODE_COMPLEX_INT);
if (integer_zerop (op1))
- do_jump (op0, if_true_label, if_false_label, inv (prob));
+ do_jump (op0, if_true_label, if_false_label,
+ prob.invert ());
else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
&& !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
do_jump_by_parts_equality (op0, op1, if_false_label, if_true_label,
@@ -247,7 +242,7 @@ do_jump_1 (enum tree_code code, tree op0
else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
&& !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
do_jump_by_parts_equality (op0, op1, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, NE, NE, if_false_label, if_true_label,
prob);
@@ -270,7 +265,7 @@ do_jump_1 (enum tree_code code, tree op0
if (GET_MODE_CLASS (mode) == MODE_INT
&& ! can_compare_p (LE, mode, ccp_jump))
do_jump_by_parts_greater (op0, op1, 0, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, LE, LEU, if_false_label, if_true_label,
prob);
@@ -292,7 +287,7 @@ do_jump_1 (enum tree_code code, tree op0
if (GET_MODE_CLASS (mode) == MODE_INT
&& ! can_compare_p (GE, mode, ccp_jump))
do_jump_by_parts_greater (op0, op1, 1, if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
else
do_compare_and_jump (op0, op1, GE, GEU, if_false_label, if_true_label,
prob);
@@ -346,17 +341,17 @@ do_jump_1 (enum tree_code code, tree op0
half of the total probability of being false, so its jump has a false
probability of half the total, relative to the probability we
reached it (i.e. the first condition was true). */
- int op0_prob = -1;
- int op1_prob = -1;
- if (prob != -1)
+ profile_probability op0_prob = profile_probability::uninitialized ();
+ profile_probability op1_prob = profile_probability::uninitialized ();
+ if (prob.initialized_p ())
{
- int false_prob = inv (prob);
- int op0_false_prob = false_prob / 2;
- int op1_false_prob = GCOV_COMPUTE_SCALE ((false_prob / 2),
- inv (op0_false_prob));
+ profile_probability false_prob = prob.invert ();
+ profile_probability op0_false_prob = false_prob.apply_scale (1, 2);
+ profile_probability op1_false_prob = false_prob.apply_scale (1, 2)
+ / op0_false_prob.invert ();
/* Get the probability that each jump below is true. */
- op0_prob = inv (op0_false_prob);
- op1_prob = inv (op1_false_prob);
+ op0_prob = op0_false_prob.invert ();
+ op1_prob = op1_false_prob.invert ();
}
if (if_false_label == NULL)
{
@@ -379,12 +374,12 @@ do_jump_1 (enum tree_code code, tree op0
The second condition has the other half of the total probability,
so its jump has a probability of half the total, relative to
the probability we reached it (i.e. the first condition was false). */
- int op0_prob = -1;
- int op1_prob = -1;
- if (prob != -1)
+ profile_probability op0_prob = profile_probability::uninitialized ();
+ profile_probability op1_prob = profile_probability::uninitialized ();
+ if (prob.initialized_p ())
{
- op0_prob = prob / 2;
- op1_prob = GCOV_COMPUTE_SCALE ((prob / 2), inv (op0_prob));
+ op0_prob = prob.apply_scale (1, 2);
+ op1_prob = prob.apply_scale (1, 2) / op0_prob.invert ();
}
if (if_true_label == NULL)
{
@@ -420,11 +415,11 @@ do_jump_1 (enum tree_code code, tree op0
actually perform a jump. An example where there is no jump
is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
- PROB is probability of jump to if_true_label, or -1 if unknown. */
+ PROB is probability of jump to if_true_label. */
void
do_jump (tree exp, rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label, profile_probability prob)
{
enum tree_code code = TREE_CODE (exp);
rtx temp;
@@ -481,7 +476,7 @@ do_jump (tree exp, rtx_code_label *if_fa
case TRUTH_NOT_EXPR:
do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case COND_EXPR:
@@ -497,7 +492,8 @@ do_jump (tree exp, rtx_code_label *if_fa
}
do_pending_stack_adjust ();
- do_jump (TREE_OPERAND (exp, 0), label1, NULL, -1);
+ do_jump (TREE_OPERAND (exp, 0), label1, NULL,
+ profile_probability::uninitialized ());
do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
emit_label (label1);
do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
@@ -542,7 +538,7 @@ do_jump (tree exp, rtx_code_label *if_fa
{
tree exp0 = TREE_OPERAND (exp, 0);
rtx_code_label *set_label, *clr_label;
- int setclr_prob = prob;
+ profile_probability setclr_prob = prob;
/* Strip narrowing integral type conversions. */
while (CONVERT_EXPR_P (exp0)
@@ -558,7 +554,7 @@ do_jump (tree exp, rtx_code_label *if_fa
exp0 = TREE_OPERAND (exp0, 0);
clr_label = if_true_label;
set_label = if_false_label;
- setclr_prob = inv (prob);
+ setclr_prob = prob.invert ();
}
else
{
@@ -673,7 +669,7 @@ static void
do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
rtx op1, rtx_code_label *if_false_label,
rtx_code_label *if_true_label,
- int prob)
+ profile_probability prob)
{
int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
rtx_code_label *drop_through_label = 0;
@@ -703,7 +699,7 @@ do_jump_by_parts_greater_rtx (machine_mo
if_false_label = drop_through_label;
drop_through_if_true = false;
drop_through_if_false = true;
- prob = inv (prob);
+ prob = prob.invert ();
}
/* Compare a word at a time, high order first. */
@@ -733,7 +729,8 @@ do_jump_by_parts_greater_rtx (machine_mo
/* Consider lower words only if these are equal. */
do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
- NULL_RTX, NULL, if_false_label, inv (prob));
+ NULL_RTX, NULL, if_false_label,
+ prob.invert ());
}
if (!drop_through_if_false)
@@ -750,7 +747,8 @@ do_jump_by_parts_greater_rtx (machine_mo
static void
do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx op0 = expand_normal (swap ? treeop1 : treeop0);
rtx op1 = expand_normal (swap ? treeop0 : treeop1);
@@ -769,7 +767,8 @@ do_jump_by_parts_greater (tree treeop0,
static void
do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
rtx part;
@@ -819,7 +818,8 @@ do_jump_by_parts_zero_rtx (machine_mode
static void
do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
rtx_code_label *drop_through_label = NULL;
@@ -859,7 +859,8 @@ do_jump_by_parts_equality_rtx (machine_m
static void
do_jump_by_parts_equality (tree treeop0, tree treeop1,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx op0 = expand_normal (treeop0);
rtx op1 = expand_normal (treeop1);
@@ -956,7 +957,8 @@ void
do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
machine_mode mode, rtx size,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label,
+ profile_probability prob)
{
rtx tem;
rtx_code_label *dummy_label = NULL;
@@ -983,7 +985,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
{
std::swap (if_true_label, if_false_label);
code = rcode;
- prob = inv (prob);
+ prob = prob.invert ();
}
}
@@ -1035,7 +1037,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
case LEU:
do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case GTU:
@@ -1046,7 +1048,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
case GEU:
do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case LT:
@@ -1057,7 +1059,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
case LE:
do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case GT:
@@ -1068,7 +1070,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
case GE:
do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
if_true_label, if_false_label,
- inv (prob));
+ prob.invert ());
break;
case EQ:
@@ -1078,7 +1080,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op
case NE:
do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
- if_false_label, inv (prob));
+ if_false_label,
+ prob.invert ());
break;
default:
@@ -1115,11 +1118,13 @@ do_compare_rtx_and_jump (rtx op0, rtx op
else
{
- int first_prob = prob;
+ profile_probability first_prob = prob;
if (first_code == UNORDERED)
- first_prob = REG_BR_PROB_BASE / 100;
+ first_prob = profile_probability::guessed_always ().apply_scale
+ (1, 100);
else if (first_code == ORDERED)
- first_prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100;
+ first_prob = profile_probability::guessed_always ().apply_scale
+ (99, 100);
if (and_them)
{
rtx_code_label *dest_label;
@@ -1165,7 +1170,7 @@ static void
do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
enum rtx_code unsigned_code,
rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob)
+ rtx_code_label *if_true_label, profile_probability prob)
{
rtx op0, op1;
tree type;
Index: dojump.h
===================================================================
--- dojump.h (revision 249769)
+++ dojump.h (working copy)
@@ -57,23 +57,26 @@ extern void save_pending_stack_adjust (s
extern void restore_pending_stack_adjust (saved_pending_stack_adjust *);
/* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
-extern void jumpifnot (tree exp, rtx_code_label *label, int prob);
-extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *, int);
+extern void jumpifnot (tree exp, rtx_code_label *label,
+ profile_probability prob);
+extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *,
+ profile_probability);
/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
-extern void jumpif (tree exp, rtx_code_label *label, int prob);
-extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *, int);
+extern void jumpif (tree exp, rtx_code_label *label, profile_probability prob);
+extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *,
+ profile_probability);
/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
the result is zero, or IF_TRUE_LABEL if the result is one. */
extern void do_jump (tree exp, rtx_code_label *if_false_label,
- rtx_code_label *if_true_label, int prob);
+ rtx_code_label *if_true_label, profile_probability prob);
extern void do_jump_1 (enum tree_code, tree, tree, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
machine_mode, rtx, rtx_code_label *,
- rtx_code_label *, int);
+ rtx_code_label *, profile_probability);
extern bool split_comparison (enum rtx_code, machine_mode,
enum rtx_code *, enum rtx_code *);
Index: dwarf2cfi.c
===================================================================
--- dwarf2cfi.c (revision 249769)
+++ dwarf2cfi.c (working copy)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.
#include "common/common-target.h"
#include "except.h" /* expand_builtin_dwarf_sp_column */
+#include "profile-count.h" /* For expr.h */
#include "expr.h" /* init_return_column_size */
#include "output.h" /* asm_out_file */
#include "debug.h" /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
Index: except.c
===================================================================
--- except.c (revision 249769)
+++ except.c (working copy)
@@ -974,7 +974,6 @@ dw2_build_landing_pads (void)
{
basic_block bb;
rtx_insn *seq;
- edge e;
if (lp == NULL || lp->post_landing_pad == NULL)
continue;
@@ -991,9 +990,7 @@ dw2_build_landing_pads (void)
end_sequence ();
bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
- e = make_edge (bb, bb->next_bb, e_flags);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (bb, bb->next_bb, e_flags);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
@@ -1258,7 +1255,6 @@ sjlj_emit_dispatch_table (rtx_code_label
rtx_insn *seq;
basic_block bb;
eh_region r;
- edge e;
int i, disp_index;
vec<tree> dispatch_labels = vNULL;
@@ -1346,9 +1342,7 @@ sjlj_emit_dispatch_table (rtx_code_label
rtx_insn *before = label_rtx (lp->post_landing_pad);
bb = emit_to_new_bb_before (seq2, before);
- e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
@@ -1386,9 +1380,7 @@ sjlj_emit_dispatch_table (rtx_code_label
bb = emit_to_new_bb_before (seq, first_reachable_label);
if (num_dispatch == 1)
{
- e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
if (current_loops)
{
struct loop *loop = bb->next_bb->loop_father;
Index: explow.c
===================================================================
--- explow.c (revision 249769)
+++ explow.c (working copy)
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.
#include "memmodel.h"
#include "tm_p.h"
#include "expmed.h"
+#include "profile-count.h"
#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
Index: expmed.c
===================================================================
--- expmed.c (revision 249769)
+++ expmed.c (working copy)
@@ -5905,7 +5905,8 @@ emit_store_flag_force (rtx target, enum
{
label = gen_label_rtx ();
do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, mode,
- NULL_RTX, NULL, label, -1);
+ NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
emit_move_insn (target, trueval);
emit_label (label);
return target;
@@ -5943,7 +5944,7 @@ emit_store_flag_force (rtx target, enum
emit_move_insn (target, trueval);
label = gen_label_rtx ();
do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, NULL,
- label, -1);
+ label, profile_probability::uninitialized ());
emit_move_insn (target, falseval);
emit_label (label);
@@ -5961,5 +5962,5 @@ do_cmp_and_jump (rtx arg1, rtx arg2, enu
{
int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU);
do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, NULL_RTX,
- NULL, label, -1);
+ NULL, label, profile_probability::uninitialized ());
}
Index: expr.c
===================================================================
--- expr.c (revision 249769)
+++ expr.c (working copy)
@@ -96,7 +96,8 @@ static rtx do_store_flag (sepops, rtx, m
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (machine_mode, rtx, tree);
#endif
-static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
+static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx,
+ profile_probability);
static rtx const_vector_from_tree (tree);
static rtx const_scalar_mask_from_tree (tree);
static tree tree_expr_size (const_tree);
@@ -1452,7 +1453,7 @@ compare_by_pieces_d::generate (rtx op0,
m_accumulator = NULL_RTX;
}
do_compare_rtx_and_jump (op0, op1, NE, true, mode, NULL_RTX, NULL,
- m_fail_label, -1);
+ m_fail_label, profile_probability::uninitialized ());
}
/* Return true if MODE can be used for a set of moves and comparisons,
@@ -1484,7 +1485,8 @@ compare_by_pieces_d::finish_mode (machin
{
if (m_accumulator != NULL_RTX)
do_compare_rtx_and_jump (m_accumulator, const0_rtx, NE, true, mode,
- NULL_RTX, NULL, m_fail_label, -1);
+ NULL_RTX, NULL, m_fail_label,
+ profile_probability::uninitialized ());
}
/* Generate several move instructions to compare LEN bytes from blocks
@@ -1845,7 +1847,9 @@ emit_block_move_via_loop (rtx x, rtx y,
emit_label (cmp_label);
emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
- true, top_label, REG_BR_PROB_BASE * 90 / 100);
+ true, top_label,
+ profile_probability::guessed_always ()
+ .apply_scale (9, 10));
}
\f
/* Expand a call to memcpy or memmove or memcmp, and return the result.
@@ -5402,7 +5406,8 @@ store_expr_with_bounds (tree exp, rtx ta
do_pending_stack_adjust ();
NO_DEFER_POP;
- jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
+ jumpifnot (TREE_OPERAND (exp, 0), lab1,
+ profile_probability::uninitialized ());
store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
nontemporal, reverse, btarget);
emit_jump_insn (targetm.gen_jump (lab2));
@@ -6504,7 +6509,8 @@ store_constructor (tree exp, rtx target,
/* Generate a conditional jump to exit the loop. */
exit_cond = build2 (LT_EXPR, integer_type_node,
index, hi_index);
- jumpif (exit_cond, loop_end, -1);
+ jumpif (exit_cond, loop_end,
+ profile_probability::uninitialized ());
/* Update the loop counter, and jump to the head of
the loop. */
@@ -9043,7 +9049,7 @@ expand_expr_real_2 (sepops ops, rtx targ
lab = gen_label_rtx ();
do_compare_rtx_and_jump (target, cmpop1, comparison_code,
unsignedp, mode, NULL_RTX, NULL, lab,
- -1);
+ profile_probability::uninitialized ());
}
emit_move_insn (target, op1);
emit_label (lab);
@@ -9272,7 +9278,8 @@ expand_expr_real_2 (sepops ops, rtx targ
emit_move_insn (target, const0_rtx);
rtx_code_label *lab1 = gen_label_rtx ();
- jumpifnot_1 (code, treeop0, treeop1, lab1, -1);
+ jumpifnot_1 (code, treeop0, treeop1, lab1,
+ profile_probability::uninitialized ());
if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
emit_move_insn (target, constm1_rtx);
@@ -9523,7 +9530,8 @@ expand_expr_real_2 (sepops ops, rtx targ
NO_DEFER_POP;
rtx_code_label *lab0 = gen_label_rtx ();
rtx_code_label *lab1 = gen_label_rtx ();
- jumpifnot (treeop0, lab0, -1);
+ jumpifnot (treeop0, lab0,
+ profile_probability::uninitialized ());
store_expr (treeop1, temp,
modifier == EXPAND_STACK_PARM,
false, false);
@@ -11042,7 +11050,8 @@ expand_expr_real_1 (tree exp, rtx target
int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
do_jump (TREE_OPERAND (rhs, 1),
value ? label : 0,
- value ? 0 : label, -1);
+ value ? 0 : label,
+ profile_probability::uninitialized ());
expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
false);
do_pending_stack_adjust ();
@@ -11512,7 +11521,7 @@ do_store_flag (sepops ops, rtx target, m
int
try_casesi (tree index_type, tree index_expr, tree minval, tree range,
rtx table_label, rtx default_label, rtx fallback_label,
- int default_probability)
+ profile_probability default_probability)
{
struct expand_operand ops[5];
machine_mode index_mode = SImode;
@@ -11582,7 +11591,7 @@ try_casesi (tree index_type, tree index_
static void
do_tablejump (rtx index, machine_mode mode, rtx range, rtx table_label,
- rtx default_label, int default_probability)
+ rtx default_label, profile_probability default_probability)
{
rtx temp, vector;
@@ -11645,7 +11654,8 @@ do_tablejump (rtx index, machine_mode mo
int
try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
- rtx table_label, rtx default_label, int default_probability)
+ rtx table_label, rtx default_label,
+ profile_probability default_probability)
{
rtx index;
Index: expr.h
===================================================================
--- expr.h (revision 249769)
+++ expr.h (working copy)
@@ -288,8 +288,8 @@ expand_normal (tree exp)
extern tree string_constant (tree, tree *);
/* Two different ways of generating switch statements. */
-extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
-extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, int);
+extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
+extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, profile_probability);
extern int safe_from_p (const_rtx, tree, int);
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c (revision 249769)
+++ gimple-pretty-print.c (working copy)
@@ -80,7 +80,7 @@ debug_gimple_stmt (gimple *gs)
by xstrdup_for_dump. */
static const char *
-dump_probability (int frequency, profile_count &count)
+dump_profile (int frequency, profile_count &count)
{
float minimum = 0.01f;
@@ -102,6 +102,38 @@ dump_probability (int frequency, profile
return ret;
}
+/* Return formatted string of a VALUE probability
+ (biased by REG_BR_PROB_BASE). Returned string is allocated
+ by xstrdup_for_dump. */
+
+static const char *
+dump_probability (profile_probability probability, profile_count &count)
+{
+ float minimum = 0.01f;
+ float fvalue = -1;
+
+ if (probability.initialized_p ())
+ {
+ fvalue = probability.to_reg_br_prob_base () * 100.0f / REG_BR_PROB_BASE;
+ if (fvalue < minimum && probability.to_reg_br_prob_base ())
+ fvalue = minimum;
+ }
+
+ char *buf;
+ if (count.initialized_p ())
+ asprintf (&buf, "[%.2f%%] [count: %" PRId64 "]", fvalue,
+ count.to_gcov_type ());
+ else if (probability.initialized_p ())
+ asprintf (&buf, "[%.2f%%] [count: INV]", fvalue);
+ else
+ asprintf (&buf, "[INV] [count: INV]");
+
+ const char *ret = xstrdup_for_dump (buf);
+ free (buf);
+
+ return ret;
+}
+
/* Dump E probability to BUFFER. */
static void
@@ -1090,7 +1122,7 @@ dump_gimple_label (pretty_printer *buffe
dump_generic_node (buffer, label, spc, flags, false);
basic_block bb = gimple_bb (gs);
if (bb && !(flags & TDF_GIMPLE))
- pp_scalar (buffer, " %s", dump_probability (bb->frequency, bb->count));
+ pp_scalar (buffer, " %s", dump_profile (bb->frequency, bb->count));
pp_colon (buffer);
}
if (flags & TDF_GIMPLE)
@@ -2670,8 +2702,8 @@ dump_gimple_bb_header (FILE *outf, basic
fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
else
fprintf (outf, "%*s<bb %d> %s:\n",
- indent, "", bb->index, dump_probability (bb->frequency,
- bb->count));
+ indent, "", bb->index, dump_profile (bb->frequency,
+ bb->count));
}
}
}
Index: graph.c
===================================================================
--- graph.c (revision 249769)
+++ graph.c (working copy)
@@ -136,12 +136,16 @@ draw_cfg_node_succ_edges (pretty_printer
pp_printf (pp,
"\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
- "[style=%s,color=%s,weight=%d,constraint=%s, label=\"[%i%%]\"];\n",
+ "[style=%s,color=%s,weight=%d,constraint=%s];\n",
funcdef_no, e->src->index,
funcdef_no, e->dest->index,
style, color, weight,
- (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true",
- e->probability * 100 / REG_BR_PROB_BASE);
+ (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true");
+ if (e->probability.initialized_p ())
+ pp_printf (pp, ", label=\"[%i%%]\"",
+ e->probability.to_reg_br_prob_base ()
+ * 100 / REG_BR_PROB_BASE);
+ pp_printf (pp, "];\n");
}
pp_flush (pp);
}
Index: hsa-gen.c
===================================================================
--- hsa-gen.c (revision 249769)
+++ hsa-gen.c (working copy)
@@ -6139,7 +6139,7 @@ convert_switch_statements (void)
auto_vec <edge> new_edges;
auto_vec <phi_definition *> phi_todo_list;
auto_vec <profile_count> edge_counts;
- auto_vec <int> edge_probabilities;
+ auto_vec <profile_probability> edge_probabilities;
/* Investigate all labels that and PHI nodes in these edges which
should be fixed after we add new collection of edges. */
@@ -6231,12 +6231,12 @@ convert_switch_statements (void)
basic_block label_bb
= label_to_block_fn (func, CASE_LABEL (label));
edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
- int prob_sum = sum_slice <int> (edge_probabilities, i, labels, 0) +
- edge_probabilities[0];
+ profile_probability prob_sum = sum_slice <profile_probability>
+ (edge_probabilities, i, labels, profile_probability::never ())
+ + edge_probabilities[0];
- if (prob_sum)
- new_edge->probability
- = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
+ if (prob_sum.initialized_p ())
+ new_edge->probability = edge_probabilities[i] / prob_sum;
new_edge->count = edge_counts[i];
new_edges.safe_push (new_edge);
@@ -6253,8 +6253,7 @@ convert_switch_statements (void)
}
edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
- next_edge->probability
- = inverse_probability (new_edge->probability);
+ next_edge->probability = new_edge->probability.invert ();
next_edge->count = edge_counts[0]
+ sum_slice <profile_count> (edge_counts, i, labels,
profile_count::zero ());
@@ -6265,7 +6264,7 @@ convert_switch_statements (void)
of the switch. */
{
edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
- e->probability = inverse_probability (new_edge->probability);
+ e->probability = new_edge->probability.invert ();
e->count = edge_counts[0];
new_edges.safe_insert (0, e);
}
Index: ifcvt.c
===================================================================
--- ifcvt.c (revision 249769)
+++ ifcvt.c (working copy)
@@ -78,7 +78,7 @@ static int cond_exec_changed_p;
/* Forward references. */
static int count_bb_insns (const_basic_block);
-static bool cheap_bb_rtx_cost_p (const_basic_block, int, int);
+static bool cheap_bb_rtx_cost_p (const_basic_block, profile_probability, int);
static rtx_insn *first_active_insn (basic_block);
static rtx_insn *last_active_insn (basic_block, int);
static rtx_insn *find_active_insn_before (basic_block, rtx_insn *);
@@ -132,11 +132,14 @@ count_bb_insns (const_basic_block bb)
plus a small fudge factor. */
static bool
-cheap_bb_rtx_cost_p (const_basic_block bb, int scale, int max_cost)
+cheap_bb_rtx_cost_p (const_basic_block bb,
+ profile_probability prob, int max_cost)
{
int count = 0;
rtx_insn *insn = BB_HEAD (bb);
bool speed = optimize_bb_for_speed_p (bb);
+ int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
+ : REG_BR_PROB_BASE;
/* Set scale to REG_BR_PROB_BASE to void the identical scaling
applied to insn_rtx_cost when optimizing for size. Only do
@@ -4807,7 +4810,8 @@ find_if_case_1 (basic_block test_bb, edg
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
basic_block new_bb;
- int then_bb_index, then_prob;
+ int then_bb_index;
+ profile_probability then_prob;
rtx else_target = NULL_RTX;
/* If we are partitioning hot/cold basic blocks, we don't want to
@@ -4853,10 +4857,7 @@ find_if_case_1 (basic_block test_bb, edg
"\nIF-CASE-1 found, start %d, then %d\n",
test_bb->index, then_bb->index);
- if (then_edge->probability)
- then_prob = REG_BR_PROB_BASE - then_edge->probability;
- else
- then_prob = REG_BR_PROB_BASE / 2;
+ then_prob = then_edge->probability.invert ();
/* We're speculating from the THEN path, we want to make sure the cost
of speculation is within reason. */
@@ -4927,7 +4928,7 @@ find_if_case_2 (basic_block test_bb, edg
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
edge else_succ;
- int then_prob, else_prob;
+ profile_probability then_prob, else_prob;
/* We do not want to speculate (empty) loop latches. */
if (current_loops
@@ -4973,16 +4974,8 @@ find_if_case_2 (basic_block test_bb, edg
if (then_bb->index < NUM_FIXED_BLOCKS)
return FALSE;
- if (else_edge->probability)
- {
- else_prob = else_edge->probability;
- then_prob = REG_BR_PROB_BASE - else_prob;
- }
- else
- {
- else_prob = REG_BR_PROB_BASE / 2;
- then_prob = REG_BR_PROB_BASE / 2;
- }
+ else_prob = else_edge->probability;
+ then_prob = else_prob.invert ();
/* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
if (else_prob > then_prob)
Index: internal-fn.c
===================================================================
--- internal-fn.c (revision 249769)
+++ internal-fn.c (working copy)
@@ -569,7 +569,7 @@ expand_arith_overflow_result_store (tree
gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
EQ, true, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
@@ -597,7 +597,7 @@ expand_arith_overflow_result_store (tree
}
do_compare_rtx_and_jump (res, lres,
EQ, true, tgtmode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
@@ -767,7 +767,7 @@ expand_addsub_overflow (location_t loc,
tem = op1;
do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
true, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
goto do_error_label;
}
@@ -782,7 +782,7 @@ expand_addsub_overflow (location_t loc,
code == PLUS_EXPR ? res : op0, sgn,
NULL_RTX, false, OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -824,9 +824,9 @@ expand_addsub_overflow (location_t loc,
else if (pos_neg == 3)
/* If ARG0 is not known to be always positive, check at runtime. */
do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -840,7 +840,7 @@ expand_addsub_overflow (location_t loc,
rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -852,7 +852,7 @@ expand_addsub_overflow (location_t loc,
res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
rtx tem = op1;
/* The operation is commutative, so we can pick operand to compare
against. For prec <= BITS_PER_WORD, I think preferring REG operand
@@ -866,7 +866,7 @@ expand_addsub_overflow (location_t loc,
: CONST_SCALAR_INT_P (op0))
tem = op0;
do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -894,7 +894,7 @@ expand_addsub_overflow (location_t loc,
? and_optab : ior_optab,
op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
else
{
@@ -902,17 +902,17 @@ expand_addsub_overflow (location_t loc,
do_compare_rtx_and_jump (op1, const0_rtx,
code == MINUS_EXPR ? GE : LT, false, mode,
NULL_RTX, NULL, do_ior_label,
- PROB_EVEN);
+ profile_probability::even ());
tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
emit_jump (do_error);
emit_label (do_ior_label);
tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
goto do_error_label;
}
@@ -926,13 +926,13 @@ expand_addsub_overflow (location_t loc,
OPTAB_LIB_WIDEN);
rtx_code_label *op0_geu_op1 = gen_label_rtx ();
do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
- op0_geu_op1, PROB_EVEN);
+ op0_geu_op1, profile_probability::even ());
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
emit_jump (do_error);
emit_label (op0_geu_op1);
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
}
@@ -960,7 +960,7 @@ expand_addsub_overflow (location_t loc,
&& JUMP_P (last)
&& any_condjump_p (last)
&& !find_reg_note (last, REG_BR_PROB, 0))
- add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
+ add_int_reg_note (last, REG_BR_PROB, PROB_UNLIKELY);
emit_jump (done_label);
goto do_error_label;
}
@@ -1020,7 +1020,7 @@ expand_addsub_overflow (location_t loc,
/* No overflow if the result has bit sign cleared. */
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
}
/* Compare the result of the operation with the first operand.
@@ -1031,7 +1031,7 @@ expand_addsub_overflow (location_t loc,
do_compare_rtx_and_jump (res, op0,
(pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
false, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
do_error_label:
@@ -1128,7 +1128,7 @@ expand_neg_overflow (location_t loc, tre
/* Compare the operand with the most negative value. */
rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
- done_label, PROB_VERY_LIKELY);
+ done_label, profile_probability::very_likely ());
}
emit_label (do_error);
@@ -1261,15 +1261,15 @@ expand_mul_overflow (location_t loc, tre
ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
case 3:
rtx_code_label *do_main_label;
do_main_label = gen_label_rtx ();
do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
@@ -1306,15 +1306,15 @@ expand_mul_overflow (location_t loc, tre
ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
- NULL, do_error, PROB_VERY_UNLIKELY);
+ NULL, do_error, profile_probability::very_unlikely ());
int prec;
prec = GET_MODE_PRECISION (mode);
rtx sgn;
sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
- NULL, done_label, PROB_VERY_LIKELY);
+ NULL, done_label, profile_probability::very_likely ());
goto do_error_label;
case 3:
/* Rest of handling of this case after res is computed. */
@@ -1361,7 +1361,7 @@ expand_mul_overflow (location_t loc, tre
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
goto do_error_label;
}
/* The general case, do all the needed comparisons at runtime. */
@@ -1378,7 +1378,7 @@ expand_mul_overflow (location_t loc, tre
tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, after_negate_label, PROB_VERY_LIKELY);
+ NULL, after_negate_label, profile_probability::very_likely ());
/* Both arguments negative here, negate them and continue with
normal unsigned overflow checking multiplication. */
emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
@@ -1394,13 +1394,13 @@ expand_mul_overflow (location_t loc, tre
tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN);
do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
/* One argument is negative here, the other positive. This
overflows always, unless one of the arguments is 0. But
if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
is, thus we can keep do_main code oring in overflow as is. */
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, do_main_label, PROB_VERY_LIKELY);
+ NULL, do_main_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
@@ -1467,7 +1467,7 @@ expand_mul_overflow (location_t loc, tre
HIPART is non-zero. */
do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
else
{
rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
@@ -1477,7 +1477,7 @@ expand_mul_overflow (location_t loc, tre
HIPART is different from RES < 0 ? -1 : 0. */
do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
}
else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
@@ -1570,12 +1570,12 @@ expand_mul_overflow (location_t loc, tre
if (!op0_small_p)
do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
NULL_RTX, NULL, large_op0,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
if (!op1_small_p)
do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
NULL_RTX, NULL, small_op0_large_op1,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
/* If both op0 and op1 are sign (!uns) or zero (uns) extended from
hmode to mode, the multiplication will never overflow. We can
@@ -1621,7 +1621,7 @@ expand_mul_overflow (location_t loc, tre
if (!op1_small_p)
do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
NULL_RTX, NULL, both_ops_large,
- PROB_UNLIKELY);
+ profile_probability::unlikely ());
/* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
but op0 is not, prepare larger, hipart and lopart pseudos and
@@ -1658,7 +1658,7 @@ expand_mul_overflow (location_t loc, tre
else if (larger_sign != -1)
do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
NULL_RTX, NULL, after_hipart_neg,
- PROB_EVEN);
+ profile_probability::even ());
tem = convert_modes (mode, hmode, lopart, 1);
tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
@@ -1674,7 +1674,7 @@ expand_mul_overflow (location_t loc, tre
else if (smaller_sign != -1)
do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
NULL_RTX, NULL, after_lopart_neg,
- PROB_EVEN);
+ profile_probability::even ());
tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
1, OPTAB_DIRECT);
@@ -1704,7 +1704,7 @@ expand_mul_overflow (location_t loc, tre
do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
NULL_RTX, NULL, do_overflow,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
/* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
@@ -1741,7 +1741,7 @@ expand_mul_overflow (location_t loc, tre
NULL_RTX, 1, OPTAB_DIRECT);
do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
}
if (!op1_medium_p)
@@ -1750,7 +1750,7 @@ expand_mul_overflow (location_t loc, tre
NULL_RTX, 1, OPTAB_DIRECT);
do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
}
/* At this point hipart{0,1} are both in [-1, 0]. If they are
@@ -1761,18 +1761,18 @@ expand_mul_overflow (location_t loc, tre
else if (op0_sign == 1 || op1_sign == 1)
do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
NULL_RTX, NULL, hipart_different,
- PROB_EVEN);
+ profile_probability::even ());
do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
emit_jump (done_label);
emit_label (hipart_different);
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
NULL_RTX, NULL, do_error,
- PROB_VERY_UNLIKELY);
+ profile_probability::very_unlikely ());
emit_jump (done_label);
}
@@ -1817,7 +1817,7 @@ expand_mul_overflow (location_t loc, tre
{
rtx_code_label *all_done_label = gen_label_rtx ();
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_LIKELY);
+ NULL, all_done_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
emit_label (all_done_label);
}
@@ -1828,14 +1828,14 @@ expand_mul_overflow (location_t loc, tre
rtx_code_label *all_done_label = gen_label_rtx ();
rtx_code_label *set_noovf = gen_label_rtx ();
do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_LIKELY);
+ NULL, all_done_label, profile_probability::very_likely ());
expand_arith_set_overflow (lhs, target);
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
- NULL, set_noovf, PROB_VERY_LIKELY);
+ NULL, set_noovf, profile_probability::very_likely ());
do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
- NULL, all_done_label, PROB_VERY_UNLIKELY);
+ NULL, all_done_label, profile_probability::very_unlikely ());
do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
- all_done_label, PROB_VERY_UNLIKELY);
+ all_done_label, profile_probability::very_unlikely ());
emit_label (set_noovf);
write_complex_part (target, const0_rtx, true);
emit_label (all_done_label);
@@ -1977,7 +1977,7 @@ expand_vector_ubsan_overflow (location_t
emit_move_insn (cntvar, ret);
do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
- PROB_VERY_LIKELY);
+ profile_probability::very_likely ());
}
if (lhs && resv == NULL_TREE)
{
Index: ipa-cp.c
===================================================================
--- ipa-cp.c (revision 249769)
+++ ipa-cp.c (working copy)
@@ -2623,7 +2623,8 @@ good_cloning_opportunity_p (struct cgrap
struct ipa_node_params *info = IPA_NODE_REF (node);
if (max_count > profile_count::zero ())
{
- int factor = RDIV (count_sum.probability_in (max_count)
+ int factor = RDIV (count_sum.probability_in
+ (max_count).to_reg_br_prob_base ()
* 1000, REG_BR_PROB_BASE);
int64_t evaluation = (((int64_t) time_benefit * factor)
/ size_cost);
Index: ipa-split.c
===================================================================
--- ipa-split.c (revision 249769)
+++ ipa-split.c (working copy)
@@ -1292,9 +1292,7 @@ split_function (basic_block return_bb, s
break;
}
}
- e = make_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- e->count = new_return_bb->count;
+ e = make_single_succ_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
add_bb_to_loop (new_return_bb, current_loops->tree_root);
bitmap_set_bit (split_point->split_bbs, new_return_bb->index);
retbnd = find_retbnd (return_bb);
@@ -1527,11 +1525,9 @@ split_function (basic_block return_bb, s
}
else
{
- e = make_edge (call_bb, return_bb,
- return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
- ? 0 : EDGE_FALLTHRU);
- e->count = call_bb->count;
- e->probability = REG_BR_PROB_BASE;
+ e = make_single_succ_edge (call_bb, return_bb,
+ return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+ ? 0 : EDGE_FALLTHRU);
/* If there is return basic block, see what value we need to store
return value into and put call just before it. */
Index: ipa-utils.c
===================================================================
--- ipa-utils.c (revision 249769)
+++ ipa-utils.c (working copy)
@@ -598,7 +598,8 @@ ipa_merge_profiles (struct cgraph_node *
}
}
int prob = direct->count.probability_in (direct->count
- + indirect->count);
+ + indirect->count).
+ to_reg_br_prob_base ();
direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE);
indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob),
REG_BR_PROB_BASE);
@@ -616,7 +617,8 @@ ipa_merge_profiles (struct cgraph_node *
e2->speculative_call_info (direct, indirect, ref);
e->count = count;
e->frequency = freq;
- int prob = direct->count.probability_in (e->count);
+ int prob = direct->count.probability_in (e->count)
+ .to_reg_br_prob_base ();
e->make_speculative (direct->callee, direct->count,
RDIV (freq * prob, REG_BR_PROB_BASE));
}
Index: loop-doloop.c
===================================================================
--- loop-doloop.c (revision 249769)
+++ loop-doloop.c (working copy)
@@ -356,7 +356,8 @@ add_test (rtx cond, edge *e, basic_block
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
label = block_label (dest);
- do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label, -1);
+ do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
jump = get_last_insn ();
if (!jump || !JUMP_P (jump))
@@ -575,10 +576,11 @@ doloop_modify (struct loop *loop, struct
add_reg_note (jump_insn, REG_NONNEG, NULL_RTX);
/* Update the REG_BR_PROB note. */
- if (true_prob_val)
+ if (true_prob_val && desc->in_edge->probability.initialized_p ())
{
/* Seems safer to use the branch probability. */
- add_int_reg_note (jump_insn, REG_BR_PROB, desc->in_edge->probability);
+ add_int_reg_note (jump_insn, REG_BR_PROB,
+ desc->in_edge->probability.to_reg_br_prob_base ());
}
}
Index: loop-unroll.c
===================================================================
--- loop-unroll.c (revision 249769)
+++ loop-unroll.c (working copy)
@@ -774,7 +774,8 @@ split_edge_and_insert (edge e, rtx_insn
static rtx_insn *
compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp,
- rtx_code_label *label, int prob, rtx_insn *cinsn)
+ rtx_code_label *label, profile_probability prob,
+ rtx_insn *cinsn)
{
rtx_insn *seq;
rtx_jump_insn *jump;
@@ -808,12 +809,14 @@ compare_and_jump_seq (rtx op0, rtx op1,
op0 = force_operand (op0, NULL_RTX);
op1 = force_operand (op1, NULL_RTX);
do_compare_rtx_and_jump (op0, op1, comp, 0,
- mode, NULL_RTX, NULL, label, -1);
+ mode, NULL_RTX, NULL, label,
+ profile_probability::uninitialized ());
jump = as_a <rtx_jump_insn *> (get_last_insn ());
jump->set_jump_target (label);
LABEL_NUSES (label)++;
}
- add_int_reg_note (jump, REG_BR_PROB, prob);
+ if (prob.initialized_p ())
+ add_int_reg_note (jump, REG_BR_PROB, prob.to_reg_br_prob_base ());
seq = get_insns ();
end_sequence ();
@@ -857,7 +860,8 @@ unroll_loop_runtime_iterations (struct l
{
rtx old_niter, niter, tmp;
rtx_insn *init_code, *branch_code;
- unsigned i, j, p;
+ unsigned i, j;
+ profile_probability p;
basic_block preheader, *body, swtch, ezc_swtch = NULL;
int may_exit_copy, iter_freq, new_freq;
profile_count iter_count, new_count;
@@ -989,7 +993,7 @@ unroll_loop_runtime_iterations (struct l
/* Create item for switch. */
j = n_peel - i - (extra_zero_check ? 0 : 1);
- p = REG_BR_PROB_BASE / (i + 2);
+ p = profile_probability::always ().apply_scale (1, i + 2);
preheader = split_edge (loop_preheader_edge (loop));
/* Add in frequency/count of edge from switch block. */
@@ -1006,7 +1010,7 @@ unroll_loop_runtime_iterations (struct l
swtch = split_edge_and_insert (single_pred_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
- single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
+ single_succ_edge (swtch)->probability = p.invert ();
single_succ_edge (swtch)->count = new_count;
new_freq += iter_freq;
new_count += iter_count;
@@ -1021,7 +1025,7 @@ unroll_loop_runtime_iterations (struct l
if (extra_zero_check)
{
/* Add branch for zero iterations. */
- p = REG_BR_PROB_BASE / (max_unroll + 1);
+ p = profile_probability::always ().apply_scale (1, max_unroll + 1);
swtch = ezc_swtch;
preheader = split_edge (loop_preheader_edge (loop));
/* Recompute frequency/count adjustments since initial peel copy may
@@ -1039,7 +1043,7 @@ unroll_loop_runtime_iterations (struct l
swtch = split_edge_and_insert (single_succ_edge (swtch), branch_code);
set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
- single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
+ single_succ_edge (swtch)->probability = p.invert ();
single_succ_edge (swtch)->count -= iter_count;
e = make_edge (swtch, preheader,
single_succ_edge (swtch)->flags & EDGE_IRREDUCIBLE_LOOP);
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 249769)
+++ lra-constraints.c (working copy)
@@ -6482,7 +6482,8 @@ lra_inheritance (void)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability < EBB_PROBABILITY_CUTOFF)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () < EBB_PROBABILITY_CUTOFF)
break;
bb = bb->next_bb;
}
Index: lto-streamer-in.c
===================================================================
--- lto-streamer-in.c (revision 249769)
+++ lto-streamer-in.c (working copy)
@@ -754,12 +754,12 @@ input_cfg (struct lto_input_block *ib, s
unsigned int dest_index;
unsigned int edge_flags;
basic_block dest;
- int probability;
+ profile_probability probability;
profile_count count;
edge e;
dest_index = streamer_read_uhwi (ib);
- probability = (int) streamer_read_hwi (ib);
+ probability = profile_probability::stream_in (ib);
count = profile_count::stream_in (ib).apply_scale
(count_materialization_scale, REG_BR_PROB_BASE);
edge_flags = streamer_read_uhwi (ib);
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c (revision 249769)
+++ lto-streamer-out.c (working copy)
@@ -1860,7 +1860,7 @@ output_cfg (struct output_block *ob, str
FOR_EACH_EDGE (e, ei, bb->succs)
{
streamer_write_uhwi (ob, e->dest->index);
- streamer_write_hwi (ob, e->probability);
+ e->probability.stream_out (ob);
e->count.stream_out (ob);
streamer_write_uhwi (ob, e->flags);
}
Index: mcf.c
===================================================================
--- mcf.c (revision 249769)
+++ mcf.c (working copy)
@@ -1231,12 +1231,15 @@ adjust_cfg_counts (fixup_graph_type *fix
}
if (bb_gcov_count (bb))
- e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
- bb_gcov_count (bb));
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
if (dump_file)
- fprintf (dump_file, " = %" PRId64 "\t(%.1f%%)\n",
- edge_gcov_count (e),
- e->probability * 100.0 / REG_BR_PROB_BASE);
+ {
+ fprintf (dump_file, " = %" PRId64 "\t",
+ edge_gcov_count (e));
+ e->probability.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
}
}
@@ -1251,31 +1254,8 @@ adjust_cfg_counts (fixup_graph_type *fix
if (bb_gcov_count (bb))
{
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
- bb_gcov_count (bb));
- }
- else
- {
- int total = 0;
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- total++;
- if (total)
- {
- FOR_EACH_EDGE (e, ei, bb->succs)
- {
- if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- e->probability = REG_BR_PROB_BASE / total;
- else
- e->probability = 0;
- }
- }
- else
- {
- total += EDGE_COUNT (bb->succs);
- FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = REG_BR_PROB_BASE / total;
- }
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
}
}
Index: modulo-sched.c
===================================================================
--- modulo-sched.c (revision 249769)
+++ modulo-sched.c (working copy)
@@ -1713,12 +1713,13 @@ sms_schedule (void)
rtx comp_rtx = gen_rtx_GT (VOIDmode, count_reg,
gen_int_mode (stage_count,
GET_MODE (count_reg)));
- unsigned prob = (PROB_SMS_ENOUGH_ITERATIONS
- * REG_BR_PROB_BASE) / 100;
+ profile_probability prob = profile_probability::guessed_always ()
+ .apply_scale (PROB_SMS_ENOUGH_ITERATIONS, 100);
loop_version (loop, comp_rtx, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
- prob, REG_BR_PROB_BASE - prob,
+ prob, prob.invert (),
+ prob.to_reg_br_prob_base (),
+ prob.invert ().to_reg_br_prob_base (),
true);
}
Index: omp-expand.c
===================================================================
--- omp-expand.c (revision 249769)
+++ omp-expand.c (working copy)
@@ -1741,9 +1741,9 @@ expand_omp_for_init_counts (struct omp_f
entry_bb);
}
ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
- ne->probability = REG_BR_PROB_BASE / 2000 - 1;
+ ne->probability = profile_probability::very_unlikely ();
e->flags = EDGE_TRUE_VALUE;
- e->probability = REG_BR_PROB_BASE - ne->probability;
+ e->probability = ne->probability.invert ();
if (l2_dom_bb == NULL)
l2_dom_bb = entry_bb;
entry_bb = e->dest;
@@ -1920,7 +1920,7 @@ extract_omp_for_update_vars (struct omp_
if (i < fd->collapse - 1)
{
e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (1, 8);
t = fd->loops[i + 1].n1;
t = force_gimple_operand_gsi (&gsi, t,
@@ -1961,7 +1961,7 @@ extract_omp_for_update_vars (struct omp_
stmt = gimple_build_cond_empty (t);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
- e->probability = REG_BR_PROB_BASE * 7 / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
}
else
make_edge (bb, body_bb, EDGE_FALLTHRU);
@@ -2219,8 +2219,8 @@ expand_omp_ordered_sink (gimple_stmt_ite
GSI_CONTINUE_LINKING);
gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
- e3->probability = REG_BR_PROB_BASE / 8;
- e1->probability = REG_BR_PROB_BASE - e3->probability;
+ e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
+ e1->probability = e3->probability.invert ();
e1->flags = EDGE_TRUE_VALUE;
set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
@@ -2373,9 +2373,9 @@ expand_omp_for_ordered_loops (struct omp
remove_edge (e1);
make_edge (body_bb, new_header, EDGE_FALLTHRU);
e3->flags = EDGE_FALSE_VALUE;
- e3->probability = REG_BR_PROB_BASE / 8;
+ e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
- e1->probability = REG_BR_PROB_BASE - e3->probability;
+ e1->probability = e3->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
@@ -3149,8 +3149,8 @@ expand_omp_for_generic (struct omp_regio
e->flags = EDGE_TRUE_VALUE;
if (e)
{
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ find_edge (cont_bb, l2_bb)->probability = e->probability.invert ();
}
else
{
@@ -3351,9 +3351,9 @@ expand_omp_for_static_nochunk (struct om
ep = split_block (entry_bb, cond_stmt);
ep->flags = EDGE_TRUE_VALUE;
entry_bb = ep->dest;
- ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
+ ep->probability = profile_probability::very_likely ();
ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
- ep->probability = REG_BR_PROB_BASE / 2000 - 1;
+ ep->probability = profile_probability::very_unlikely ();
if (gimple_in_ssa_p (cfun))
{
int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
@@ -3634,10 +3634,10 @@ expand_omp_for_static_nochunk (struct om
/* Connect all the blocks. */
ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
- ep->probability = REG_BR_PROB_BASE / 4 * 3;
+ ep->probability = profile_probability::guessed_always ().apply_scale (3, 4);
ep = find_edge (entry_bb, second_bb);
ep->flags = EDGE_TRUE_VALUE;
- ep->probability = REG_BR_PROB_BASE / 4;
+ ep->probability = profile_probability::guessed_always ().apply_scale (1, 4);
find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
@@ -3835,9 +3835,9 @@ expand_omp_for_static_chunk (struct omp_
se = split_block (entry_bb, cond_stmt);
se->flags = EDGE_TRUE_VALUE;
entry_bb = se->dest;
- se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
+ se->probability = profile_probability::very_likely ();
se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
- se->probability = REG_BR_PROB_BASE / 2000 - 1;
+ se->probability = profile_probability::very_unlikely ();
if (gimple_in_ssa_p (cfun))
{
int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
@@ -4448,8 +4448,8 @@ expand_cilk_for (struct omp_region *regi
}
ne->flags = EDGE_FALSE_VALUE;
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- ne->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ ne->probability = e->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
@@ -4810,8 +4810,8 @@ expand_omp_simd (struct omp_region *regi
}
ne->flags = EDGE_FALSE_VALUE;
- e->probability = REG_BR_PROB_BASE * 7 / 8;
- ne->probability = REG_BR_PROB_BASE / 8;
+ e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
+ ne->probability = e->probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
@@ -4824,8 +4824,10 @@ expand_omp_simd (struct omp_region *regi
gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
make_edge (entry_bb, l2_bb, EDGE_FALSE_VALUE);
FALLTHRU_EDGE (entry_bb)->flags = EDGE_TRUE_VALUE;
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE * 7 / 8;
- BRANCH_EDGE (entry_bb)->probability = REG_BR_PROB_BASE / 8;
+ FALLTHRU_EDGE (entry_bb)->probability
+ = profile_probability::guessed_always ().apply_scale (7, 8);
+ BRANCH_EDGE (entry_bb)->probability
+ = FALLTHRU_EDGE (entry_bb)->probability.invert ();
l2_dom_bb = entry_bb;
}
set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
@@ -5018,9 +5020,9 @@ expand_omp_taskloop_for_outer (struct om
gsi = gsi_last_bb (exit_bb);
gsi_remove (&gsi, true);
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
remove_edge (BRANCH_EDGE (entry_bb));
- FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (cont_bb)->probability = profile_probability::always ();
remove_edge (BRANCH_EDGE (cont_bb));
set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
set_immediate_dominator (CDI_DOMINATORS, region->entry,
@@ -5208,7 +5210,7 @@ expand_omp_taskloop_for_inner (struct om
gsi = gsi_last_bb (exit_bb);
gsi_remove (&gsi, true);
- FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
+ FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
if (!broken_loop)
remove_edge (BRANCH_EDGE (entry_bb));
else
@@ -6604,8 +6606,11 @@ expand_omp_atomic_pipeline (basic_block
e = single_succ_edge (store_bb);
e->flags &= ~EDGE_FALLTHRU;
e->flags |= EDGE_FALSE_VALUE;
+ /* Expect no looping. */
+ e->probability = profile_probability::guessed_always ();
e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
+ e->probability = profile_probability::guessed_never ();
/* Copy the new value to loadedi (we already did that before the condition
if we are not in SSA). */
Index: omp-simd-clone.c
===================================================================
--- omp-simd-clone.c (revision 249769)
+++ omp-simd-clone.c (working copy)
@@ -1151,8 +1151,7 @@ simd_clone_adjust (struct cgraph_node *n
if (incr_bb)
{
- edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
+ make_single_succ_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
gsi = gsi_last_bb (incr_bb);
iter2 = make_ssa_name (iter);
g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
@@ -1264,7 +1263,10 @@ simd_clone_adjust (struct cgraph_node *n
redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
- make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+ edge new_e = make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+
+ /* FIXME: Do we need to distribute probabilities for the conditional? */
+ new_e->probability = profile_probability::guessed_never ();
/* The successor of incr_bb is already pointing to latch_bb; just
change the flags.
make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
Index: optabs.c
===================================================================
--- optabs.c (revision 249769)
+++ optabs.c (working copy)
@@ -693,7 +693,8 @@ expand_doubleword_shift (machine_mode op
NO_DEFER_POP;
do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
- 0, 0, subword_label, -1);
+ 0, 0, subword_label,
+ profile_probability::uninitialized ());
OK_DEFER_POP;
if (!expand_superword_shift (binoptab, outof_input, superword_op1,
@@ -3187,7 +3188,8 @@ expand_abs (machine_mode mode, rtx op0,
NO_DEFER_POP;
do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
- NULL_RTX, NULL, op1, -1);
+ NULL_RTX, NULL, op1,
+ profile_probability::uninitialized ());
op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
target, target, 0);
@@ -3979,7 +3981,8 @@ prepare_operand (enum insn_code icode, r
we can do the branch. */
static void
-emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
+emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+ profile_probability prob)
{
machine_mode optab_mode;
enum mode_class mclass;
@@ -3994,13 +3997,13 @@ emit_cmp_and_jump_insn_1 (rtx test, mach
gcc_assert (insn_operand_matches (icode, 0, test));
insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
XEXP (test, 1), label));
- if (prob != -1
+ if (prob.initialized_p ()
&& profile_status_for_fn (cfun) != PROFILE_ABSENT
&& insn
&& JUMP_P (insn)
&& any_condjump_p (insn)
&& !find_reg_note (insn, REG_BR_PROB, 0))
- add_int_reg_note (insn, REG_BR_PROB, prob);
+ add_int_reg_note (insn, REG_BR_PROB, prob.to_reg_br_prob_base ());
}
/* Generate code to compare X with Y so that the condition codes are
@@ -4025,7 +4028,7 @@ emit_cmp_and_jump_insn_1 (rtx test, mach
void
emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
machine_mode mode, int unsignedp, rtx label,
- int prob)
+ profile_probability prob)
{
rtx op0 = x, op1 = y;
rtx test;
@@ -5856,7 +5859,8 @@ expand_compare_and_swap_loop (rtx mem, r
/* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
- GET_MODE (success), 1, label, 0);
+ GET_MODE (success), 1, label,
+ profile_probability::guessed_never ());
return true;
}
Index: optabs.h
===================================================================
--- optabs.h (revision 249769)
+++ optabs.h (working copy)
@@ -247,7 +247,9 @@ extern rtx prepare_operand (enum insn_co
/* Emit a pair of rtl insns to compare two rtx's and to jump
to a label if the comparison is true. */
extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
- machine_mode, int, rtx, int prob=-1);
+ machine_mode, int, rtx,
+ profile_probability prob
+ = profile_probability::uninitialized ());
/* Generate code to indirectly jump to a location given in the rtx LOC. */
extern void emit_indirect_jump (rtx);
Index: predict.c
===================================================================
--- predict.c (revision 249769)
+++ predict.c (working copy)
@@ -404,11 +404,11 @@ optimize_loop_nest_for_size_p (struct lo
bool
predictable_edge_p (edge e)
{
- if (profile_status_for_fn (cfun) == PROFILE_ABSENT)
+ if (!e->probability.initialized_p ())
return false;
- if ((e->probability
+ if ((e->probability.to_reg_br_prob_base ()
<= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100)
- || (REG_BR_PROB_BASE - e->probability
+ || (REG_BR_PROB_BASE - e->probability.to_reg_br_prob_base ()
<= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100))
return true;
return false;
@@ -539,7 +539,7 @@ probability_reliable_p (int prob)
bool
edge_probability_reliable_p (const_edge e)
{
- return probability_reliable_p (e->probability);
+ return e->probability.reliable_p ();
}
/* Same predicate as edge_probability_reliable_p, working on notes. */
@@ -859,12 +859,13 @@ set_even_probabilities (basic_block bb,
if (!unlikely_executed_edge_p (e))
{
if (unlikely_edges != NULL && unlikely_edges->contains (e))
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
else
- e->probability = (REG_BR_PROB_BASE + c / 2) / c;
+ e->probability = profile_probability::guessed_always ()
+ .apply_scale (1, c);
}
else
- e->probability = 0;
+ e->probability = profile_probability::never ();
}
/* Combine all REG_BR_PRED notes into single probability and attach REG_BR_PROB
@@ -971,20 +972,23 @@ combine_predictions_for_insn (rtx_insn *
conditional jump. */
if (!single_succ_p (bb))
{
- BRANCH_EDGE (bb)->probability = combined_probability;
+ BRANCH_EDGE (bb)->probability
+ = profile_probability::from_reg_br_prob_base (combined_probability);
FALLTHRU_EDGE (bb)->probability
- = REG_BR_PROB_BASE - combined_probability;
+ = BRANCH_EDGE (bb)->probability.invert ();
}
}
else if (!single_succ_p (bb))
{
int prob = XINT (prob_note, 0);
- BRANCH_EDGE (bb)->probability = prob;
- FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
+ BRANCH_EDGE (bb)->probability
+ = profile_probability::from_reg_br_prob_base (prob);
+ FALLTHRU_EDGE (bb)->probability
+ = BRANCH_EDGE (bb)->probability.invert ();
}
else
- single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
+ single_succ_edge (bb)->probability = profile_probability::always ();
}
/* Edge prediction hash traits. */
@@ -1129,6 +1133,8 @@ combine_predictions_for_bb (basic_block
if (!first)
first = e;
}
+ else if (!e->probability.initialized_p ())
+ e->probability = profile_probability::never ();
/* When there is no successor or only one choice, prediction is easy.
@@ -1173,8 +1179,8 @@ combine_predictions_for_bb (basic_block
nedges, bb->index);
FOR_EACH_EDGE (e, ei, bb->succs)
if (!unlikely_executed_edge_p (e))
- dump_prediction (dump_file, PRED_COMBINED, e->probability,
- bb, REASON_NONE, e);
+ dump_prediction (dump_file, PRED_COMBINED,
+ e->probability.to_reg_br_prob_base (), bb, REASON_NONE, e);
}
}
return;
@@ -1284,8 +1290,9 @@ combine_predictions_for_bb (basic_block
if (!bb->count.initialized_p () && !dry_run)
{
- first->probability = combined_probability;
- second->probability = REG_BR_PROB_BASE - combined_probability;
+ first->probability
+ = profile_probability::from_reg_br_prob_base (combined_probability);
+ second->probability = first->probability.invert ();
}
}
@@ -3042,7 +3049,7 @@ propagate_freq (basic_block head, bitmap
* BLOCK_INFO (e->src)->frequency /
REG_BR_PROB_BASE); */
- sreal tmp = e->probability;
+ sreal tmp = e->probability.to_reg_br_prob_base ();
tmp *= BLOCK_INFO (e->src)->frequency;
tmp *= real_inv_br_prob_base;
frequency += tmp;
@@ -3074,7 +3081,7 @@ propagate_freq (basic_block head, bitmap
= ((e->probability * BLOCK_INFO (bb)->frequency)
/ REG_BR_PROB_BASE); */
- sreal tmp = e->probability;
+ sreal tmp = e->probability.to_reg_br_prob_base ();
tmp *= BLOCK_INFO (bb)->frequency;
EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base;
}
@@ -3534,7 +3541,7 @@ estimate_bb_frequencies (bool force)
mark_dfs_back_edges ();
single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->probability =
- REG_BR_PROB_BASE;
+ profile_probability::always ();
/* Set up block info for each basic block. */
alloc_aux_for_blocks (sizeof (block_info));
@@ -3546,7 +3553,8 @@ estimate_bb_frequencies (bool force)
FOR_EACH_EDGE (e, ei, bb->succs)
{
- EDGE_INFO (e)->back_edge_prob = e->probability;
+ EDGE_INFO (e)->back_edge_prob
+ = e->probability.to_reg_br_prob_base ();
EDGE_INFO (e)->back_edge_prob *= real_inv_br_prob_base;
}
}
@@ -3898,16 +3906,18 @@ void
force_edge_cold (edge e, bool impossible)
{
profile_count count_sum = profile_count::zero ();
- int prob_sum = 0;
+ profile_probability prob_sum = profile_probability::never ();
edge_iterator ei;
edge e2;
profile_count old_count = e->count;
- int old_probability = e->probability;
- int prob_scale = REG_BR_PROB_BASE;
+ profile_probability old_probability = e->probability;
bool uninitialized_exit = false;
+ profile_probability goal = (impossible ? profile_probability::never ()
+ : profile_probability::very_unlikely ());
+
/* If edge is already improbably or cold, just return. */
- if (e->probability <= (impossible ? PROB_VERY_UNLIKELY : 0)
+ if (e->probability <= goal
&& (!impossible || e->count == profile_count::zero ()))
return;
FOR_EACH_EDGE (e2, ei, e->src->succs)
@@ -3917,24 +3927,26 @@ force_edge_cold (edge e, bool impossible
count_sum += e2->count;
else
uninitialized_exit = true;
- prob_sum += e2->probability;
+ if (e2->probability.initialized_p ())
+ prob_sum += e2->probability;
}
/* If there are other edges out of e->src, redistribute probabilitity
there. */
- if (prob_sum)
+ if (prob_sum > profile_probability::never ())
{
- e->probability
- = MIN (e->probability, impossible ? 0 : PROB_VERY_UNLIKELY);
+ if (!(e->probability < goal))
+ e->probability = goal;
if (impossible)
e->count = profile_count::zero ();
- else if (old_probability)
- e->count = e->count.apply_scale (e->probability, old_probability);
+ else if (old_probability > profile_probability::never ())
+ e->count = e->count.apply_probability (e->probability
+ / old_probability);
else
e->count = e->count.apply_scale (1, REG_BR_PROB_BASE);
- prob_scale = RDIV ((REG_BR_PROB_BASE - e->probability) * REG_BR_PROB_BASE,
- prob_sum);
+ profile_probability prob_comp = prob_sum / e->probability.invert ();
+
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Making edge %i->%i %s by redistributing "
"probability to other edges.\n",
@@ -3946,15 +3958,14 @@ force_edge_cold (edge e, bool impossible
{
if (count_sum > 0)
e2->count.apply_scale (count_sum2, count_sum);
- e2->probability = RDIV (e2->probability * prob_scale,
- REG_BR_PROB_BASE);
+ e2->probability /= prob_comp;
}
}
/* If all edges out of e->src are unlikely, the basic block itself
is unlikely. */
else
{
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
if (e->src->count == profile_count::zero ())
return;
if (count_sum == profile_count::zero () && !uninitialized_exit
@@ -3989,7 +4000,8 @@ 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 == profile_count::zero ()
+ if (!(prob_sum > profile_probability::never ())
+ && count_sum == profile_count::zero ()
&& single_pred_p (e->src) && e->src->frequency > (impossible ? 0 : 1))
{
int old_frequency = e->src->frequency;
Index: profile-count.c
===================================================================
--- profile-count.c (revision 249769)
+++ profile-count.c (working copy)
@@ -31,6 +31,8 @@ along with GCC; see the file COPYING3.
#include "data-streamer.h"
#include "cgraph.h"
+/* Dump THIS to F. */
+
void
profile_count::dump (FILE *f) const
{
@@ -39,43 +41,53 @@ profile_count::dump (FILE *f) const
else
{
fprintf (f, "%" PRId64, m_val);
- if (m_quality == count_adjusted)
- fprintf (f, "(adjusted)");
- else if (m_quality == count_afdo)
- fprintf (f, "(auto FDO)");
- else if (m_quality == count_guessed)
- fprintf (f, "(guessed)");
+ if (m_quality == profile_adjusted)
+ fprintf (f, " (adjusted)");
+ else if (m_quality == profile_afdo)
+ fprintf (f, " (auto FDO)");
+ else if (m_quality == profile_guessed)
+ fprintf (f, " (guessed)");
}
}
+/* Dump THIS to stderr. */
+
void
profile_count::debug () const
{
dump (stderr);
+ fprintf (stderr, "\n");
}
+/* Return true if THIS differs from OTHER; tolerate small diferences. */
+
bool
profile_count::differs_from_p (profile_count other) const
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (m_val - other.m_val < 100 || other.m_val - m_val < 100)
+ if ((uint64_t)m_val - (uint64_t)other.m_val < 100
+ || (uint64_t)other.m_val - (uint64_t)m_val < 100)
return false;
if (!other.m_val)
return true;
- int64_t ratio = m_val * 100 / other.m_val;
+ int64_t ratio = (int64_t)m_val * 100 / other.m_val;
return ratio < 99 || ratio > 101;
}
+/* Stream THIS from IB. */
+
profile_count
profile_count::stream_in (struct lto_input_block *ib)
{
profile_count ret;
ret.m_val = streamer_read_gcov_count (ib);
- ret.m_quality = (profile_count_quality) streamer_read_uhwi (ib);
+ ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
return ret;
}
+/* Stream THIS to OB. */
+
void
profile_count::stream_out (struct output_block *ob)
{
@@ -83,9 +95,102 @@ profile_count::stream_out (struct output
streamer_write_uhwi (ob, m_quality);
}
+/* Stream THIS to OB. */
+
void
profile_count::stream_out (struct lto_output_stream *ob)
{
streamer_write_gcov_count_stream (ob, m_val);
streamer_write_uhwi_stream (ob, m_quality);
}
+
+/* Dump THIS to F. */
+
+void
+profile_probability::dump (FILE *f) const
+{
+ if (!initialized_p ())
+ fprintf (f, "uninitialized");
+ else
+ {
+ /* Make difference between 0.00 as a roundoff error and actual 0.
+ Similarly for 1. */
+ if (m_val == 0)
+ fprintf (f, "never");
+ else if (m_val == max_probability)
+ fprintf (f, "always");
+ else
+ fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
+ if (m_quality == profile_adjusted)
+ fprintf (f, " (adjusted)");
+ else if (m_quality == profile_afdo)
+ fprintf (f, " (auto FDO)");
+ else if (m_quality == profile_guessed)
+ fprintf (f, " (guessed)");
+ }
+}
+
+/* Dump THIS to stderr. */
+
+void
+profile_probability::debug () const
+{
+ dump (stderr);
+ fprintf (stderr, "\n");
+}
+
+/* Return true if THIS differs from OTHER; tolerate small diferences. */
+
+bool
+profile_probability::differs_from_p (profile_probability other) const
+{
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if ((uint64_t)m_val - (uint64_t)other.m_val < 10
+ || (uint64_t)other.m_val - (uint64_t)m_val < 10)
+ return false;
+ if (!other.m_val)
+ return true;
+ int64_t ratio = m_val * 100 / other.m_val;
+ return ratio < 99 || ratio > 101;
+}
+
+/* Return true if THIS differs significantly from OTHER. */
+
+bool
+profile_probability::differs_lot_from_p (profile_probability other) const
+{
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
+ return d > max_probability / 2;
+}
+
+/* Stream THIS from IB. */
+
+profile_probability
+profile_probability::stream_in (struct lto_input_block *ib)
+{
+ profile_probability ret;
+ ret.m_val = streamer_read_uhwi (ib);
+ ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
+ return ret;
+}
+
+/* Stream THIS to OB. */
+
+void
+profile_probability::stream_out (struct output_block *ob)
+{
+ streamer_write_uhwi (ob, m_val);
+ streamer_write_uhwi (ob, m_quality);
+}
+
+/* Stream THIS to OB. */
+
+void
+profile_probability::stream_out (struct lto_output_stream *ob)
+{
+ streamer_write_uhwi_stream (ob, m_val);
+ streamer_write_uhwi_stream (ob, m_quality);
+}
Index: profile-count.h
===================================================================
--- profile-count.h (revision 249769)
+++ profile-count.h (working copy)
@@ -23,19 +23,19 @@ along with GCC; see the file COPYING3.
/* Quality of the proflie count. Because gengtype does not support enums
inside of clases, this is in global namespace. */
-enum profile_count_quality {
+enum profile_quality {
/* Profile is based on static branch prediction heuristics. It may or may
not reflect the reality. */
- count_guessed = 0,
+ profile_guessed = 0,
/* Profile was determined by autofdo. */
- count_afdo = 1,
+ profile_afdo = 1,
/* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
- count_adjusted = 2,
+ profile_adjusted = 2,
/* Profile was read from profile feedback or determined by accurate static
method. */
- count_read = 3
+ profile_precise = 3
};
/* The base value for branch probability notes and edge probabilities. */
@@ -43,6 +43,422 @@ enum profile_count_quality {
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
+/* Data type to hold probabilities. It implement fixed point arithmetics
+ with capping so probability is always in range [0,1] and scaling requiring
+ values greater than 1 needs to be represented otherwise.
+
+ In addition to actual value the quality of profile is tracked and propagated
+ through all operations. Special value UNINITIALIZED is used for probabilities
+ that has not been detemrined yet (for example bacause of
+ -fno-guess-branch-probability)
+
+ Typically probabilities are derived from profile feedback (via
+ probability_in_gcov_type), autoFDO or guessed statically and then propagated
+ thorough the compilation.
+
+ Named probabilities are available:
+ - never (0 probability)
+ - guessed_never
+ - very_unlikely (1/2000 probability)
+ - unlikely (1/5 probablity)
+ - even (1/2 probability)
+ - likely (4/5 probability)
+ - very_likely (1999/2000 probability)
+ - guessed_always
+ - always
+
+ Named probabilities except for never/always are assumed to be statically
+ guessed and thus not necessarily acurate. The difference between never
+ and guessedn never is that the first one should be used only in case that
+ well behaving program will very likely not execute the "never" path.
+ For example if the path is going to abort () call or it exception handling.
+
+ Alawyas and guessted_always probabilities are symmetric.
+
+ For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
+ integer arithmetics. Once the code is converted to branch probabiitlies,
+ these conversions will probably go away because they are lossy.
+*/
+
+class GTY((user)) profile_probability
+{
+ /* For now use values in range 0...REG_BR_PROB_BASE. Later we can use full
+ precision of 30 bits available. */
+
+ static const int n_bits = 30;
+ static const uint32_t max_probability = REG_BR_PROB_BASE;
+ static const uint32_t uninitialized_probability = ((uint32_t) 1 << n_bits) - 1;
+
+ uint32_t m_val : 30;
+ enum profile_quality m_quality : 2;
+
+ friend class profile_count;
+public:
+
+ /* Named probabilities. */
+ static profile_probability never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+ static profile_probability guessed_never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ static profile_probability very_unlikely ()
+ {
+ /* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
+ profile_probability r
+ = profile_probability::always ().apply_scale (1, 2000);
+ r.m_val--;
+ return r;
+ }
+ static profile_probability unlikely ()
+ {
+ /* Be consistent with PROB_VERY_LIKELY in predict.h. */
+ profile_probability r
+ = profile_probability::always ().apply_scale (1, 5);
+ r.m_val--;
+ return r;
+ }
+ static profile_probability even ()
+ {
+ return profile_probability::always ().apply_scale (1, 2);
+ }
+ static profile_probability very_likely ()
+ {
+ return profile_probability::always () - very_unlikely ();
+ }
+ static profile_probability likely ()
+ {
+ return profile_probability::always () - unlikely ();
+ }
+ static profile_probability guessed_always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ static profile_probability always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+ /* Probabilities which has not been initialized. Either because
+ initialization did not happen yet or because profile is unknown. */
+ static profile_probability uninitialized ()
+ {
+ profile_probability c;
+ c.m_val = uninitialized_probability;
+ c.m_quality = profile_guessed;
+ return c;
+ }
+
+
+ /* Return true if value has been initialized. */
+ bool initialized_p () const
+ {
+ return m_val != uninitialized_probability;
+ }
+ /* Return true if value can be trusted. */
+ bool reliable_p () const
+ {
+ return initialized_p ();
+ }
+
+ /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
+ this is mostly to support legacy code and hsould go away. */
+ static profile_probability from_reg_br_prob_base (int v)
+ {
+ profile_probability ret;
+ gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
+ ret.m_val = RDIV (v * max_probability, REG_BR_PROB_BASE);
+ ret.m_quality = profile_guessed;
+ return ret;
+ }
+ int to_reg_br_prob_base () const
+ {
+ gcc_checking_assert (initialized_p ());
+ return RDIV (m_val * REG_BR_PROB_BASE, max_probability);
+ }
+
+ /* Return VAL1/VAL2. */
+ static profile_probability probability_in_gcov_type
+ (gcov_type val1, gcov_type val2)
+ {
+ profile_probability ret;
+ gcc_checking_assert (val1 >= 0 && val2 > 0);
+ if (val1 > val2)
+ ret.m_val = max_probability;
+ else
+ ret.m_val = RDIV (val1 * max_probability, val2);
+ ret.m_quality = profile_precise;
+ return ret;
+ }
+
+ /* Basic operations. */
+ bool operator== (const profile_probability &other) const
+ {
+ return m_val == other.m_val && m_quality == other.m_quality;
+ }
+ profile_probability operator+ (const profile_probability &other) const
+ {
+ if (other == profile_probability::never ())
+ return *this;
+ if (*this == profile_probability::never ())
+ return other;
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+
+ profile_probability ret;
+ ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator+= (const profile_probability &other)
+ {
+ if (other == profile_probability::never ())
+ return *this;
+ if (*this == profile_probability::never ())
+ {
+ *this = other;
+ return *this;
+ }
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator- (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator-= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator* (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator*= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ()
+ || other == profile_probability::never ())
+ return *this = profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+ profile_probability operator/ (const profile_probability &other) const
+ {
+ if (*this == profile_probability::never ())
+ return profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ if (m_val >= other.m_val)
+ ret.m_val = max_probability;
+ else if (!m_val)
+ ret.m_val = 0;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+ profile_probability &operator/= (const profile_probability &other)
+ {
+ if (*this == profile_probability::never ())
+ return *this = profile_probability::never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = profile_probability::uninitialized ();
+ else
+ {
+ if (m_val > other.m_val)
+ m_val = max_probability;
+ else if (!m_val)
+ ;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ gcov_type apply (gcov_type val) const
+ {
+ if (*this == profile_probability::uninitialized ())
+ return val / 2;
+ return RDIV (val * m_val, max_probability);
+ }
+
+ /* Return 1-*THIS. */
+ profile_probability invert () const
+ {
+ return profile_probability::always() - *this;
+ }
+
+ profile_probability combine_with_freq (int freq1, profile_probability other,
+ int freq2) const
+ {
+ profile_probability ret;
+
+ if (*this == profile_probability::uninitialized ()
+ || other == profile_probability::uninitialized ())
+ return profile_probability::uninitialized ();
+
+ gcc_checking_assert (freq1 >= 0 && freq2 >= 0);
+ if (!freq1 && !freq2)
+ {
+ ret.m_val = (m_val + other.m_val) / 2;
+ }
+ else
+ ret.m_val = RDIV (m_val * (uint64_t) freq1
+ + other.m_val * (uint64_t) freq2, freq1 + freq2);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ /* Return *THIS * NUM / DEN. */
+ profile_probability apply_scale (int64_t num, int64_t den) const
+ {
+ if (*this == profile_probability::never ())
+ return *this;
+ if (!initialized_p ())
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ ret.m_val = MIN (RDIV (m_val * num, den),
+ max_probability);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
+ return ret;
+ }
+
+ /* Return true when the probability of edge is reliable.
+
+ The profile guessing code is good at predicting branch outcome (ie.
+ taken/not taken), that is predicted right slightly over 75% of time.
+ It is however notoriously poor on predicting the probability itself.
+ In general the profile appear a lot flatter (with probabilities closer
+ to 50%) than the reality so it is bad idea to use it to drive optimization
+ such as those disabling dynamic branch prediction for well predictable
+ branches.
+
+ There are two exceptions - edges leading to noreturn edges and edges
+ predicted by number of iterations heuristics are predicted well. This macro
+ should be able to distinguish those, but at the moment it simply check for
+ noreturn heuristic that is only one giving probability over 99% or bellow
+ 1%. In future we might want to propagate reliability information across the
+ CFG if we find this information useful on multiple places. */
+
+ bool probably_reliable_p () const
+ {
+ if (m_quality >= profile_adjusted)
+ return true;
+ if (!initialized_p ())
+ return false;
+ return m_val < max_probability / 100
+ || m_val > max_probability - max_probability / 100;
+ }
+
+ /* Return false if profile_probability is bogus. */
+ bool verify () const
+ {
+ if (m_val == uninitialized_probability)
+ return m_quality == profile_guessed;
+ else
+ return m_val <= REG_BR_PROB_BASE;
+ }
+
+ /* Comparsions are three-state and conservative. False is returned if
+ the inequality can not be decided. */
+ bool operator< (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val < other.m_val;
+ }
+ bool operator> (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val > other.m_val;
+ }
+
+ bool operator<= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val <= other.m_val;
+ }
+ bool operator>= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val >= other.m_val;
+ }
+
+ /* Output THIS to F. */
+ void dump (FILE *f) const;
+
+ /* Print THIS to stderr. */
+ void debug () const;
+
+ /* Return true if THIS is known to differ significantly from OTHER. */
+ bool differs_from_p (profile_probability other) const;
+ /* Return if difference is greater than 50%. */
+ bool differs_lot_from_p (profile_probability other) const;
+
+ /* LTO streaming support. */
+ static profile_probability stream_in (struct lto_input_block *);
+ void stream_out (struct output_block *);
+ void stream_out (struct lto_output_stream *);
+};
+
/* Main data type to hold profile counters in GCC. In most cases profile
counts originate from profile feedback. They are 64bit integers
representing number of executions during the train run.
@@ -85,7 +501,7 @@ class GTY(()) profile_count
static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
uint64_t m_val : n_bits;
- enum profile_count_quality m_quality : 2;
+ enum profile_quality m_quality : 2;
/* Assume numbers smaller than this to multiply. This is set to make
testsuite pass, in future we may implement precise multiplication in higer
@@ -108,7 +524,7 @@ public:
{
profile_count c;
c.m_val = uninitialized_count;
- c.m_quality = count_guessed;
+ c.m_quality = profile_guessed;
return c;
}
@@ -120,7 +536,7 @@ public:
profile_count ret;
gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
ret.m_val = v;
- ret.m_quality = count_read;
+ ret.m_quality = profile_precise;
return ret;
}
@@ -207,7 +623,7 @@ public:
/* Return false if profile_count is bogus. */
bool verify () const
{
- return m_val != uninitialized_count || m_quality == count_guessed;
+ return m_val != uninitialized_count || m_quality == profile_guessed;
}
/* Comparsions are three-state and conservative. False is returned if
@@ -237,7 +653,7 @@ public:
}
bool operator>= (const profile_count &other) const
{
- return initialized_p () && m_val >= other.m_val;
+ return initialized_p () && other.initialized_p () && m_val >= other.m_val;
}
bool operator<= (const gcov_type other) const
{
@@ -261,7 +677,23 @@ public:
return profile_count::uninitialized ();
profile_count ret;
ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
+ return ret;
+ }
+
+ /* Scale counter according to PROB. */
+ profile_count apply_probability (profile_probability prob) const
+ {
+ if (*this == profile_count::zero ())
+ return *this;
+ if (prob == profile_probability::never ())
+ return profile_count::zero ();
+ if (!initialized_p ())
+ return profile_count::uninitialized ();
+ profile_count ret;
+ ret.m_val = RDIV (m_val * prob.m_val,
+ profile_probability::max_probability);
+ ret.m_quality = MIN (m_quality, prob.m_quality);
return ret;
}
/* Return *THIS * NUM / DEN. */
@@ -277,7 +709,7 @@ public:
gcc_checking_assert ((num <= REG_BR_PROB_BASE
|| den <= REG_BR_PROB_BASE) || 1);
ret.m_val = RDIV (m_val * num, den);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
return ret;
}
profile_count apply_scale (profile_count num, profile_count den) const
@@ -299,23 +731,27 @@ public:
else
ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
den.m_val), max_safe_multiplier);
- ret.m_quality = MIN (m_quality, count_adjusted);
+ ret.m_quality = MIN (m_quality, profile_adjusted);
return ret;
}
/* Return probability of event with counter THIS within event with counter
OVERALL. */
- int probability_in (profile_count overall)
+ profile_probability probability_in (const profile_count overall) const
{
if (!m_val)
- return 0;
- if (!initialized_p () || !overall.initialized_p ())
- return REG_BR_PROB_BASE / 2;
- if (overall < *this)
- return REG_BR_PROB_BASE;
- if (!overall.m_val)
- return REG_BR_PROB_BASE / 2;
- return RDIV (m_val * REG_BR_PROB_BASE, overall.m_val);
+ return profile_probability::never ();
+ if (!initialized_p () || !overall.initialized_p ()
+ || !overall.m_val)
+ return profile_probability::uninitialized ();
+ profile_probability ret;
+ if (overall < m_val)
+ ret.m_val = profile_probability::max_probability;
+ else
+ ret.m_val = RDIV (m_val * profile_probability::max_probability,
+ overall.m_val);
+ ret.m_quality = MIN (m_quality, overall.m_quality);
+ return ret;
}
/* Output THIS to F. */
Index: profile.c
===================================================================
--- profile.c (revision 249769)
+++ profile.c (working copy)
@@ -768,8 +768,8 @@ compute_branch_probabilities (unsigned c
if (bb_gcov_count (bb))
{
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = GCOV_COMPUTE_SCALE (edge_gcov_count (e),
- bb_gcov_count (bb));
+ e->probability = profile_probability::probability_in_gcov_type
+ (edge_gcov_count (e), bb_gcov_count (bb));
if (bb->index >= NUM_FIXED_BLOCKS
&& block_ends_with_condjump_p (bb)
&& EDGE_COUNT (bb->succs) >= 2)
@@ -784,7 +784,7 @@ compute_branch_probabilities (unsigned c
if (!(e->flags & (EDGE_FAKE | EDGE_FALLTHRU)))
break;
- prob = e->probability;
+ prob = e->probability.to_reg_br_prob_base ();
index = prob * 20 / REG_BR_PROB_BASE;
if (index == 20)
@@ -810,15 +810,17 @@ compute_branch_probabilities (unsigned c
{
FOR_EACH_EDGE (e, ei, bb->succs)
if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
- e->probability = REG_BR_PROB_BASE / total;
+ e->probability
+ = profile_probability::guessed_always ().apply_scale (1, total);
else
- e->probability = 0;
+ e->probability = profile_probability::never ();
}
else
{
total += EDGE_COUNT (bb->succs);
FOR_EACH_EDGE (e, ei, bb->succs)
- e->probability = REG_BR_PROB_BASE / total;
+ e->probability
+ = profile_probability::guessed_always ().apply_scale (1, total);
}
if (bb->index >= NUM_FIXED_BLOCKS
&& block_ends_with_condjump_p (bb)
Index: recog.c
===================================================================
--- recog.c (revision 249769)
+++ recog.c (working copy)
@@ -3460,8 +3460,7 @@ peep2_attempt (basic_block bb, rtx_insn
flags);
nehe->probability = eh_edge->probability;
- nfte->probability
- = REG_BR_PROB_BASE - nehe->probability;
+ nfte->probability = nehe->probability.invert ();
peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
bb = nfte->src;
Index: sched-ebb.c
===================================================================
--- sched-ebb.c (revision 249769)
+++ sched-ebb.c (working copy)
@@ -648,7 +648,8 @@ schedule_ebbs (void)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability <= probability_cutoff)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () <= probability_cutoff)
break;
if (e->dest->flags & BB_DISABLE_SCHEDULE)
break;
Index: sched-rgn.c
===================================================================
--- sched-rgn.c (revision 249769)
+++ sched-rgn.c (working copy)
@@ -507,7 +507,8 @@ find_single_block_region (bool ebbs_p)
e = find_fallthru_edge (bb->succs);
if (! e)
break;
- if (e->probability <= probability_cutoff)
+ if (e->probability.initialized_p ()
+ && e->probability.to_reg_br_prob_base () <= probability_cutoff)
break;
}
@@ -1441,7 +1442,11 @@ compute_dom_prob_ps (int bb)
FOR_EACH_EDGE (out_edge, out_ei, in_edge->src->succs)
bitmap_set_bit (pot_split[bb], EDGE_TO_BIT (out_edge));
- prob[bb] += combine_probabilities (prob[pred_bb], in_edge->probability);
+ prob[bb] += combine_probabilities
+ (prob[pred_bb],
+ in_edge->probability.initialized_p ()
+ ? in_edge->probability.to_reg_br_prob_base ()
+ : 0);
// The rounding divide in combine_probabilities can result in an extra
// probability increment propagating along 50-50 edges. Eventually when
// the edges re-merge, the accumulated probability can go slightly above
@@ -3171,8 +3176,10 @@ schedule_region (int rgn)
sched_rgn_n_insns += sched_n_insns;
realloc_bb_state_array (saved_last_basic_block);
f = find_fallthru_edge (last_bb->succs);
- if (f && f->probability * 100 / REG_BR_PROB_BASE >=
- PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF))
+ if (f
+ && (!f->probability.initialized_p ()
+ || f->probability.to_reg_br_prob_base () * 100 / REG_BR_PROB_BASE >=
+ PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF)))
{
memcpy (bb_state[f->dest->index], curr_state,
dfa_state_size);
Index: sel-sched-ir.c
===================================================================
--- sel-sched-ir.c (revision 249769)
+++ sel-sched-ir.c (working copy)
@@ -4747,7 +4747,9 @@ compute_succs_info (insn_t insn, short f
sinfo->probs_ok.safe_push (
/* FIXME: Improve calculation when skipping
inner loop to exits. */
- si.bb_end ? si.e1->probability : REG_BR_PROB_BASE);
+ si.bb_end && si.e1->probability.initialized_p ()
+ ? si.e1->probability.to_reg_br_prob_base ()
+ : REG_BR_PROB_BASE);
sinfo->succs_ok_n++;
}
else
@@ -4756,8 +4758,8 @@ compute_succs_info (insn_t insn, short f
/* Compute all_prob. */
if (!si.bb_end)
sinfo->all_prob = REG_BR_PROB_BASE;
- else
- sinfo->all_prob += si.e1->probability;
+ else if (si.e1->probability.initialized_p ())
+ sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
sinfo->all_succs_n++;
}
Index: stmt.c
===================================================================
--- stmt.c (revision 249769)
+++ stmt.c (working copy)
@@ -93,9 +93,9 @@ struct case_node
tree low; /* Lowest index value for this label */
tree high; /* Highest index value for this label */
tree code_label; /* Label to jump to when node matches */
- int prob; /* Probability of taking this case. */
+ profile_probability prob; /* Probability of taking this case. */
/* Probability of reaching subtree rooted at this node */
- int subtree_prob;
+ profile_probability subtree_prob;
};
typedef struct case_node *case_node_ptr;
@@ -108,7 +108,8 @@ static void balance_case_nodes (case_nod
static int node_has_low_bound (case_node_ptr, tree);
static int node_has_high_bound (case_node_ptr, tree);
static int node_is_bounded (case_node_ptr, tree);
-static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *, int, tree);
+static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *,
+ profile_probability, tree);
\f
/* Return the rtx-label that corresponds to a LABEL_DECL,
creating it if necessary. */
@@ -704,9 +705,8 @@ expand_naked_return (void)
is the probability of jumping to LABEL. */
static void
do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
- int unsignedp, int prob)
+ int unsignedp, profile_probability prob)
{
- gcc_assert (prob <= REG_BR_PROB_BASE);
do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
NULL_RTX, NULL, label, prob);
}
@@ -722,7 +722,7 @@ do_jump_if_equal (machine_mode mode, rtx
static struct case_node *
add_case_node (struct case_node *head, tree low, tree high,
- tree label, int prob,
+ tree label, profile_probability prob,
object_allocator<case_node> &case_node_pool)
{
struct case_node *r;
@@ -859,7 +859,7 @@ expand_switch_as_decision_tree_p (tree r
static void
emit_case_decision_tree (tree index_expr, tree index_type,
case_node_ptr case_list, rtx_code_label *default_label,
- int default_prob)
+ profile_probability default_prob)
{
rtx index = expand_normal (index_expr);
@@ -902,14 +902,14 @@ emit_case_decision_tree (tree index_expr
/* Return the sum of probabilities of outgoing edges of basic block BB. */
-static int
+static profile_probability
get_outgoing_edge_probs (basic_block bb)
{
edge e;
edge_iterator ei;
- int prob_sum = 0;
+ profile_probability prob_sum = profile_probability::never ();
if (!bb)
- return 0;
+ return profile_probability::never ();
FOR_EACH_EDGE (e, ei, bb->succs)
prob_sum += e->probability;
return prob_sum;
@@ -922,16 +922,11 @@ get_outgoing_edge_probs (basic_block bb)
BASE_PROB is the probability of reaching the branch instruction relative
to the same basic block BB. */
-static inline int
-conditional_probability (int target_prob, int base_prob)
+static inline profile_probability
+conditional_probability (profile_probability target_prob,
+ profile_probability base_prob)
{
- if (base_prob > 0)
- {
- gcc_assert (target_prob >= 0);
- gcc_assert (target_prob <= base_prob);
- return GCOV_COMPUTE_SCALE (target_prob, base_prob);
- }
- return -1;
+ return target_prob / base_prob;
}
/* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
@@ -960,12 +955,13 @@ emit_case_dispatch_table (tree index_exp
rtx_code_label *table_label = gen_label_rtx ();
bool has_gaps = false;
edge default_edge = stmt_bb ? EDGE_SUCC (stmt_bb, 0) : NULL;
- int default_prob = default_edge ? default_edge->probability : 0;
- int base = get_outgoing_edge_probs (stmt_bb);
+ profile_probability default_prob = default_edge ? default_edge->probability
+ : profile_probability::never ();
+ profile_probability base = get_outgoing_edge_probs (stmt_bb);
bool try_with_tablejump = false;
- int new_default_prob = conditional_probability (default_prob,
- base);
+ profile_probability new_default_prob = conditional_probability (default_prob,
+ base);
if (! try_casesi (index_type, index_expr, minval, range,
table_label, default_label, fallback_label,
@@ -1030,15 +1026,16 @@ emit_case_dispatch_table (tree index_exp
through the indirect jump or the direct conditional jump
before that. Split the probability of reaching the
default label among these two jumps. */
- new_default_prob = conditional_probability (default_prob/2,
+ new_default_prob = conditional_probability (default_prob.apply_scale
+ (1, 2),
base);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
base -= default_prob;
}
else
{
base -= default_prob;
- default_prob = 0;
+ default_prob = profile_probability::never ();
}
if (default_edge)
@@ -1047,12 +1044,12 @@ emit_case_dispatch_table (tree index_exp
/* We have altered the probability of the default edge. So the probabilities
of all other edges need to be adjusted so that it sums up to
REG_BR_PROB_BASE. */
- if (base)
+ if (base > profile_probability::never ())
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, stmt_bb->succs)
- e->probability = GCOV_COMPUTE_SCALE (e->probability, base);
+ e->probability /= base;
}
if (try_with_tablejump)
@@ -1150,7 +1147,7 @@ expand_case (gswitch *stmt)
default_label = jump_target_rtx
(CASE_LABEL (gimple_switch_default_label (stmt)));
edge default_edge = EDGE_SUCC (bb, 0);
- int default_prob = default_edge->probability;
+ profile_probability default_prob = default_edge->probability;
/* Get upper and lower bounds of case values. */
elt = gimple_switch_label (stmt, 1);
@@ -1213,7 +1210,7 @@ expand_case (gswitch *stmt)
edge case_edge = find_edge (bb, case_bb);
case_list = add_case_node (
case_list, low, high, lab,
- case_edge->probability / (intptr_t)(case_edge->aux),
+ case_edge->probability.apply_scale (1, (intptr_t)(case_edge->aux)),
case_node_pool);
}
reset_out_edges_aux (bb);
@@ -1310,7 +1307,8 @@ expand_sjlj_dispatch_table (rtx dispatch
{
tree elt = dispatch_table[i];
rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt));
- do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
+ do_jump_if_equal (index_mode, index, zero, lab, 0,
+ profile_probability::uninitialized ());
force_expand_binop (index_mode, sub_optab,
index, CONST1_RTX (index_mode),
index, 0, OPTAB_DIRECT);
@@ -1332,7 +1330,10 @@ expand_sjlj_dispatch_table (rtx dispatch
tree elt = dispatch_table[i];
tree low = CASE_LOW (elt);
tree lab = CASE_LABEL (elt);
- case_list = add_case_node (case_list, low, low, lab, 0, case_node_pool);
+ case_list = add_case_node (case_list, low, low, lab,
+ profile_probability::guessed_always ()
+ .apply_scale (1, ncases),
+ case_node_pool);
}
emit_case_dispatch_table (index_expr, index_type,
@@ -1576,12 +1577,12 @@ node_is_bounded (case_node_ptr node, tre
static void
emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
- int default_prob, tree index_type)
+ profile_probability default_prob, tree index_type)
{
/* If INDEX has an unsigned type, we must make unsigned branches. */
int unsignedp = TYPE_UNSIGNED (index_type);
- int probability;
- int prob = node->prob, subtree_prob = node->subtree_prob;
+ profile_probability probability;
+ profile_probability prob = node->prob, subtree_prob = node->subtree_prob;
machine_mode mode = GET_MODE (index);
machine_mode imode = TYPE_MODE (index_type);
@@ -1701,7 +1702,7 @@ emit_case_nodes (rtx index, case_node_pt
subtree or the left subtree. Divide the probability
equally. */
probability = conditional_probability (
- node->right->subtree_prob + default_prob/2,
+ node->right->subtree_prob + default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
/* See if the value is on the right. */
emit_cmp_and_jump_insns (index,
@@ -1712,7 +1713,7 @@ emit_case_nodes (rtx index, case_node_pt
GT, NULL_RTX, mode, unsignedp,
label_rtx (test_label),
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
/* Value must be on the left.
Handle the left-hand subtree. */
@@ -1743,7 +1744,7 @@ emit_case_nodes (rtx index, case_node_pt
if (!node_has_low_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1753,7 +1754,7 @@ emit_case_nodes (rtx index, case_node_pt
LT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
emit_case_nodes (index, node->right, default_label, default_prob, index_type);
@@ -1785,7 +1786,7 @@ emit_case_nodes (rtx index, case_node_pt
if (!node_has_high_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1795,7 +1796,7 @@ emit_case_nodes (rtx index, case_node_pt
GT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
emit_case_nodes (index, node->left, default_label,
@@ -1858,7 +1859,7 @@ emit_case_nodes (rtx index, case_node_pt
test_label = build_decl (curr_insn_location (),
LABEL_DECL, NULL_TREE, void_type_node);
probability = conditional_probability (
- node->right->subtree_prob + default_prob/2,
+ node->right->subtree_prob + default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1868,7 +1869,7 @@ emit_case_nodes (rtx index, case_node_pt
GT, NULL_RTX, mode, unsignedp,
label_rtx (test_label),
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the left-hand subtree. */
@@ -1909,7 +1910,7 @@ emit_case_nodes (rtx index, case_node_pt
if (!node_has_low_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1919,7 +1920,7 @@ emit_case_nodes (rtx index, case_node_pt
LT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the right-hand subtree. */
@@ -1946,7 +1947,7 @@ emit_case_nodes (rtx index, case_node_pt
if (!node_has_high_bound (node, index_type))
{
probability = conditional_probability (
- default_prob/2,
+ default_prob.apply_scale (1, 2),
subtree_prob + default_prob);
emit_cmp_and_jump_insns (index,
convert_modes
@@ -1956,7 +1957,7 @@ emit_case_nodes (rtx index, case_node_pt
GT, NULL_RTX, mode, unsignedp,
default_label,
probability);
- default_prob /= 2;
+ default_prob = default_prob.apply_scale (1, 2);
}
/* Value belongs to this node or to the left-hand subtree. */
Index: targhooks.c
===================================================================
--- targhooks.c (revision 249769)
+++ targhooks.c (working copy)
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.
#include "stringpool.h"
#include "tree-vrp.h"
#include "tree-ssanames.h"
+#include "profile-count.h"
#include "optabs.h"
#include "regs.h"
#include "recog.h"
Index: tracer.c
===================================================================
--- tracer.c (revision 249769)
+++ tracer.c (working copy)
@@ -135,10 +135,8 @@ better_p (const_edge e1, const_edge e2)
if (e1->count.initialized_p () && e2->count.initialized_p ()
&& !(e1->count == e2->count))
return e1->count > e2->count;
- if (e1->src->frequency * e1->probability !=
- e2->src->frequency * e2->probability)
- return (e1->src->frequency * e1->probability
- > e2->src->frequency * e2->probability);
+ if (EDGE_FREQUENCY (e1) != EDGE_FREQUENCY (e2))
+ return EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2);
/* This is needed to avoid changes in the decision after
CFG is modified. */
if (e1->src != e2->src)
@@ -160,7 +158,8 @@ find_best_successor (basic_block bb)
best = e;
if (!best || ignore_bb_p (best->dest))
return NULL;
- if (best->probability <= probability_cutoff)
+ if (best->probability.initialized_p ()
+ && best->probability.to_reg_br_prob_base () <= probability_cutoff)
return NULL;
return best;
}
Index: trans-mem.c
===================================================================
--- trans-mem.c (revision 249769)
+++ trans-mem.c (working copy)
@@ -2934,9 +2934,9 @@ expand_transaction (struct tm_region *re
join_bb->frequency = test_bb->frequency = transaction_bb->frequency;
join_bb->count = test_bb->count = transaction_bb->count;
- ei->probability = PROB_ALWAYS;
- et->probability = PROB_LIKELY;
- ef->probability = PROB_UNLIKELY;
+ ei->probability = profile_probability::always ();
+ et->probability = profile_probability::likely ();
+ ef->probability = profile_probability::unlikely ();
et->count = test_bb->count.apply_probability (et->probability);
ef->count = test_bb->count.apply_probability (ef->probability);
@@ -2967,20 +2967,20 @@ expand_transaction (struct tm_region *re
edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU);
test_bb->frequency = transaction_bb->frequency;
test_bb->count = transaction_bb->count;
- ei->probability = PROB_ALWAYS;
+ ei->probability = profile_probability::always ();
// Not abort edge. If both are live, chose one at random as we'll
// we'll be fixing that up below.
redirect_edge_pred (fallthru_edge, test_bb);
fallthru_edge->flags = EDGE_FALSE_VALUE;
- fallthru_edge->probability = PROB_VERY_LIKELY;
+ fallthru_edge->probability = profile_probability::very_likely ();
fallthru_edge->count = test_bb->count.apply_probability
(fallthru_edge->probability);
// Abort/over edge.
redirect_edge_pred (abort_edge, test_bb);
abort_edge->flags = EDGE_TRUE_VALUE;
- abort_edge->probability = PROB_VERY_UNLIKELY;
+ abort_edge->probability = profile_probability::unlikely ();
abort_edge->count = test_bb->count.apply_probability
(abort_edge->probability);
@@ -3020,13 +3020,13 @@ expand_transaction (struct tm_region *re
// use the uninst path when falling back to serial mode.
redirect_edge_pred (inst_edge, test_bb);
inst_edge->flags = EDGE_FALSE_VALUE;
- inst_edge->probability = REG_BR_PROB_BASE / 2;
+ inst_edge->probability = profile_probability::even ();
inst_edge->count
= test_bb->count.apply_probability (inst_edge->probability);
redirect_edge_pred (uninst_edge, test_bb);
uninst_edge->flags = EDGE_TRUE_VALUE;
- uninst_edge->probability = REG_BR_PROB_BASE / 2;
+ uninst_edge->probability = profile_probability::even ();
uninst_edge->count
= test_bb->count.apply_probability (uninst_edge->probability);
}
Index: tree-call-cdce.c
===================================================================
--- tree-call-cdce.c (revision 249769)
+++ tree-call-cdce.c (working copy)
@@ -752,10 +752,6 @@ gen_shrink_wrap_conditions (gcall *bi_ca
return;
}
-
-/* Probability of the branch (to the call) is taken. */
-#define ERR_PROB 0.01
-
/* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
conditions in CONDS is false. */
@@ -916,14 +912,15 @@ shrink_wrap_one_built_in_call_with_conds
basic_block src_bb = call_edge->src;
gcc_assert (src_bb == nocall_edge->src);
- call_edge->probability = REG_BR_PROB_BASE * ERR_PROB;
+ call_edge->probability = profile_probability::very_unlikely ();
call_edge->count
= src_bb->count.apply_probability (call_edge->probability);
- nocall_edge->probability = inverse_probability (call_edge->probability);
+ nocall_edge->probability = profile_probability::always ()
+ - call_edge->probability;
nocall_edge->count = src_bb->count - call_edge->count;
- unsigned int call_frequency = apply_probability (src_bb->frequency,
- call_edge->probability);
+ unsigned int call_frequency
+ = call_edge->probability.apply (src_bb->frequency);
bi_call_bb->count += call_edge->count;
bi_call_bb->frequency += call_frequency;
Index: tree-cfg.c
===================================================================
--- tree-cfg.c (revision 249769)
+++ tree-cfg.c (working copy)
@@ -2837,9 +2837,7 @@ gimple_split_edge (edge edge_in)
new_bb = create_empty_bb (after_bb);
new_bb->frequency = EDGE_FREQUENCY (edge_in);
new_bb->count = edge_in->count;
- new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
- new_edge->probability = REG_BR_PROB_BASE;
- new_edge->count = edge_in->count;
+ new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU);
e = redirect_edge_and_branch (edge_in, new_bb);
gcc_assert (e == edge_in);
@@ -7244,7 +7242,7 @@ move_sese_region_to_fn (struct function
basic_block after, bb, *entry_pred, *exit_succ, abb;
struct function *saved_cfun = cfun;
int *entry_flag, *exit_flag;
- unsigned *entry_prob, *exit_prob;
+ profile_probability *entry_prob, *exit_prob;
unsigned i, num_entry_edges, num_exit_edges, num_nodes;
edge e;
edge_iterator ei;
@@ -7282,7 +7280,7 @@ move_sese_region_to_fn (struct function
num_entry_edges = EDGE_COUNT (entry_bb->preds);
entry_pred = XNEWVEC (basic_block, num_entry_edges);
entry_flag = XNEWVEC (int, num_entry_edges);
- entry_prob = XNEWVEC (unsigned, num_entry_edges);
+ entry_prob = XNEWVEC (profile_probability, num_entry_edges);
i = 0;
for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;)
{
@@ -7297,7 +7295,7 @@ move_sese_region_to_fn (struct function
num_exit_edges = EDGE_COUNT (exit_bb->succs);
exit_succ = XNEWVEC (basic_block, num_exit_edges);
exit_flag = XNEWVEC (int, num_exit_edges);
- exit_prob = XNEWVEC (unsigned, num_exit_edges);
+ exit_prob = XNEWVEC (profile_probability, num_exit_edges);
i = 0;
for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
{
Index: tree-cfgcleanup.c
===================================================================
--- tree-cfgcleanup.c (revision 249769)
+++ tree-cfgcleanup.c (working copy)
@@ -155,8 +155,6 @@ cleanup_control_expr_graph (basic_block
}
if (!warned)
fold_undefer_and_ignore_overflow_warnings ();
- if (taken_edge->probability > REG_BR_PROB_BASE)
- taken_edge->probability = REG_BR_PROB_BASE;
}
else
taken_edge = single_succ_edge (bb);
Index: tree-eh.c
===================================================================
--- tree-eh.c (revision 249769)
+++ tree-eh.c (working copy)
@@ -3244,9 +3244,7 @@ lower_resx (basic_block bb, gresx *stmt,
}
gcc_assert (EDGE_COUNT (bb->succs) == 0);
- e = make_edge (bb, new_bb, EDGE_FALLTHRU);
- e->count = bb->count;
- e->probability = REG_BR_PROB_BASE;
+ e = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
}
else
{
@@ -3262,7 +3260,7 @@ lower_resx (basic_block bb, gresx *stmt,
e = single_succ_edge (bb);
gcc_assert (e->flags & EDGE_EH);
e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU;
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
/* If there are no more EH users of the landing pad, delete it. */
@@ -4283,7 +4281,7 @@ cleanup_empty_eh_move_lp (basic_block bb
/* Clean up E_OUT for the fallthru. */
e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU;
- e_out->probability = REG_BR_PROB_BASE;
+ e_out->probability = profile_probability::always ();
e_out->count = e_out->src->count;
}
Index: tree-if-conv.c
===================================================================
--- tree-if-conv.c (revision 249769)
+++ tree-if-conv.c (working copy)
@@ -2564,7 +2564,8 @@ version_loop_for_if_conversion (struct l
/* At this point we invalidate porfile confistency until IFN_LOOP_VECTORIZED
is re-merged in the vectorizer. */
new_loop = loop_version (loop, cond, &cond_bb,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE,
+ profile_probability::always (),
+ profile_probability::always (),
REG_BR_PROB_BASE, REG_BR_PROB_BASE, true);
free_original_copy_tables ();
Index: tree-inline.c
===================================================================
--- tree-inline.c (revision 249769)
+++ tree-inline.c (working copy)
@@ -2291,10 +2291,44 @@ copy_edges_for_bb (basic_block bb, profi
}
}
+ bool update_probs = false;
+
if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH)
- make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
+ {
+ make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
+ update_probs = true;
+ }
else if (can_throw)
- make_eh_edges (copy_stmt);
+ {
+ make_eh_edges (copy_stmt);
+ update_probs = true;
+ }
+
+ /* EH edges may not match old edges. Copy as much as possible. */
+ if (update_probs)
+ {
+ edge e;
+ edge_iterator ei;
+ basic_block copy_stmt_bb = gimple_bb (copy_stmt);
+
+ FOR_EACH_EDGE (old_edge, ei, bb->succs)
+ if ((old_edge->flags & EDGE_EH)
+ && (e = find_edge (copy_stmt_bb,
+ (basic_block) old_edge->dest->aux))
+ && (e->flags & EDGE_EH))
+ {
+ e->probability = old_edge->probability;
+ e->count = old_edge->count;
+ }
+
+ FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
+ if ((e->flags & EDGE_EH) && !e->probability.initialized_p ())
+ {
+ e->probability = profile_probability::never ();
+ e->count = profile_count::zero ();
+ }
+ }
+
/* If the call we inline cannot make abnormal goto do not add
additional abnormal edges but only retain those already present
@@ -2317,7 +2351,8 @@ copy_edges_for_bb (basic_block bb, profi
&& gimple_call_arg (copy_stmt, 0) == boolean_true_node)
nonlocal_goto = false;
else
- make_edge (copy_stmt_bb, abnormal_goto_dest, EDGE_ABNORMAL);
+ make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest,
+ EDGE_ABNORMAL);
}
if ((can_throw || nonlocal_goto)
@@ -2789,7 +2824,7 @@ copy_cfg_body (copy_body_data * id, prof
if (new_entry)
{
edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = incoming_count;
}
Index: tree-parloops.c
===================================================================
--- tree-parloops.c (revision 249769)
+++ tree-parloops.c (working copy)
@@ -2115,10 +2115,12 @@ create_parallel_loop (struct loop *loop,
gcc_assert (exit == single_dom_exit (loop));
guard = make_edge (for_bb, ex_bb, 0);
+ /* FIXME: What is the probability? */
+ guard->probability = profile_probability::guessed_never ();
/* Split the latch edge, so LOOPS_HAVE_SIMPLE_LATCHES is still valid. */
loop->latch = split_edge (single_succ_edge (loop->latch));
single_pred_edge (loop->latch)->flags = 0;
- end = make_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
+ end = make_single_succ_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
rescan_loop_exit (end, true, false);
for (gphi_iterator gpi = gsi_start_phis (ex_bb);
@@ -2358,7 +2360,9 @@ gen_parallel_loop (struct loop *loop,
/* We assume that the loop usually iterates a lot. */
prob = 4 * REG_BR_PROB_BASE / 5;
loop_version (loop, many_iterations_cond, NULL,
- prob, REG_BR_PROB_BASE - prob,
+ profile_probability::from_reg_br_prob_base (prob),
+ profile_probability::from_reg_br_prob_base
+ (REG_BR_PROB_BASE - prob),
prob, REG_BR_PROB_BASE - prob, true);
update_ssa (TODO_update_ssa);
free_original_copy_tables ();
@@ -3132,6 +3136,8 @@ oacc_entry_exit_single_gang (bitmap in_l
gsi_insert_after (&gsi2, cond, GSI_NEW_STMT);
edge e3 = make_edge (bb, bb3, EDGE_FALSE_VALUE);
+ /* FIXME: What is the probability? */
+ e3->probability = profile_probability::guessed_never ();
e->flags = EDGE_TRUE_VALUE;
tree vdef = gimple_vdef (stmt);
Index: tree-profile.c
===================================================================
--- tree-profile.c (revision 249769)
+++ tree-profile.c (working copy)
@@ -436,16 +436,16 @@ gimple_gen_ic_func_profiler (void)
edge true_edge = single_succ_edge (cond_bb);
true_edge->flags = EDGE_TRUE_VALUE;
- int probability;
+ profile_probability probability;
if (DECL_VIRTUAL_P (current_function_decl))
- probability = PROB_VERY_LIKELY;
+ probability = profile_probability::very_likely ();
else
- probability = PROB_UNLIKELY;
+ probability = profile_probability::unlikely ();
true_edge->probability = probability;
edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE - true_edge->probability;
+ e->probability = true_edge->probability.invert ();
/* Insert code:
@@ -497,10 +497,10 @@ gimple_gen_time_profiler (unsigned tag,
edge true_edge = single_succ_edge (cond_bb);
true_edge->flags = EDGE_TRUE_VALUE;
- true_edge->probability = PROB_UNLIKELY;
+ true_edge->probability = profile_probability::unlikely ();
edge e
= make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
- e->probability = REG_BR_PROB_BASE - true_edge->probability;
+ e->probability = true_edge->probability.invert ();
gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
tree original_ref = tree_coverage_counter_ref (tag, base);
Index: tree-ssa-dce.c
===================================================================
--- tree-ssa-dce.c (revision 249769)
+++ tree-ssa-dce.c (working copy)
@@ -1054,7 +1054,7 @@ remove_dead_stmt (gimple_stmt_iterator *
e = e2;
}
gcc_assert (e);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
/* The edge is no longer associated with a conditional, so it does
Index: tree-ssa-ifcombine.c
===================================================================
--- tree-ssa-ifcombine.c (revision 249769)
+++ tree-ssa-ifcombine.c (working copy)
@@ -363,18 +363,14 @@ update_profile_after_ifcombine (basic_bl
inner_taken->count += outer2->count;
outer2->count = profile_count::zero ();
- inner_taken->probability = outer2->probability
- + RDIV (outer_to_inner->probability
- * inner_taken->probability,
- REG_BR_PROB_BASE);
- if (inner_taken->probability > REG_BR_PROB_BASE)
- inner_taken->probability = REG_BR_PROB_BASE;
- inner_not_taken->probability = REG_BR_PROB_BASE
+ inner_taken->probability = outer2->probability + outer_to_inner->probability
+ * inner_taken->probability;
+ inner_not_taken->probability = profile_probability::always ()
- inner_taken->probability;
- outer_to_inner->probability = REG_BR_PROB_BASE;
+ outer_to_inner->probability = profile_probability::always ();
inner_cond_bb->frequency = outer_cond_bb->frequency;
- outer2->probability = 0;
+ outer2->probability = profile_probability::never ();
}
/* If-convert on a and pattern with a common else block. The inner
Index: tree-ssa-loop-im.c
===================================================================
--- tree-ssa-loop-im.c (revision 249769)
+++ tree-ssa-loop-im.c (working copy)
@@ -1801,7 +1801,7 @@ execute_sm_if_changed (edge ex, tree mem
int freq_sum = 0;
profile_count count_sum = profile_count::zero ();
int nbbs = 0, ncount = 0;
- int flag_probability = -1;
+ profile_probability flag_probability = profile_probability::uninitialized ();
/* Flag is set in FLAG_BBS. Determine probability that flag will be true
at loop exit.
@@ -1824,27 +1824,29 @@ execute_sm_if_changed (edge ex, tree mem
if ((*it)->count.initialized_p ())
count_sum += (*it)->count, ncount ++;
if (dominated_by_p (CDI_DOMINATORS, ex->src, *it))
- flag_probability = REG_BR_PROB_BASE;
+ flag_probability = profile_probability::always ();
nbbs++;
}
- if (flag_probability != -1)
+ profile_probability cap = profile_probability::always ().apply_scale (2, 3);
+
+ if (flag_probability.initialized_p ())
;
else if (ncount == nbbs && count_sum > 0 && preheader->count >= count_sum)
{
flag_probability = count_sum.probability_in (preheader->count);
- if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ if (flag_probability > cap)
+ flag_probability = cap;
}
else if (freq_sum > 0 && EDGE_FREQUENCY (preheader) >= freq_sum)
{
- flag_probability = GCOV_COMPUTE_SCALE (freq_sum,
- EDGE_FREQUENCY (preheader));
- if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ flag_probability = profile_probability::from_reg_br_prob_base
+ (GCOV_COMPUTE_SCALE (freq_sum, EDGE_FREQUENCY (preheader)));
+ if (flag_probability > cap)
+ flag_probability = cap;
}
else
- flag_probability = REG_BR_PROB_BASE * 2 / 3;
+ flag_probability = cap;
/* ?? Insert store after previous store if applicable. See note
below. */
@@ -1876,7 +1878,7 @@ execute_sm_if_changed (edge ex, tree mem
old_dest = ex->dest;
new_bb = split_edge (ex);
then_bb = create_empty_bb (new_bb);
- then_bb->frequency = apply_probability (new_bb->frequency, flag_probability);
+ then_bb->frequency = flag_probability.apply (new_bb->frequency);
then_bb->count = new_bb->count.apply_probability (flag_probability);
if (irr)
then_bb->flags = BB_IRREDUCIBLE_LOOP;
@@ -1901,13 +1903,11 @@ execute_sm_if_changed (edge ex, tree mem
e1->flags |= EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0);
e1->flags &= ~EDGE_FALLTHRU;
- e1->probability = REG_BR_PROB_BASE - flag_probability;
+ e1->probability = flag_probability.invert ();
e1->count = new_bb->count - then_bb->count;
- then_old_edge = make_edge (then_bb, old_dest,
+ then_old_edge = make_single_succ_edge (then_bb, old_dest,
EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0));
- then_old_edge->probability = REG_BR_PROB_BASE;
- then_old_edge->count = then_bb->count;
set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb);
Index: tree-ssa-loop-ivcanon.c
===================================================================
--- tree-ssa-loop-ivcanon.c (revision 249769)
+++ tree-ssa-loop-ivcanon.c (working copy)
@@ -529,7 +529,7 @@ remove_exits_and_undefined_stmts (struct
}
if (!loop_exit_edge_p (loop, exit_edge))
exit_edge = EDGE_SUCC (bb, 1);
- exit_edge->probability = REG_BR_PROB_BASE;
+ exit_edge->probability = profile_probability::always ();
exit_edge->count = exit_edge->src->count;
gcc_checking_assert (loop_exit_edge_p (loop, exit_edge));
gcond *cond_stmt = as_a <gcond *> (elt->stmt);
@@ -642,7 +642,7 @@ unloop_loops (bitmap loop_closed_ssa_inv
it in. */
stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags);
- latch_edge->probability = 0;
+ latch_edge->probability = profile_probability::never ();
latch_edge->count = profile_count::zero ();
latch_edge->flags |= flags;
latch_edge->goto_locus = locus;
@@ -1106,7 +1106,7 @@ try_peel_loop (struct loop *loop,
}
int scale = 1;
if (loop->header->count > 0)
- scale = entry_count.probability_in (loop->header->count);
+ scale = entry_count.probability_in (loop->header->count).to_reg_br_prob_base ();
else if (loop->header->frequency)
scale = RDIV (entry_freq * REG_BR_PROB_BASE, loop->header->frequency);
scale_loop_profile (loop, scale, 0);
Index: tree-ssa-loop-manip.c
===================================================================
--- tree-ssa-loop-manip.c (revision 249769)
+++ tree-ssa-loop-manip.c (working copy)
@@ -1244,7 +1244,10 @@ tree_transform_and_unroll_loop (struct l
scale_rest = REG_BR_PROB_BASE;
new_loop = loop_version (loop, enter_main_cond, NULL,
- prob_entry, REG_BR_PROB_BASE - prob_entry,
+ profile_probability::from_reg_br_prob_base
+ (prob_entry),
+ profile_probability::from_reg_br_prob_base
+ (REG_BR_PROB_BASE - prob_entry),
scale_unrolled, scale_rest, true);
gcc_assert (new_loop != NULL);
update_ssa (TODO_update_ssa);
@@ -1259,9 +1262,11 @@ tree_transform_and_unroll_loop (struct l
/* Since the exit edge will be removed, the frequency of all the blocks
in the loop that are dominated by it must be scaled by
1 / (1 - exit->probability). */
- scale_dominated_blocks_in_loop (loop, exit->src,
- REG_BR_PROB_BASE,
- REG_BR_PROB_BASE - exit->probability);
+ if (exit->probability.initialized_p ())
+ scale_dominated_blocks_in_loop (loop, exit->src,
+ REG_BR_PROB_BASE,
+ REG_BR_PROB_BASE
+ - exit->probability.to_reg_br_prob_base ());
bsi = gsi_last_bb (exit_bb);
exit_if = gimple_build_cond (EQ_EXPR, integer_zero_node,
@@ -1278,11 +1283,13 @@ tree_transform_and_unroll_loop (struct l
new_exit->count = exit->count;
new_exit->probability = exit->probability;
new_nonexit = single_pred_edge (loop->latch);
- new_nonexit->probability = REG_BR_PROB_BASE - exit->probability;
+ new_nonexit->probability = exit->probability.invert ();
new_nonexit->flags = EDGE_TRUE_VALUE;
new_nonexit->count -= exit->count;
- scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
- REG_BR_PROB_BASE);
+ if (new_nonexit->probability.initialized_p ())
+ scale_bbs_frequencies_int (&loop->latch, 1,
+ new_nonexit->probability.to_reg_br_prob_base (),
+ REG_BR_PROB_BASE);
old_entry = loop_preheader_edge (loop);
new_entry = loop_preheader_edge (new_loop);
@@ -1368,24 +1375,29 @@ tree_transform_and_unroll_loop (struct l
if (freq_e == profile_count::zero ())
freq_e = profile_count::from_gcov_type (1);
/* This should not overflow. */
- scale = freq_e.probability_in (freq_h);
+ scale = freq_e.probability_in (freq_h).to_reg_br_prob_base ();
scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
}
exit_bb = single_pred (loop->latch);
new_exit = find_edge (exit_bb, rest);
new_exit->count = loop_preheader_edge (loop)->count;
- new_exit->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
+ new_exit->probability = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
rest->count += new_exit->count;
rest->frequency += EDGE_FREQUENCY (new_exit);
new_nonexit = single_pred_edge (loop->latch);
- prob = new_nonexit->probability;
- new_nonexit->probability = REG_BR_PROB_BASE - new_exit->probability;
+ if (new_nonexit->probability.initialized_p ())
+ prob = new_nonexit->probability.to_reg_br_prob_base ();
+ else
+ prob = 0;
+ new_nonexit->probability = new_exit->probability.invert ();
new_nonexit->count = exit_bb->count - new_exit->count;
if (prob > 0)
- scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
+ scale_bbs_frequencies_int (&loop->latch, 1,
+ new_nonexit->probability.to_reg_br_prob_base (),
prob);
/* Finally create the new counter for number of iterations and add the new
Index: tree-ssa-loop-split.c
===================================================================
--- tree-ssa-loop-split.c (revision 249769)
+++ tree-ssa-loop-split.c (working copy)
@@ -354,10 +354,10 @@ connect_loops (struct loop *loop1, struc
}
new_e->count = skip_bb->count;
- new_e->probability = PROB_LIKELY;
+ new_e->probability = profile_probability::likely ();
new_e->count = skip_e->count.apply_probability (PROB_LIKELY);
skip_e->count -= new_e->count;
- skip_e->probability = inverse_probability (PROB_LIKELY);
+ skip_e->probability = profile_probability::unlikely ();
return new_e;
}
@@ -559,8 +559,11 @@ split_loop (struct loop *loop1, struct t
them, and fix up SSA form for that. */
initialize_original_copy_tables ();
basic_block cond_bb;
+
+ /* FIXME: probabilities seems wrong here. */
struct loop *loop2 = loop_version (loop1, cond, &cond_bb,
- REG_BR_PROB_BASE, REG_BR_PROB_BASE,
+ profile_probability::always (),
+ profile_probability::always (),
REG_BR_PROB_BASE, REG_BR_PROB_BASE,
true);
gcc_assert (loop2);
Index: tree-ssa-loop-unswitch.c
===================================================================
--- tree-ssa-loop-unswitch.c (revision 249769)
+++ tree-ssa-loop-unswitch.c (working copy)
@@ -480,7 +480,7 @@ static struct loop *
tree_unswitch_loop (struct loop *loop,
basic_block unswitch_on, tree cond)
{
- unsigned prob_true;
+ profile_probability prob_true;
edge edge_true, edge_false;
/* Some sanity checking. */
@@ -490,9 +490,13 @@ tree_unswitch_loop (struct loop *loop,
extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
prob_true = edge_true->probability;
+ int p = prob_true.initialized_p () ? prob_true.to_reg_br_prob_base ()
+ : REG_BR_PROB_BASE / 2;
return loop_version (loop, unshare_expr (cond),
- NULL, prob_true, REG_BR_PROB_BASE - prob_true, prob_true,
- REG_BR_PROB_BASE - prob_true, false);
+ NULL, prob_true,
+ prob_true.invert (),
+ p, REG_BR_PROB_BASE - p,
+ false);
}
/* Unswitch outer loops by hoisting invariant guard on
@@ -818,10 +822,13 @@ hoist_guard (struct loop *loop, edge gua
/* Create new loop pre-header. */
e = split_block (pre_header, last_stmt (pre_header));
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Moving guard %i->%i (prob %i) to bb %i, "
- "new preheader is %i\n",
- guard->src->index, guard->dest->index, guard->probability,
- e->src->index, e->dest->index);
+ {
+ fprintf (dump_file, " Moving guard %i->%i (prob ",
+ guard->src->index, guard->dest->index);
+ guard->probability.dump (dump_file);
+ fprintf (dump_file, ") to bb %i, new preheader is %i\n",
+ e->src->index, e->dest->index);
+ }
gcc_assert (loop_preheader_edge (loop)->src == e->dest);
@@ -854,23 +861,26 @@ hoist_guard (struct loop *loop, edge gua
}
new_edge->count = skip_count;
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Estimated probability of skipping loop is %i\n",
- new_edge->probability);
+ {
+ fprintf (dump_file, " Estimated probability of skipping loop is ");
+ new_edge->probability.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
/* Update profile after the transform:
First decrease count of path from newly hoisted loop guard
to loop header... */
e->count -= skip_count;
- e->probability = REG_BR_PROB_BASE - new_edge->probability;
+ e->probability = new_edge->probability.invert ();
e->dest->count = e->count;
e->dest->frequency = EDGE_FREQUENCY (e);
/* ... now update profile to represent that original guard will be optimized
away ... */
- guard->probability = 0;
+ guard->probability = profile_probability::never ();
guard->count = profile_count::zero ();
- not_guard->probability = REG_BR_PROB_BASE;
+ not_guard->probability = profile_probability::always ();
/* This count is wrong (frequency of not_guard does not change),
but will be scaled later. */
not_guard->count = guard->src->count;
@@ -888,7 +898,10 @@ hoist_guard (struct loop *loop, edge gua
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " %i", bb->index);
- scale_bbs_frequencies_int (&bb, 1, e->probability, REG_BR_PROB_BASE);
+ if (e->probability.initialized_p ())
+ scale_bbs_frequencies_int (&bb, 1,
+ e->probability.to_reg_br_prob_base (),
+ REG_BR_PROB_BASE);
}
}
Index: tree-ssa-phionlycprop.c
===================================================================
--- tree-ssa-phionlycprop.c (revision 249769)
+++ tree-ssa-phionlycprop.c (working copy)
@@ -313,8 +313,6 @@ propagate_rhs_into_lhs (gimple *stmt, tr
te->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
te->flags &= ~EDGE_ABNORMAL;
te->flags |= EDGE_FALLTHRU;
- if (te->probability > REG_BR_PROB_BASE)
- te->probability = REG_BR_PROB_BASE;
}
}
}
Index: tree-ssa-phiopt.c
===================================================================
--- tree-ssa-phiopt.c (revision 249769)
+++ tree-ssa-phiopt.c (working copy)
@@ -374,7 +374,7 @@ replace_phi_edge_with_variable (basic_bl
{
EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
@@ -384,7 +384,7 @@ replace_phi_edge_with_variable (basic_bl
EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
EDGE_SUCC (cond_block, 1)->flags
&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
+ EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
@@ -1017,7 +1017,7 @@ value_replacement (basic_block cond_bb,
if (optimize_bb_for_speed_p (cond_bb)
/* The special case is useless if it has a low probability. */
&& profile_status_for_fn (cfun) != PROFILE_ABSENT
- && EDGE_PRED (middle_bb, 0)->probability < PROB_EVEN
+ && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
/* If assign is cheap, there is no point avoiding it. */
&& estimate_num_insns (assign, &eni_time_weights)
>= 3 * estimate_num_insns (cond, &eni_time_weights))
Index: tree-ssa-reassoc.c
===================================================================
--- tree-ssa-reassoc.c (revision 249769)
+++ tree-ssa-reassoc.c (working copy)
@@ -5843,7 +5843,7 @@ branch_fixup (void)
gsi_insert_after (&gsi, g, GSI_NEW_STMT);
edge etrue = make_edge (cond_bb, merge_bb, EDGE_TRUE_VALUE);
- etrue->probability = REG_BR_PROB_BASE / 2;
+ etrue->probability = profile_probability::even ();
etrue->count = cond_bb->count.apply_scale (1, 2);
edge efalse = find_edge (cond_bb, then_bb);
efalse->flags = EDGE_FALSE_VALUE;
Index: tree-ssa-tail-merge.c
===================================================================
--- tree-ssa-tail-merge.c (revision 249769)
+++ tree-ssa-tail-merge.c (working copy)
@@ -1592,9 +1592,10 @@ replace_block_by (basic_block bb1, basic
else if (bb2->frequency && !bb1->frequency)
;
else if (out_freq_sum)
- e2->probability = GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
- + EDGE_FREQUENCY (e2),
- out_freq_sum);
+ e2->probability = profile_probability::from_reg_br_prob_base
+ (GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
+ + EDGE_FREQUENCY (e2),
+ out_freq_sum));
out_sum += e2->count;
}
bb2->frequency += bb1->frequency;
Index: tree-ssa-threadupdate.c
===================================================================
--- tree-ssa-threadupdate.c (revision 249769)
+++ tree-ssa-threadupdate.c (working copy)
@@ -302,7 +302,7 @@ remove_ctrl_stmt_and_useless_edges (basi
}
else
{
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = bb->count;
ei_next (&ei);
}
@@ -546,11 +546,9 @@ static void
create_edge_and_update_destination_phis (struct redirection_data *rd,
basic_block bb, int idx)
{
- edge e = make_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
+ edge e = make_single_succ_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
rescan_loop_exit (e, true, false);
- e->probability = REG_BR_PROB_BASE;
- e->count = bb->count;
/* We used to copy the thread path here. That was added in 2007
and dutifully updated through the representation changes in 2013.
@@ -765,7 +763,8 @@ compute_path_counts (struct redirection_
/* Handle incoming profile insanities. */
if (total_count < path_in_count)
path_in_count = total_count;
- int onpath_scale = path_in_count.probability_in (total_count);
+ int onpath_scale
+ = path_in_count.probability_in (total_count).to_reg_br_prob_base ();
/* Walk the entire path to do some more computation in order to estimate
how much of the path_in_count will flow out of the duplicated threading
@@ -919,7 +918,7 @@ recompute_probabilities (basic_block bb)
get a flow verification error.
Not much we can do to make counts/freqs sane without
redoing the profile estimation. */
- esucc->probability = REG_BR_PROB_BASE;
+ esucc->probability = profile_probability::guessed_always ();
}
}
@@ -978,7 +977,8 @@ update_joiner_offpath_counts (edge epath
among the duplicated off-path edges based on their original
ratio to the full off-path count (total_orig_off_path_count).
*/
- int scale = enonpath->count.probability_in (total_orig_off_path_count);
+ int scale = enonpath->count.probability_in (total_orig_off_path_count)
+ .to_reg_br_prob_base ();
/* Give the duplicated offpath edge a portion of the duplicated
total. */
enonpathdup->count = total_dup_off_path_count.apply_probability (scale);
@@ -1048,9 +1048,13 @@ freqs_to_counts_path (struct redirection
/* Scale up the frequency by REG_BR_PROB_BASE, to avoid rounding
errors applying the probability when the frequencies are very
small. */
- ein->count = profile_count::from_gcov_type
- (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
- ein->probability));
+ if (ein->probability.initialized_p ())
+ ein->count = profile_count::from_gcov_type
+ (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
+ ein->probability.to_reg_br_prob_base ()));
+ else
+ /* FIXME: this is hack; we should track uninitialized values. */
+ ein->count = profile_count::zero ();
}
for (unsigned int i = 1; i < path->length (); i++)
@@ -2358,7 +2362,7 @@ duplicate_thread_path (edge entry, edge
if (e)
{
rescan_loop_exit (e, true, false);
- e->probability = REG_BR_PROB_BASE;
+ e->probability = profile_probability::always ();
e->count = region_copy[n_region - 1]->count;
}
Index: tree-switch-conversion.c
===================================================================
--- tree-switch-conversion.c (revision 249769)
+++ tree-switch-conversion.c (working copy)
@@ -103,7 +103,7 @@ hoist_edge_and_branch_if_true (gimple_st
e_false->flags &= ~EDGE_FALLTHRU;
e_false->flags |= EDGE_FALSE_VALUE;
- e_false->probability = REG_BR_PROB_BASE - e_true->probability;
+ e_false->probability = e_true->probability.invert ();
e_false->count = split_bb->count - e_true->count;
new_bb->count = e_false->count;
@@ -556,7 +556,7 @@ struct switch_conv_info
basic_block final_bb;
/* The probability of the default edge in the replaced switch. */
- int default_prob;
+ profile_probability default_prob;
/* The count of the default edge in the replaced switch. */
profile_count default_count;
@@ -1422,7 +1422,7 @@ gen_inbound_check (gswitch *swtch, struc
/* flags and profiles of the edge for in-range values */
if (!info->default_case_nonstandard)
e01 = make_edge (bb0, bb1, EDGE_TRUE_VALUE);
- e01->probability = REG_BR_PROB_BASE - info->default_prob;
+ e01->probability = info->default_prob.invert ();
e01->count = info->other_count;
/* flags and profiles of the edge taking care of out-of-range values */
@@ -1434,7 +1434,7 @@ gen_inbound_check (gswitch *swtch, struc
bbf = info->final_bb;
e1f = make_edge (bb1, bbf, EDGE_FALLTHRU);
- e1f->probability = REG_BR_PROB_BASE;
+ e1f->probability = profile_probability::always ();
e1f->count = info->other_count;
if (info->default_case_nonstandard)
@@ -1442,7 +1442,7 @@ gen_inbound_check (gswitch *swtch, struc
else
{
e2f = make_edge (bb2, bbf, EDGE_FALLTHRU);
- e2f->probability = REG_BR_PROB_BASE;
+ e2f->probability = profile_probability::always ();
e2f->count = info->default_count;
}
Index: tree-vect-loop-manip.c
===================================================================
--- tree-vect-loop-manip.c (revision 249769)
+++ tree-vect-loop-manip.c (working copy)
@@ -540,7 +540,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (
static edge
slpeel_add_loop_guard (basic_block guard_bb, tree cond,
basic_block guard_to, basic_block dom_bb,
- int probability, bool irreducible_p)
+ profile_probability probability, bool irreducible_p)
{
gimple_stmt_iterator gsi;
edge new_e, enter_e;
@@ -571,7 +571,7 @@ slpeel_add_loop_guard (basic_block guard
new_e->flags |= EDGE_IRREDUCIBLE_LOOP;
enter_e->count -= new_e->count;
- enter_e->probability = inverse_probability (probability);
+ enter_e->probability = probability.invert ();
set_immediate_dominator (CDI_DOMINATORS, guard_to, dom_bb);
/* Split enter_e to preserve LOOPS_HAVE_PREHEADERS. */
@@ -1660,7 +1660,7 @@ vect_do_peeling (loop_vec_info loop_vinf
edge e, guard_e;
tree type = TREE_TYPE (niters), guard_cond;
basic_block guard_bb, guard_to;
- int prob_prolog, prob_vector, prob_epilog;
+ profile_probability prob_prolog, prob_vector, prob_epilog;
int bound_prolog = 0, bound_scalar = 0, bound = 0;
int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
int prolog_peeling = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
@@ -1670,10 +1670,11 @@ vect_do_peeling (loop_vec_info loop_vinf
if (!prolog_peeling && !epilog_peeling)
return NULL;
- prob_vector = 9 * REG_BR_PROB_BASE / 10;
+ prob_vector = profile_probability::guessed_always ().apply_scale (9, 10);
if ((vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo)) == 2)
vf = 3;
- prob_prolog = prob_epilog = (vf - 1) * REG_BR_PROB_BASE / vf;
+ prob_prolog = prob_epilog = profile_probability::guessed_always ()
+ .apply_scale (vf - 1, vf);
vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
struct loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -1718,9 +1719,11 @@ vect_do_peeling (loop_vec_info loop_vinf
separately. Note in this case, the probability of epilog loop
needs to be scaled back later. */
basic_block bb_before_loop = loop_preheader_edge (loop)->src;
- scale_bbs_frequencies_int (&bb_before_loop, 1, prob_vector,
+ if (prob_vector.initialized_p ())
+ scale_bbs_frequencies_int (&bb_before_loop, 1,
+ prob_vector.to_reg_br_prob_base (),
REG_BR_PROB_BASE);
- scale_loop_profile (loop, prob_vector, bound);
+ scale_loop_profile (loop, prob_vector.to_reg_br_prob_base (), bound);
}
tree niters_prolog = build_int_cst (type, 0);
@@ -1762,15 +1765,17 @@ vect_do_peeling (loop_vec_info loop_vinf
guard_to = split_edge (loop_preheader_edge (loop));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
guard_to, guard_bb,
- inverse_probability (prob_prolog),
+ prob_prolog.invert (),
irred_flag);
e = EDGE_PRED (guard_to, 0);
e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
slpeel_update_phi_nodes_for_guard1 (prolog, loop, guard_e, e);
- scale_bbs_frequencies_int (&bb_after_prolog, 1, prob_prolog,
+ scale_bbs_frequencies_int (&bb_after_prolog, 1,
+ prob_prolog.to_reg_br_prob_base (),
REG_BR_PROB_BASE);
- scale_loop_profile (prolog, prob_prolog, bound_prolog);
+ scale_loop_profile (prolog, prob_prolog.to_reg_br_prob_base (),
+ bound_prolog);
}
/* Update init address of DRs. */
vect_update_inits_of_drs (loop_vinfo, niters_prolog);
@@ -1834,7 +1839,7 @@ vect_do_peeling (loop_vec_info loop_vinf
guard_to = split_edge (loop_preheader_edge (epilog));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
guard_to, guard_bb,
- inverse_probability (prob_vector),
+ prob_vector.invert (),
irred_flag);
e = EDGE_PRED (guard_to, 0);
e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
@@ -1846,7 +1851,8 @@ vect_do_peeling (loop_vec_info loop_vinf
guard_to->count = guard_bb->count;
single_succ_edge (guard_to)->count = guard_to->count;
/* Scale probability of epilog loop back. */
- int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE / prob_vector;
+ int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE
+ / prob_vector.to_reg_br_prob_base ();
scale_loop_frequencies (epilog, scale_up, REG_BR_PROB_BASE);
}
@@ -1875,7 +1881,7 @@ vect_do_peeling (loop_vec_info loop_vinf
guard_to = split_edge (single_exit (epilog));
guard_e = slpeel_add_loop_guard (guard_bb, guard_cond, guard_to,
skip_vector ? anchor : guard_bb,
- inverse_probability (prob_epilog),
+ prob_epilog.invert (),
irred_flag);
slpeel_update_phi_nodes_for_guard2 (loop, epilog, guard_e,
single_exit (epilog));
@@ -1883,13 +1889,13 @@ vect_do_peeling (loop_vec_info loop_vinf
the guard_bb, which is the case when skip_vector is true. */
if (guard_bb != bb_before_epilog)
{
- prob_epilog = (combine_probabilities (prob_vector, prob_epilog)
- + inverse_probability (prob_vector));
+ prob_epilog = prob_vector * prob_epilog + prob_vector.invert ();
- scale_bbs_frequencies_int (&bb_before_epilog, 1, prob_epilog,
+ scale_bbs_frequencies_int (&bb_before_epilog, 1,
+ prob_epilog.to_reg_br_prob_base (),
REG_BR_PROB_BASE);
}
- scale_loop_profile (epilog, prob_epilog, bound);
+ scale_loop_profile (epilog, prob_epilog.to_reg_br_prob_base (), bound);
}
else
slpeel_update_phi_nodes_for_lcssa (epilog);
@@ -2171,7 +2177,10 @@ vect_loop_versioning (loop_vec_info loop
/* We don't want to scale SCALAR_LOOP's frequencies, we need to
scale LOOP's frequencies instead. */
nloop = loop_version (scalar_loop, cond_expr, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
+ profile_probability::guessed_always ().apply_scale
+ (prob, REG_BR_PROB_BASE),
+ profile_probability::guessed_always ().apply_scale
+ (REG_BR_PROB_BASE - prob, REG_BR_PROB_BASE),
REG_BR_PROB_BASE, REG_BR_PROB_BASE - prob, true);
scale_loop_frequencies (loop, prob, REG_BR_PROB_BASE);
/* CONDITION_BB was created above SCALAR_LOOP's preheader,
@@ -2200,7 +2209,10 @@ vect_loop_versioning (loop_vec_info loop
}
else
nloop = loop_version (loop, cond_expr, &condition_bb,
- prob, REG_BR_PROB_BASE - prob,
+ profile_probability::guessed_always ().apply_scale
+ (prob, REG_BR_PROB_BASE),
+ profile_probability::guessed_always ().apply_scale
+ (REG_BR_PROB_BASE - prob, REG_BR_PROB_BASE),
prob, REG_BR_PROB_BASE - prob, true);
if (version_niter)
Index: tree-vect-loop.c
===================================================================
--- tree-vect-loop.c (revision 249769)
+++ tree-vect-loop.c (working copy)
@@ -7121,21 +7121,25 @@ scale_profile_for_vect_loop (struct loop
if (!(freq_e > profile_count::from_gcov_type (1)))
freq_e = profile_count::from_gcov_type (1);
/* This should not overflow. */
- scale = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h);
+ scale = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h)
+ .to_reg_br_prob_base ();
scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
}
basic_block exit_bb = single_pred (loop->latch);
edge exit_e = single_exit (loop);
exit_e->count = loop_preheader_edge (loop)->count;
- exit_e->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
+ exit_e->probability = profile_probability::always ()
+ .apply_scale (1, new_est_niter + 1);
edge exit_l = single_pred_edge (loop->latch);
- int prob = exit_l->probability;
- exit_l->probability = REG_BR_PROB_BASE - exit_e->probability;
+ int prob = exit_l->probability.initialized_p ()
+ ? exit_l->probability.to_reg_br_prob_base () : 0;
+ exit_l->probability = exit_e->probability.invert ();
exit_l->count = exit_bb->count - exit_e->count;
if (prob > 0)
- scale_bbs_frequencies_int (&loop->latch, 1, exit_l->probability, prob);
+ scale_bbs_frequencies_int (&loop->latch, 1,
+ exit_l->probability.to_reg_br_prob_base (), prob);
}
/* Function vect_transform_loop.
@@ -7658,7 +7662,7 @@ optimize_mask_stores (struct loop *loop)
e->flags = EDGE_TRUE_VALUE;
efalse = make_edge (bb, store_bb, EDGE_FALSE_VALUE);
/* Put STORE_BB to likely part. */
- efalse->probability = PROB_UNLIKELY;
+ efalse->probability = profile_probability::unlikely ();
store_bb->frequency = PROB_ALWAYS - EDGE_FREQUENCY (efalse);
make_edge (store_bb, join_bb, EDGE_FALLTHRU);
if (dom_info_available_p (CDI_DOMINATORS))
Index: ubsan.c
===================================================================
--- ubsan.c (revision 249769)
+++ ubsan.c (working copy)
@@ -799,7 +799,7 @@ ubsan_expand_null_ifn (gimple_stmt_itera
/* Make an edge coming from the 'cond block' into the 'then block';
this edge is unlikely taken, so set up the probability accordingly. */
e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
/* Connect 'then block' with the 'else block'. This is needed
as the ubsan routines we call in the 'then block' are not noreturn.
@@ -810,7 +810,7 @@ ubsan_expand_null_ifn (gimple_stmt_itera
e = find_edge (cond_bb, fallthru_bb);
e->flags = EDGE_FALSE_VALUE;
e->count = cond_bb->count;
- e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_likely ();
/* Update dominance info for the newly created then_bb; note that
fallthru_bb's dominance info has already been updated by
@@ -873,13 +873,13 @@ ubsan_expand_null_ifn (gimple_stmt_itera
this edge is unlikely taken, so set up the probability
accordingly. */
e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
- e->probability = PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_unlikely ();
/* Set up the fallthrough basic block. */
e = find_edge (cond1_bb, cond2_bb);
e->flags = EDGE_FALSE_VALUE;
e->count = cond1_bb->count;
- e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
+ e->probability = profile_probability::very_likely ();
/* Update dominance info. */
if (dom_info_available_p (CDI_DOMINATORS))
Index: value-prof.c
===================================================================
--- value-prof.c (revision 249769)
+++ value-prof.c (working copy)
@@ -104,11 +104,6 @@ along with GCC; see the file COPYING3.
and gimple_value_profile_transformations table-driven, perhaps...
*/
-static tree gimple_divmod_fixed_value (gassign *, tree, int, gcov_type,
- gcov_type);
-static tree gimple_mod_pow2 (gassign *, int, gcov_type, gcov_type);
-static tree gimple_mod_subtract (gassign *, int, int, int, gcov_type,
- gcov_type, gcov_type);
static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
@@ -693,7 +688,7 @@ gimple_value_profile_transformations (vo
alter the original STMT. */
static tree
-gimple_divmod_fixed_value (gassign *stmt, tree value, int prob,
+gimple_divmod_fixed_value (gassign *stmt, tree value, profile_probability prob,
gcov_type count, gcov_type all)
{
gassign *stmt1, *stmt2;
@@ -753,16 +748,16 @@ gimple_divmod_fixed_value (gassign *stmt
e12->count = profile_count::from_gcov_type (count);
e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
- e13->probability = REG_BR_PROB_BASE - prob;
+ e13->probability = prob.invert ();
e13->count = profile_count::from_gcov_type (all - count);
remove_edge (e23);
e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
- e24->probability = REG_BR_PROB_BASE;
+ e24->probability = profile_probability::always ();
e24->count = profile_count::from_gcov_type (count);
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count);
return tmp2;
@@ -777,7 +772,7 @@ gimple_divmod_fixed_value_transform (gim
enum tree_code code;
gcov_type val, count, all;
tree result, value, tree_val;
- gcov_type prob;
+ profile_probability prob;
gassign *stmt;
stmt = dyn_cast <gassign *> (gsi_stmt (*si));
@@ -816,9 +811,9 @@ gimple_divmod_fixed_value_transform (gim
/* Compute probability of taking the optimal path. */
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT))
tree_val = build_int_cst (get_gcov_type (), val);
@@ -855,7 +850,7 @@ gimple_divmod_fixed_value_transform (gim
the temp; it does not replace or alter the original STMT. */
static tree
-gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all)
+gimple_mod_pow2 (gassign *stmt, profile_probability prob, gcov_type count, gcov_type all)
{
gassign *stmt1, *stmt2, *stmt3;
gcond *stmt4;
@@ -918,16 +913,16 @@ gimple_mod_pow2 (gassign *stmt, int prob
e12->count = profile_count::from_gcov_type (count);
e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
- e13->probability = REG_BR_PROB_BASE - prob;
+ e13->probability = prob.invert ();
e13->count = profile_count::from_gcov_type (all - count);
remove_edge (e23);
e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
- e24->probability = REG_BR_PROB_BASE;
+ e24->probability = profile_probability::always ();
e24->count = profile_count::from_gcov_type (count);
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count);
return result;
@@ -942,7 +937,7 @@ gimple_mod_pow2_value_transform (gimple_
enum tree_code code;
gcov_type count, wrong_values, all;
tree lhs_type, result, value;
- gcov_type prob;
+ profile_probability prob;
gassign *stmt;
stmt = dyn_cast <gassign *> (gsi_stmt (*si));
@@ -987,9 +982,9 @@ gimple_mod_pow2_value_transform (gimple_
return false;
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
result = gimple_mod_pow2 (stmt, prob, count, all);
@@ -1009,7 +1004,8 @@ gimple_mod_pow2_value_transform (gimple_
/* FIXME: Generalize the interface to handle NCOUNTS > 1. */
static tree
-gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts,
+gimple_mod_subtract (gassign *stmt, profile_probability prob1,
+ profile_probability prob2, int ncounts,
gcov_type count1, gcov_type count2, gcov_type all)
{
gassign *stmt1;
@@ -1079,7 +1075,7 @@ gimple_mod_subtract (gassign *stmt, int
e12->flags &= ~EDGE_FALLTHRU;
e12->flags |= EDGE_FALSE_VALUE;
- e12->probability = REG_BR_PROB_BASE - prob1;
+ e12->probability = prob1.invert ();
e12->count = profile_count::from_gcov_type (all - count1);
e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
@@ -1091,14 +1087,14 @@ gimple_mod_subtract (gassign *stmt, int
e23->flags &= ~EDGE_FALLTHRU;
e23->flags |= EDGE_FALSE_VALUE;
e23->count = profile_count::from_gcov_type (all - count1 - count2);
- e23->probability = REG_BR_PROB_BASE - prob2;
+ e23->probability = prob2.invert ();
e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
e24->probability = prob2;
e24->count = profile_count::from_gcov_type (count2);
}
- e34->probability = REG_BR_PROB_BASE;
+ e34->probability = profile_probability::always ();
e34->count = profile_count::from_gcov_type (all - count1 - count2);
return result;
@@ -1113,7 +1109,7 @@ gimple_mod_subtract_transform (gimple_st
enum tree_code code;
gcov_type count, wrong_values, all;
tree lhs_type, result;
- gcov_type prob1, prob2;
+ profile_probability prob1, prob2;
unsigned int i, steps;
gcov_type count1, count2;
gassign *stmt;
@@ -1181,12 +1177,12 @@ gimple_mod_subtract_transform (gimple_st
/* Compute probability of taking the optimal path(s). */
if (all > 0)
{
- prob1 = GCOV_COMPUTE_SCALE (count1, all);
- prob2 = GCOV_COMPUTE_SCALE (count2, all);
+ prob1 = profile_probability::probability_in_gcov_type (count1, all);
+ prob2 = profile_probability::probability_in_gcov_type (count2, all);
}
else
{
- prob1 = prob2 = 0;
+ prob1 = prob2 = profile_probability::never ();
}
/* In practice, "steps" is always 2. This interface reflects this,
@@ -1316,7 +1312,7 @@ check_ic_target (gcall *call_stmt, struc
gcall *
gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
- int prob, profile_count count, profile_count all)
+ profile_probability prob, profile_count count, profile_count all)
{
gcall *dcall_stmt;
gassign *load_stmt;
@@ -1386,7 +1382,7 @@ gimple_ic (gcall *icall_stmt, struct cgr
/* The indirect call might be noreturn. */
if (e_ij != NULL)
{
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
e_ij->count = all - count;
e_ij = single_pred_edge (split_edge (e_ij));
}
@@ -1402,7 +1398,7 @@ gimple_ic (gcall *icall_stmt, struct cgr
e_cd->count = count;
e_ci = make_edge (cond_bb, icall_bb, EDGE_FALSE_VALUE);
- e_ci->probability = REG_BR_PROB_BASE - prob;
+ e_ci->probability = prob.invert ();
e_ci->count = all - count;
remove_edge (e_di);
@@ -1414,12 +1410,12 @@ gimple_ic (gcall *icall_stmt, struct cgr
else
{
e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
- e_dj->probability = REG_BR_PROB_BASE;
+ e_dj->probability = profile_probability::always ();
e_dj->count = count;
e_ij->count = all - count;
}
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
}
/* Insert PHI node for the call result if necessary. */
@@ -1497,6 +1493,8 @@ gimple_ic (gcall *icall_stmt, struct cgr
if (e_eh->flags & (EDGE_EH | EDGE_ABNORMAL))
{
e = make_edge (dcall_bb, e_eh->dest, e_eh->flags);
+ e->probability = e_eh->probability;
+ e->count = e_eh->count;
for (gphi_iterator psi = gsi_start_phis (e_eh->dest);
!gsi_end_p (psi); gsi_next (&psi))
{
@@ -1645,7 +1643,7 @@ interesting_stringop_to_profile_p (gcall
assuming we'll propagate a true constant into ICALL_SIZE later. */
static void
-gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob,
+gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probability prob,
gcov_type count, gcov_type all)
{
gassign *tmp_stmt;
@@ -1709,16 +1707,16 @@ gimple_stringop_fixed_value (gcall *vcal
e_ci->count = profile_count::from_gcov_type (count);
e_cv = make_edge (cond_bb, vcall_bb, EDGE_FALSE_VALUE);
- e_cv->probability = REG_BR_PROB_BASE - prob;
+ e_cv->probability = prob.invert ();
e_cv->count = profile_count::from_gcov_type (all - count);
remove_edge (e_iv);
e_ij = make_edge (icall_bb, join_bb, EDGE_FALLTHRU);
- e_ij->probability = REG_BR_PROB_BASE;
+ e_ij->probability = profile_probability::always ();
e_ij->count = profile_count::from_gcov_type (count);
- e_vj->probability = REG_BR_PROB_BASE;
+ e_vj->probability = profile_probability::always ();
e_vj->count = profile_count::from_gcov_type (all - count);
/* Insert PHI node for the call result if necessary. */
@@ -1753,7 +1751,7 @@ gimple_stringops_transform (gimple_stmt_
gcov_type count, all, val;
tree dest, src;
unsigned int dest_align, src_align;
- gcov_type prob;
+ profile_probability prob;
tree tree_val;
int size_arg;
@@ -1788,9 +1786,9 @@ gimple_stringops_transform (gimple_stmt_
if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count))
return false;
if (all > 0)
- prob = GCOV_COMPUTE_SCALE (count, all);
+ prob = profile_probability::probability_in_gcov_type (count, all);
else
- prob = 0;
+ prob = profile_probability::never ();
dest = gimple_call_arg (stmt, 0);
dest_align = get_pointer_alignment (dest);
Index: value-prof.h
===================================================================
--- value-prof.h (revision 249769)
+++ value-prof.h (working copy)
@@ -90,8 +90,8 @@ void gimple_move_stmt_histograms (struct
void verify_histograms (void);
void free_histograms (function *);
void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
-gcall *gimple_ic (gcall *, struct cgraph_node *, int, profile_count,
- profile_count);
+gcall *gimple_ic (gcall *, struct cgraph_node *, profile_probability,
+ profile_count, profile_count);
bool check_ic_target (gcall *, struct cgraph_node *);
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
@ 2017-06-29 18:28 ` Christophe Lyon
2017-06-29 22:19 ` Jan Hubicka
2017-06-30 6:51 ` [Committed] S/390: Adjust to the recent branch probability changes Andreas Krebbel
` (3 subsequent siblings)
4 siblings, 1 reply; 19+ messages in thread
From: Christophe Lyon @ 2017-06-29 18:28 UTC (permalink / raw)
To: Jan Hubicka; +Cc: gcc-patches, Jakub Jelinek, Martin Liška
Hi,
On 29 June 2017 at 14:27, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this is second step of the profile maintenance revamp. It implements
> profile_probability type which is pretty much symmetric to profile_count
> except that it implements fixed point arithmetics for values 0...1.
> It is used to maintain probabilities of edges out of basic blocks.
> In addition it tracks information about quality of the estimate which can
> later be used for optimization.
>
> Large patch is symmetric just updating existing code to new API. Because
> probabilities are not just integers, some changes are needed. In particular
> 1) I have introduced names for common probabilities, which corresponds to
> PROB_* macros. A lot of code however used explicit calcuation of
> REG_BR_PROB_BASE.
> 2) There is now difference between probability of 0 and uninitialized
> probability. There are a lot of places where we forget to set edge
> probabilities after updating CFG which originally went unnoticed.
> Now we can see ICE when such missing probabilities are intorudced between
> profile estimation and inlning. Rest of code now accepts missing
> probabilities and I will implement checker and fix bugs incremetnally.
>
> Before inlining however I need probabilities to exist because inliner
> redoes probability->frequency computation and for that one can not have
> missing info.
>
> This noticed few erorrs which I knew how to fix, and some I added fixmes
> for:
>
> omp-simd-clone.c:
> - in simd_clone_adjust for edge incr_bb->new_exit_bb
> tree-parloops.c:
> - in create_parallel_loop for guard edge
> - in oacc_entry_exit_single_gang for e3 edge.
> tree-ssa-loop-split.c
> - loop profile updating seems just completely wrong here.
>
> I the first two files I would welcome some suggestions what to do.
>
> To make conversion possible, sometimes I still go to old representation of
> counts via to_reg_br_prob_base/from_reg_br_prob_base. I plan to eliminate most
> of uses of this incrementaly (there are 60 of them).
>
> Bootstrapped/regtested x86_64-linux, will commit it later today after bit
> more testing.
>
After this commit (r249800), GCC builds fail for arm and aarch64:
/gccsrc/gcc/except.c: In function ‘void
sjlj_emit_function_enter(rtx_code_label*)’:
/gcc-fsf/gccsrc/gcc/except.c:1183: error: conversion from ‘int’ to
non-scalar type ‘profile_probability’ requested
make[2]: *** [except.o] Error 1
> Honza
>
> 2017-06-28 Jan Hubicka <hubicka@ucw.cz>
>
> * asan.c (asan_emit_stack_protection): Update.
> (create_cond_insert_point): Update.
> * auto-profile.c (afdo_propagate_circuit): Update.
> * basic-block.h (struct edge_def): Turn probability to
> profile_probability.
> (EDGE_FREQUENCY): Update.
> * bb-reorder.c (find_traces_1_round): Update.
> (better_edge_p): Update.
> (sanitize_hot_paths): Update.
> * cfg.c (unchecked_make_edge): Initialize probability to uninitialized.
> (make_single_succ_edge): Update.
> (check_bb_profile): Update.
> (dump_edge_info): Update.
> (update_bb_profile_for_threading): Update.
> * cfganal.c (connect_infinite_loops_to_exit): Initialize new edge
> probabilitycount to 0.
> * cfgbuild.c (compute_outgoing_frequencies): Update.
> * cfgcleanup.c (try_forward_edges): Update.
> (outgoing_edges_match): Update.
> (try_crossjump_to_edge): Update.
> * cfgexpand.c (expand_gimple_cond): Update make_single_succ_edge.
> (expand_gimple_tailcall): Update.
> (construct_init_block): Use make_single_succ_edge.
> (construct_exit_block): Use make_single_succ_edge.
> * cfghooks.c (verify_flow_info): Update.
> (redirect_edge_succ_nodup): Update.
> (split_edge): Update.
> (account_profile_record): Update.
> * cfgloopanal.c (single_likely_exit): Update.
> * cfgloopmanip.c (scale_loop_profile): Update.
> (set_zero_probability): Remove.
> (duplicate_loop_to_header_edge): Update.
> * cfgloopmanip.h (loop_version): Update prototype.
> * cfgrtl.c (try_redirect_by_replacing_jump): Update.
> (force_nonfallthru_and_redirect): Update.
> (update_br_prob_note): Update.
> (rtl_verify_edges): Update.
> (purge_dead_edges): Update.
> (rtl_lv_add_condition_to_bb): Update.
> * cgraph.c: (cgraph_edge::redirect_call_stmt_to_calle): Update.
> * cgraphunit.c (init_lowered_empty_function): Update.
> (cgraph_node::expand_thunk): Update.
> * cilk-common.c: Include profile-count.h
> * dojump.c (inv): Remove.
> (jumpifnot): Update.
> (jumpifnot_1): Update.
> (do_jump_1): Update.
> (do_jump): Update.
> (do_jump_by_parts_greater_rtx): Update.
> (do_compare_rtx_and_jump): Update.
> * dojump.h (jumpifnot, jumpifnot_1, jumpif_1, jumpif, do_jump,
> do_jump_1. do_compare_rtx_and_jump): Update prototype.
> * dwarf2cfi.c: Include profile-count.h
> * except.c (dw2_build_landing_pads): Use make_single_succ_edge.
> (sjlj_emit_dispatch_table): Likewise.
> * explow.c: Include profile-count.h
> * expmed.c (emit_store_flag_force): Update.
> (do_cmp_and_jump): Update.
> * expr.c (compare_by_pieces_d::generate): Update.
> (compare_by_pieces_d::finish_mode): Update.
> (emit_block_move_via_loop): Update.
> (store_expr_with_bounds): Update.
> (store_constructor): Update.
> (expand_expr_real_2): Update.
> (expand_expr_real_1): Update.
> * expr.h (try_casesi, try_tablejump): Update prototypes.
> * gimple-pretty-print.c (dump_probability): Update.
> (dump_profile): New.
> (dump_gimple_label): Update.
> (dump_gimple_bb_header): Update.
> * graph.c (draw_cfg_node_succ_edges): Update.
> * hsa-gen.c (convert_switch_statements): Update.
> * ifcvt.c (cheap_bb_rtx_cost_p): Update.
> (find_if_case_1): Update.
> (find_if_case_2): Update.
> * internal-fn.c (expand_arith_overflow_result_store): Update.
> (expand_addsub_overflow): Update.
> (expand_neg_overflow): Update.
> (expand_mul_overflow): Update.
> (expand_vector_ubsan_overflow): Update.
> * ipa-cp.c (good_cloning_opportunity_p): Update.
> * ipa-split.c (split_function): Use make_single_succ_edge.
> * ipa-utils.c (ipa_merge_profiles): Update.
> * loop-doloop.c (add_test): Update.
> (doloop_modify): Update.
> * loop-unroll.c (compare_and_jump_seq): Update.
> (unroll_loop_runtime_iterations): Update.
> * lra-constraints.c (lra_inheritance): Update.
> * lto-streamer-in.c (input_cfg): Update.
> * lto-streamer-out.c (output_cfg): Update.
> * mcf.c (adjust_cfg_counts): Update.
> * modulo-sched.c (sms_schedule): Update.
> * omp-expand.c (expand_omp_for_init_counts): Update.
> (extract_omp_for_update_vars): Update.
> (expand_omp_ordered_sink): Update.
> (expand_omp_for_ordered_loops): Update.
> (expand_omp_for_generic): Update.
> (expand_omp_for_static_nochunk): Update.
> (expand_omp_for_static_chunk): Update.
> (expand_cilk_for): Update.
> (expand_omp_simd): Update.
> (expand_omp_taskloop_for_outer): Update.
> (expand_omp_taskloop_for_inner): Update.
> * omp-simd-clone.c (simd_clone_adjust): Update.
> * optabs.c (expand_doubleword_shift): Update.
> (expand_abs): Update.
> (emit_cmp_and_jump_insn_1): Update.
> (expand_compare_and_swap_loop): Update.
> * optabs.h (emit_cmp_and_jump_insns): Update prototype.
> * predict.c (predictable_edge_p): Update.
> (edge_probability_reliable_p): Update.
> (set_even_probabilities): Update.
> (combine_predictions_for_insn): Update.
> (combine_predictions_for_bb): Update.
> (propagate_freq): Update.
> (estimate_bb_frequencies): Update.
> (force_edge_cold): Update.
> * profile-count.c (profile_count::dump): Add missing space into dump.
> (profile_count::debug): Add newline.
> (profile_count::differs_from_p): Explicitly convert to unsigned.
> (profile_count::stream_in): Update.
> (profile_probability::dump): New member function.
> (profile_probability::debug): New member function.
> (profile_probability::differs_from_p): New member function.
> (profile_probability::differs_lot_from_p): New member function.
> (profile_probability::stream_in): New member function.
> (profile_probability::stream_out): New member function.
> * profile-count.h (profile_count_quality): Rename to ...
> (profile_quality): ... this one.
> (profile_probability): New.
> (profile_count): Update.
> * profile.c (compute_branch_probabilities): Update.
> * recog.c (peep2_attempt): Update.
> * sched-ebb.c (schedule_ebbs): Update.
> * sched-rgn.c (find_single_block_region): Update.
> (compute_dom_prob_ps): Update.
> (schedule_region): Update.
> * sel-sched-ir.c (compute_succs_info): Update.
> * stmt.c (struct case_node): Update.
> (do_jump_if_equal): Update.
> (get_outgoing_edge_probs): Update.
> (conditional_probability): Update.
> (emit_case_dispatch_table): Update.
> (expand_case): Update.
> (expand_sjlj_dispatch_table): Update.
> (emit_case_nodes): Update.
> * targhooks.c: Update.
> * tracer.c (better_p): Update.
> (find_best_successor): Update.
> * trans-mem.c (expand_transaction): Update.
> * tree-call-cdce.c: Update.
> * tree-cfg.c (gimple_split_edge): Upate.
> (move_sese_region_to_fn): Upate.
> * tree-cfgcleanup.c (cleanup_control_expr_graph): Upate.
> * tree-eh.c (lower_resx): Upate.
> (cleanup_empty_eh_move_lp): Upate.
> * tree-if-conv.c (version_loop_for_if_conversion): Update.
> * tree-inline.c (copy_edges_for_bb): Update.
> (copy_cfg_body): Update.
> * tree-parloops.c (gen_parallel_loop): Update.
> * tree-profile.c (gimple_gen_ic_func_profiler): Update.
> (gimple_gen_time_profiler): Update.
> * tree-ssa-dce.c (remove_dead_stmt): Update.
> * tree-ssa-ifcombine.c (update_profile_after_ifcombine): Update.
> * tree-ssa-loop-im.c (execute_sm_if_changed): Update.
> * tree-ssa-loop-ivcanon.c (remove_exits_and_undefined_stmts): Update.
> (unloop_loops): Update.
> (try_peel_loop): Update.
> * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update.
> * tree-ssa-loop-split.c (connect_loops): Update.
> (split_loop): Update.
> * tree-ssa-loop-unswitch.c (tree_unswitch_loop): Update.
> (hoist_guard): Update.
> * tree-ssa-phionlycprop.c (propagate_rhs_into_lhs): Update.
> * tree-ssa-phiopt.c (replace_phi_edge_with_variable): Update.
> (value_replacement): Update.
> * tree-ssa-reassoc.c (branch_fixup): Update.
> * tree-ssa-tail-merge.c (replace_block_by): Update.
> * tree-ssa-threadupdate.c (remove_ctrl_stmt_and_useless_edges): Update.
> (create_edge_and_update_destination_phis): Update.
> (compute_path_counts): Update.
> (recompute_probabilities): Update.
> (update_joiner_offpath_counts): Update.
> (freqs_to_counts_path): Update.
> (duplicate_thread_path): Update.
> * tree-switch-conversion.c (hoist_edge_and_branch_if_true): Update.
> (struct switch_conv_info): Update.
> (gen_inbound_check): Update.
> * tree-vect-loop-manip.c (slpeel_add_loop_guard): Update.
> (vect_do_peeling): Update.
> (vect_loop_versioning): Update.
> * tree-vect-loop.c (scale_profile_for_vect_loop): Update.
> (optimize_mask_stores): Update.
> * ubsan.c (ubsan_expand_null_ifn): Update.
> * value-prof.c (gimple_divmod_fixed_value): Update.
> (gimple_divmod_fixed_value_transform): Update.
> (gimple_mod_pow2): Update.
> (gimple_mod_pow2_value_transform): Update.
> (gimple_mod_subtract): Update.
> (gimple_mod_subtract_transform): Update.
> (gimple_ic): Update.
> (gimple_stringop_fixed_value): Update.
> (gimple_stringops_transform): Update.
> * value-prof.h: Update.
>
> Index: asan.c
> ===================================================================
> --- asan.c (revision 249769)
> +++ asan.c (working copy)
> @@ -1145,9 +1145,9 @@ asan_emit_stack_protection (rtx base, rt
> emit_move_insn (orig_base, base);
> ret = expand_normal (asan_detect_stack_use_after_return);
> lab = gen_label_rtx ();
> - int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
> emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
> - VOIDmode, 0, lab, very_likely);
> + VOIDmode, 0, lab,
> + profile_probability::very_likely ());
> snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
> use_after_return_class);
> ret = init_one_libfunc (buf);
> @@ -1158,9 +1158,9 @@ asan_emit_stack_protection (rtx base, rt
> /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
> and NULL otherwise. Check RET value is NULL here and jump over the
> BASE reassignment in this case. Otherwise, reassign BASE to RET. */
> - int very_unlikely = REG_BR_PROB_BASE / 2000 - 1;
> emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
> - VOIDmode, 0, lab, very_unlikely);
> + VOIDmode, 0, lab,
> + profile_probability:: very_unlikely ());
> ret = convert_memory_address (Pmode, ret);
> emit_move_insn (base, ret);
> emit_label (lab);
> @@ -1255,9 +1255,9 @@ asan_emit_stack_protection (rtx base, rt
> {
> rtx_code_label *lab2 = gen_label_rtx ();
> char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
> - int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
> emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
> - VOIDmode, 0, lab2, very_likely);
> + VOIDmode, 0, lab2,
> + profile_probability::very_likely ());
> shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
> set_mem_alias_set (shadow_mem, asan_shadow_set);
> mem = gen_rtx_MEM (ptr_mode, base);
> @@ -1588,7 +1588,8 @@ create_cond_insert_point (gimple_stmt_it
> = then_more_likely_p
> ? PROB_VERY_UNLIKELY
> : PROB_ALWAYS - PROB_VERY_UNLIKELY;
> - e->probability = PROB_ALWAYS - fallthrough_probability;
> + e->probability = profile_probability::from_reg_br_prob_base
> + (PROB_ALWAYS - fallthrough_probability);
> if (create_then_fallthru_edge)
> make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
>
> @@ -1596,7 +1597,8 @@ create_cond_insert_point (gimple_stmt_it
> e = find_edge (cond_bb, fallthru_bb);
> e->flags = EDGE_FALSE_VALUE;
> e->count = cond_bb->count;
> - e->probability = fallthrough_probability;
> + e->probability
> + = profile_probability::from_reg_br_prob_base (fallthrough_probability);
>
> /* Update dominance info for the newly created then_bb; note that
> fallthru_bb's dominance info has already been updated by
> Index: auto-profile.c
> ===================================================================
> --- auto-profile.c (revision 249769)
> +++ auto-profile.c (working copy)
> @@ -1346,9 +1346,10 @@ afdo_propagate_circuit (const bb_set &an
> continue;
> total++;
> only_one = ep;
> - if (e->probability == 0 && !is_edge_annotated (ep, *annotated_edge))
> + if (!e->probability.initialized_p ()
> + && !is_edge_annotated (ep, *annotated_edge))
> {
> - ep->probability = 0;
> + ep->probability = profile_probability::never ();
> ep->count = profile_count::zero ();
> set_edge_annotated (ep, annotated_edge);
> }
> Index: basic-block.h
> ===================================================================
> --- basic-block.h (revision 249769)
> +++ basic-block.h (working copy)
> @@ -45,7 +45,7 @@ struct GTY((user)) edge_def {
> unsigned int dest_idx;
>
> int flags; /* see cfg-flags.def */
> - int probability; /* biased by REG_BR_PROB_BASE */
> + profile_probability probability;
> profile_count count; /* Expected number of executions calculated
> in profile.c */
> };
> @@ -300,8 +300,7 @@ enum cfg_bb_flags
> ? EDGE_SUCC ((bb), 1) : EDGE_SUCC ((bb), 0))
>
> /* Return expected execution frequency of the edge E. */
> -#define EDGE_FREQUENCY(e) RDIV ((e)->src->frequency * (e)->probability, \
> - REG_BR_PROB_BASE)
> +#define EDGE_FREQUENCY(e) e->probability.apply (e->src->frequency)
>
> /* Compute a scale factor (or probability) suitable for scaling of
> gcov_type values via apply_probability() and apply_scale(). */
> Index: bb-reorder.c
> ===================================================================
> --- bb-reorder.c (revision 249769)
> +++ bb-reorder.c (working copy)
> @@ -206,8 +206,8 @@ static void find_traces_1_round (int, in
> int, bb_heap_t **, int);
> static basic_block copy_bb (basic_block, edge, basic_block, int);
> static long bb_to_key (basic_block);
> -static bool better_edge_p (const_basic_block, const_edge, int, int, int, int,
> - const_edge);
> +static bool better_edge_p (const_basic_block, const_edge, profile_probability,
> + int, profile_probability, int, const_edge);
> static bool connect_better_edge_p (const_edge, bool, int, const_edge,
> struct trace *);
> static void connect_traces (int, struct trace *);
> @@ -513,11 +513,12 @@ find_traces_1_round (int branch_th, int
>
> do
> {
> - int prob, freq;
> + profile_probability prob;
> + int freq;
> bool ends_in_call;
>
> /* The probability and frequency of the best edge. */
> - int best_prob = INT_MIN / 2;
> + profile_probability best_prob = profile_probability::uninitialized ();
> int best_freq = INT_MIN / 2;
>
> best_edge = NULL;
> @@ -565,7 +566,9 @@ find_traces_1_round (int branch_th, int
> successor (i.e. it is unsuitable successor). When optimizing
> for size, ignore the probability and frequency. */
> if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX)
> - || ((prob < branch_th || EDGE_FREQUENCY (e) < exec_th
> + || !prob.initialized_p ()
> + || ((prob.to_reg_br_prob_base () < branch_th
> + || EDGE_FREQUENCY (e) < exec_th
> || e->count < count_th) && (!for_size)))
> continue;
>
> @@ -648,7 +651,9 @@ find_traces_1_round (int branch_th, int
>
> if (!(e->flags & EDGE_CAN_FALLTHRU)
> || (e->flags & EDGE_COMPLEX)
> - || prob < branch_th || freq < exec_th
> + || !prob.initialized_p ()
> + || prob.to_reg_br_prob_base () < branch_th
> + || freq < exec_th
> || e->count < count_th)
> {
> /* When partitioning hot/cold basic blocks, make sure
> @@ -936,14 +941,15 @@ bb_to_key (basic_block bb)
> BEST_PROB; similarly for frequency. */
>
> static bool
> -better_edge_p (const_basic_block bb, const_edge e, int prob, int freq,
> - int best_prob, int best_freq, const_edge cur_best_edge)
> +better_edge_p (const_basic_block bb, const_edge e, profile_probability prob,
> + int freq, profile_probability best_prob, int best_freq,
> + const_edge cur_best_edge)
> {
> bool is_better_edge;
>
> /* The BEST_* values do not have to be best, but can be a bit smaller than
> maximum values. */
> - int diff_prob = best_prob / 10;
> + profile_probability diff_prob = best_prob.apply_scale (1, 10);
> int diff_freq = best_freq / 10;
>
> /* The smaller one is better to keep the original order. */
> @@ -1494,7 +1500,8 @@ sanitize_hot_paths (bool walk_up, unsign
> vec<edge, va_gc> *edges = walk_up ? bb->preds : bb->succs;
> edge e;
> edge_iterator ei;
> - int highest_probability = 0;
> + profile_probability highest_probability
> + = profile_probability::uninitialized ();
> int highest_freq = 0;
> profile_count highest_count = profile_count::uninitialized ();
> bool found = false;
> @@ -1517,12 +1524,13 @@ sanitize_hot_paths (bool walk_up, unsign
> /* The following loop will look for the hottest edge via
> the edge count, if it is non-zero, then fallback to the edge
> frequency and finally the edge probability. */
> - if (e->count > highest_count)
> + if (!highest_count.initialized_p () || e->count > highest_count)
> highest_count = e->count;
> int edge_freq = EDGE_FREQUENCY (e);
> if (edge_freq > highest_freq)
> highest_freq = edge_freq;
> - if (e->probability > highest_probability)
> + if (!highest_probability.initialized_p ()
> + || e->probability > highest_probability)
> highest_probability = e->probability;
> }
>
> Index: cfg.c
> ===================================================================
> --- cfg.c (revision 249769)
> +++ cfg.c (working copy)
> @@ -264,6 +264,7 @@ unchecked_make_edge (basic_block src, ba
> n_edges_for_fn (cfun)++;
>
> e->count = profile_count::uninitialized ();
> + e->probability = profile_probability::uninitialized ();
> e->src = src;
> e->dest = dst;
> e->flags = flags;
> @@ -332,7 +333,7 @@ make_single_succ_edge (basic_block src,
> {
> edge e = make_edge (src, dest, flags);
>
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = src->count;
> return e;
> }
> @@ -400,7 +401,6 @@ static void
> check_bb_profile (basic_block bb, FILE * file, int indent)
> {
> edge e;
> - int sum = 0;
> edge_iterator ei;
> struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
> char *s_indent = (char *) alloca ((size_t) indent + 1);
> @@ -413,21 +413,38 @@ check_bb_profile (basic_block bb, FILE *
> if (bb != EXIT_BLOCK_PTR_FOR_FN (fun))
> {
> bool found = false;
> + profile_probability sum = profile_probability::never ();
> + int isum = 0;
> +
> FOR_EACH_EDGE (e, ei, bb->succs)
> {
> - if (!(e->flags & EDGE_EH))
> + if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
> found = true;
> sum += e->probability;
> + if (e->probability.initialized_p ())
> + isum += e->probability.to_reg_br_prob_base ();
> }
> /* Only report mismatches for non-EH control flow. If there are only EH
> edges it means that the BB ends by noreturn call. Here the control
> flow may just terminate. */
> if (found)
> {
> - if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
> - fprintf (file,
> - ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
> - s_indent, sum * 100.0 / REG_BR_PROB_BASE);
> + if (sum.differs_from_p (profile_probability::always ()))
> + {
> + fprintf (file,
> + ";; %sInvalid sum of outgoing probabilities ",
> + s_indent);
> + sum.dump (file);
> + fprintf (file, "\n");
> + }
> + /* Probabilities caps to 100% and thus the previous test will never
> + fire if the sum of probabilities is too large. */
> + else if (isum > REG_BR_PROB_BASE + 100)
> + {
> + fprintf (file,
> + ";; %sInvalid sum of outgoing probabilities %.1f%%\n",
> + s_indent, isum * 100.0 / REG_BR_PROB_BASE);
> + }
> profile_count lsum = profile_count::zero ();
> FOR_EACH_EDGE (e, ei, bb->succs)
> lsum += e->count;
> @@ -442,9 +459,9 @@ check_bb_profile (basic_block bb, FILE *
> }
> }
> }
> - if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
> + if (bb != ENTRY_BLOCK_PTR_FOR_FN (fun))
> {
> - sum = 0;
> + int sum = 0;
> FOR_EACH_EDGE (e, ei, bb->preds)
> sum += EDGE_FREQUENCY (e);
> if (abs (sum - bb->frequency) > 100)
> @@ -498,8 +515,12 @@ dump_edge_info (FILE *file, edge e, dump
> else
> fprintf (file, " %d", side->index);
>
> - if (e->probability && do_details)
> - fprintf (file, " [%.1f%%] ", e->probability * 100.0 / REG_BR_PROB_BASE);
> + if (e->probability.initialized_p () && do_details)
> + {
> + fprintf (file, " [");
> + e->probability.dump (file);
> + fprintf (file, "] ");
> + }
>
> if (e->count.initialized_p () && do_details)
> {
> @@ -860,7 +881,7 @@ update_bb_profile_for_threading (basic_b
> profile_count count, edge taken_edge)
> {
> edge c;
> - int prob;
> + profile_probability prob;
> edge_iterator ei;
>
> if (bb->count < count)
> @@ -878,59 +899,51 @@ update_bb_profile_for_threading (basic_b
> /* Compute the probability of TAKEN_EDGE being reached via threaded edge.
> Watch for overflows. */
> if (bb->frequency)
> - prob = GCOV_COMPUTE_SCALE (edge_frequency, bb->frequency);
> + /* FIXME: We should get edge frequency as count. */
> + prob = profile_probability::probability_in_gcov_type
> + (edge_frequency, bb->frequency);
> else
> - prob = 0;
> + prob = profile_probability::never ();
> if (prob > taken_edge->probability)
> {
> if (dump_file)
> - fprintf (dump_file, "Jump threading proved probability of edge "
> - "%i->%i too small (it is %i, should be %i).\n",
> - taken_edge->src->index, taken_edge->dest->index,
> - taken_edge->probability, prob);
> - prob = taken_edge->probability * 6 / 8;
> + {
> + fprintf (dump_file, "Jump threading proved probability of edge "
> + "%i->%i too small (it is ",
> + taken_edge->src->index, taken_edge->dest->index);
> + taken_edge->probability.dump (dump_file);
> + fprintf (dump_file, " should be ");
> + prob.dump (dump_file);
> + fprintf (dump_file, ")\n");
> + }
> + prob = taken_edge->probability.apply_scale (6, 8);
> }
>
> /* Now rescale the probabilities. */
> taken_edge->probability -= prob;
> - prob = REG_BR_PROB_BASE - prob;
> - if (prob <= 0)
> + prob = prob.invert ();
> + if (prob == profile_probability::never ())
> {
> if (dump_file)
> fprintf (dump_file, "Edge frequencies of bb %i has been reset, "
> "frequency of block should end up being 0, it is %i\n",
> bb->index, bb->frequency);
> - EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
> + EDGE_SUCC (bb, 0)->probability = profile_probability::guessed_always ();
> ei = ei_start (bb->succs);
> ei_next (&ei);
> for (; (c = ei_safe_edge (ei)); ei_next (&ei))
> - c->probability = 0;
> + c->probability = profile_probability::guessed_never ();
> }
> - else if (prob != REG_BR_PROB_BASE)
> + else if (!(prob == profile_probability::always ()))
> {
> - int scale = RDIV (65536 * REG_BR_PROB_BASE, prob);
> -
> FOR_EACH_EDGE (c, ei, bb->succs)
> - {
> - /* Protect from overflow due to additional scaling. */
> - if (c->probability > prob)
> - c->probability = REG_BR_PROB_BASE;
> - else
> - {
> - c->probability = RDIV (c->probability * scale, 65536);
> - if (c->probability > REG_BR_PROB_BASE)
> - c->probability = REG_BR_PROB_BASE;
> - }
> - }
> + c->probability /= prob;
> }
>
> gcc_assert (bb == taken_edge->src);
> - if (taken_edge->count < count)
> - {
> - if (dump_file)
> - fprintf (dump_file, "edge %i->%i count became negative after threading",
> - taken_edge->src->index, taken_edge->dest->index);
> - }
> + if (dump_file && taken_edge->count < count)
> + fprintf (dump_file, "edge %i->%i count became negative after threading",
> + taken_edge->src->index, taken_edge->dest->index);
> taken_edge->count -= count;
> }
>
> Index: cfganal.c
> ===================================================================
> --- cfganal.c (revision 249769)
> +++ cfganal.c (working copy)
> @@ -610,7 +610,10 @@ connect_infinite_loops_to_exit (void)
> break;
>
> basic_block deadend_block = dfs_find_deadend (unvisited_block);
> - make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FAKE);
> + edge e = make_edge (deadend_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
> + EDGE_FAKE);
> + e->count = profile_count::zero ();
> + e->probability = profile_probability::never ();
> dfs.add_bb (deadend_block);
> }
> }
> Index: cfgbuild.c
> ===================================================================
> --- cfgbuild.c (revision 249769)
> +++ cfgbuild.c (working copy)
> @@ -545,10 +545,13 @@ compute_outgoing_frequencies (basic_bloc
> {
> probability = XINT (note, 0);
> e = BRANCH_EDGE (b);
> - e->probability = probability;
> + e->probability
> + = profile_probability::from_reg_br_prob_base (probability);
> e->count = b->count.apply_probability (probability);
> f = FALLTHRU_EDGE (b);
> - f->probability = REG_BR_PROB_BASE - probability;
> + f->probability
> + = profile_probability::from_reg_br_prob_base (REG_BR_PROB_BASE
> + - probability);
> f->count = b->count - e->count;
> return;
> }
> @@ -560,7 +563,7 @@ compute_outgoing_frequencies (basic_bloc
> else if (single_succ_p (b))
> {
> e = single_succ_edge (b);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = b->count;
> return;
> }
> @@ -656,7 +659,8 @@ find_many_sub_basic_blocks (sbitmap bloc
> }
> else
> uninitialized_src = true;
> - bb->frequency += EDGE_FREQUENCY (e);
> + if (e->probability.initialized_p ())
> + bb->frequency += EDGE_FREQUENCY (e);
> }
> /* When some edges are missing with read profile, this is
> most likely because RTL expansion introduced loop.
> Index: cfgcleanup.c
> ===================================================================
> --- cfgcleanup.c (revision 249769)
> +++ cfgcleanup.c (working copy)
> @@ -559,7 +559,7 @@ try_forward_edges (int mode, basic_block
> {
> /* Save the values now, as the edge may get removed. */
> profile_count edge_count = e->count;
> - int edge_probability = e->probability;
> + profile_probability edge_probability = e->probability;
> int edge_frequency;
> int n = 0;
>
> @@ -585,7 +585,7 @@ try_forward_edges (int mode, basic_block
> /* We successfully forwarded the edge. Now update profile
> data: for each edge we traversed in the chain, remove
> the original edge's execution count. */
> - edge_frequency = apply_probability (b->frequency, edge_probability);
> + edge_frequency = edge_probability.apply (b->frequency);
>
> do
> {
> @@ -1710,24 +1710,28 @@ outgoing_edges_match (int mode, basic_bl
> && optimize_bb_for_speed_p (bb1)
> && optimize_bb_for_speed_p (bb2))
> {
> - int prob2;
> + profile_probability prob2;
>
> if (b1->dest == b2->dest)
> prob2 = b2->probability;
> else
> /* Do not use f2 probability as f2 may be forwarded. */
> - prob2 = REG_BR_PROB_BASE - b2->probability;
> + prob2 = b2->probability.invert ();
>
> /* Fail if the difference in probabilities is greater than 50%.
> This rules out two well-predicted branches with opposite
> outcomes. */
> - if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2)
> + if (b1->probability.differs_lot_from_p (prob2))
> {
> if (dump_file)
> - fprintf (dump_file,
> - "Outcomes of branch in bb %i and %i differ too much (%i %i)\n",
> - bb1->index, bb2->index, b1->probability, prob2);
> -
> + {
> + fprintf (dump_file,
> + "Outcomes of branch in bb %i and %i differ too"
> + " much (", bb1->index, bb2->index);
> + b1->probability.dump (dump_file);
> + prob2.dump (dump_file);
> + fprintf (dump_file, ")\n");
> + }
> return false;
> }
> }
> @@ -2149,12 +2153,9 @@ try_crossjump_to_edge (int mode, edge e1
> }
>
> if (!redirect_edges_to->frequency && !src1->frequency)
> - s->probability = (s->probability + s2->probability) / 2;
> - else
> - s->probability
> - = ((s->probability * redirect_edges_to->frequency +
> - s2->probability * src1->frequency)
> - / (redirect_edges_to->frequency + src1->frequency));
> + s->probability = s->probability.combine_with_freq
> + (redirect_edges_to->frequency,
> + s2->probability, src1->frequency);
> }
>
> /* Adjust count and frequency for the block. An earlier jump
> Index: cfgexpand.c
> ===================================================================
> --- cfgexpand.c (revision 249769)
> +++ cfgexpand.c (working copy)
> @@ -2389,7 +2389,6 @@ static basic_block
> expand_gimple_cond (basic_block bb, gcond *stmt)
> {
> basic_block new_bb, dest;
> - edge new_edge;
> edge true_edge;
> edge false_edge;
> rtx_insn *last2, *last;
> @@ -2508,9 +2507,7 @@ expand_gimple_cond (basic_block bb, gcon
> if (loop->latch == bb
> && loop->header == dest)
> loop->latch = new_bb;
> - new_edge = make_edge (new_bb, dest, 0);
> - new_edge->probability = REG_BR_PROB_BASE;
> - new_edge->count = new_bb->count;
> + make_single_succ_edge (new_bb, dest, 0);
> if (BARRIER_P (BB_END (new_bb)))
> BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
> update_bb_for_insn (new_bb);
> @@ -3782,7 +3779,7 @@ expand_gimple_tailcall (basic_block bb,
> rtx_insn *last2, *last;
> edge e;
> edge_iterator ei;
> - int probability;
> + profile_probability probability;
>
> last2 = last = expand_gimple_stmt (stmt);
>
> @@ -3807,7 +3804,7 @@ expand_gimple_tailcall (basic_block bb,
> all edges here, or redirecting the existing fallthru edge to
> the exit block. */
>
> - probability = 0;
> + probability = profile_probability::never ();
> profile_count count = profile_count::zero ();
>
> for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
> @@ -5833,12 +5830,11 @@ construct_init_block (void)
> {
> first_block = e->dest;
> redirect_edge_succ (e, init_block);
> - e = make_edge (init_block, first_block, flags);
> + e = make_single_succ_edge (init_block, first_block, flags);
> }
> else
> - e = make_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
> + e = make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
> + EDGE_FALLTHRU);
>
> update_bb_for_insn (init_block);
> return init_block;
> @@ -5918,9 +5914,8 @@ construct_exit_block (void)
> ix++;
> }
>
> - e = make_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun), EDGE_FALLTHRU);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = EXIT_BLOCK_PTR_FOR_FN (cfun)->count;
> + e = make_single_succ_edge (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
> + EDGE_FALLTHRU);
> FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
> if (e2 != e)
> {
> Index: cfghooks.c
> ===================================================================
> --- cfghooks.c (revision 249769)
> +++ cfghooks.c (working copy)
> @@ -160,10 +160,10 @@ verify_flow_info (void)
> e->src->index, e->dest->index);
> err = 1;
> }
> - if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
> + if (!e->probability.verify ())
> {
> - error ("verify_flow_info: Wrong probability of edge %i->%i %i",
> - e->src->index, e->dest->index, e->probability);
> + error ("verify_flow_info: Wrong probability of edge %i->%i",
> + e->src->index, e->dest->index);
> err = 1;
> }
> if (!e->count.verify ())
> @@ -443,8 +443,6 @@ redirect_edge_succ_nodup (edge e, basic_
> {
> s->flags |= e->flags;
> s->probability += e->probability;
> - if (s->probability > REG_BR_PROB_BASE)
> - s->probability = REG_BR_PROB_BASE;
> s->count += e->count;
> /* FIXME: This should be called via a hook and only for IR_GIMPLE. */
> redirect_edge_var_map_dup (s, e);
> @@ -640,7 +638,7 @@ split_edge (edge e)
> ret = cfg_hooks->split_edge (e);
> ret->count = count;
> ret->frequency = freq;
> - single_succ_edge (ret)->probability = REG_BR_PROB_BASE;
> + single_succ_edge (ret)->probability = profile_probability::always ();
> single_succ_edge (ret)->count = count;
>
> if (irr)
> @@ -1451,17 +1449,17 @@ account_profile_record (struct profile_r
> basic_block bb;
> edge_iterator ei;
> edge e;
> - int sum;
>
> FOR_ALL_BB_FN (bb, cfun)
> {
> if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
> && profile_status_for_fn (cfun) != PROFILE_ABSENT)
> {
> - sum = 0;
> + profile_probability sum = profile_probability::never ();
> FOR_EACH_EDGE (e, ei, bb->succs)
> sum += e->probability;
> - if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100)
> + if (EDGE_COUNT (bb->succs)
> + && sum.differs_from_p (profile_probability::always ()))
> record->num_mismatched_freq_out[after_pass]++;
> profile_count lsum = profile_count::zero ();
> FOR_EACH_EDGE (e, ei, bb->succs)
> @@ -1472,7 +1470,7 @@ account_profile_record (struct profile_r
> if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun)
> && profile_status_for_fn (cfun) != PROFILE_ABSENT)
> {
> - sum = 0;
> + int sum = 0;
> FOR_EACH_EDGE (e, ei, bb->preds)
> sum += EDGE_FREQUENCY (e);
> if (abs (sum - bb->frequency) > 100
> Index: cfgloopanal.c
> ===================================================================
> --- cfgloopanal.c (revision 249769)
> +++ cfgloopanal.c (working copy)
> @@ -477,7 +477,7 @@ single_likely_exit (struct loop *loop)
> reasons.
> FIXME: Turn to likely_never_executed */
> if ((profile_status_for_fn (cfun) != PROFILE_ABSENT
> - && ex->probability < 5)
> + && ex->probability < profile_probability::from_reg_br_prob_base (5))
> || ex->count == profile_count::zero ())
> continue;
> if (!found)
> Index: cfgloopmanip.c
> ===================================================================
> --- cfgloopmanip.c (revision 249769)
> +++ cfgloopmanip.c (working copy)
> @@ -542,8 +542,9 @@ scale_loop_profile (struct loop *loop, i
>
> /* Probability of exit must be 1/iterations. */
> freq_delta = EDGE_FREQUENCY (e);
> - e->probability = REG_BR_PROB_BASE / iteration_bound;
> - other_e->probability = inverse_probability (e->probability);
> + e->probability = profile_probability::from_reg_br_prob_base
> + (REG_BR_PROB_BASE / iteration_bound);
> + other_e->probability = e->probability.invert ();
> freq_delta -= EDGE_FREQUENCY (e);
>
> /* Adjust counts accordingly. */
> @@ -1101,43 +1102,6 @@ can_duplicate_loop_p (const struct loop
> return ret;
> }
>
> -/* Sets probability and count of edge E to zero. The probability and count
> - is redistributed evenly to the remaining edges coming from E->src. */
> -
> -static void
> -set_zero_probability (edge e)
> -{
> - basic_block bb = e->src;
> - edge_iterator ei;
> - edge ae, last = NULL;
> - unsigned n = EDGE_COUNT (bb->succs);
> - profile_count cnt = e->count, cnt1;
> - unsigned prob = e->probability, prob1;
> -
> - gcc_assert (n > 1);
> - cnt1 = cnt.apply_scale (1, (n - 1));
> - prob1 = prob / (n - 1);
> -
> - FOR_EACH_EDGE (ae, ei, bb->succs)
> - {
> - if (ae == e)
> - continue;
> -
> - ae->probability += prob1;
> - ae->count += cnt1;
> - last = ae;
> - }
> -
> - /* Move the rest to one of the edges. */
> - last->probability += prob % (n - 1);
> - /* TODO: Remove once we have fractional counts. */
> - if (cnt.initialized_p ())
> - last->count += profile_count::from_gcov_type (cnt.to_gcov_type () % (n - 1));
> -
> - e->probability = 0;
> - e->count = profile_count::zero ();
> -}
> -
> /* Duplicates body of LOOP to given edge E NDUPL times. Takes care of updating
> loop structure and dominators. E's destination must be LOOP header for
> this to work, i.e. it must be entry or latch edge of this loop; these are
> @@ -1224,14 +1188,18 @@ duplicate_loop_to_header_edge (struct lo
> prob_pass_wont_exit =
> RDIV (REG_BR_PROB_BASE * (freq_le + freq_out_orig), freq_in);
>
> - if (orig
> - && REG_BR_PROB_BASE - orig->probability != 0)
> + if (orig && orig->probability.initialized_p ()
> + && !(orig->probability == profile_probability::always ()))
> {
> /* The blocks that are dominated by a removed exit edge ORIG have
> frequencies scaled by this. */
> - scale_after_exit
> - = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
> - REG_BR_PROB_BASE - orig->probability);
> + if (orig->probability.initialized_p ())
> + scale_after_exit
> + = GCOV_COMPUTE_SCALE (REG_BR_PROB_BASE,
> + REG_BR_PROB_BASE
> + - orig->probability.to_reg_br_prob_base ());
> + else
> + scale_after_exit = REG_BR_PROB_BASE;
> bbs_to_scale = BITMAP_ALLOC (NULL);
> for (i = 0; i < n; i++)
> {
> @@ -1387,7 +1355,7 @@ duplicate_loop_to_header_edge (struct lo
> {
> if (to_remove)
> to_remove->safe_push (new_spec_edges[SE_ORIG]);
> - set_zero_probability (new_spec_edges[SE_ORIG]);
> + force_edge_cold (new_spec_edges[SE_ORIG], true);
>
> /* Scale the frequencies of the blocks dominated by the exit. */
> if (bbs_to_scale)
> @@ -1423,7 +1391,7 @@ duplicate_loop_to_header_edge (struct lo
> {
> if (to_remove)
> to_remove->safe_push (orig);
> - set_zero_probability (orig);
> + force_edge_cold (orig, true);
>
> /* Scale the frequencies of the blocks dominated by the exit. */
> if (bbs_to_scale)
> @@ -1657,8 +1625,9 @@ force_single_succ_latches (void)
>
> static basic_block
> lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head,
> - edge e, void *cond_expr, unsigned then_prob,
> - unsigned else_prob)
> + edge e, void *cond_expr,
> + profile_probability then_prob,
> + profile_probability else_prob)
> {
> basic_block new_head = NULL;
> edge e1;
> @@ -1713,7 +1682,7 @@ lv_adjust_loop_entry_edge (basic_block f
> struct loop *
> loop_version (struct loop *loop,
> void *cond_expr, basic_block *condition_bb,
> - unsigned then_prob, unsigned else_prob,
> + profile_probability then_prob, profile_probability else_prob,
> unsigned then_scale, unsigned else_scale,
> bool place_after)
> {
> Index: cfgloopmanip.h
> ===================================================================
> --- cfgloopmanip.h (revision 249769)
> +++ cfgloopmanip.h (working copy)
> @@ -58,7 +58,8 @@ basic_block create_preheader (struct loo
> extern void create_preheaders (int);
> extern void force_single_succ_latches (void);
> struct loop * loop_version (struct loop *, void *,
> - basic_block *, unsigned, unsigned,
> + basic_block *,
> + profile_probability, profile_probability,
> unsigned, unsigned, bool);
>
> #endif /* GCC_CFGLOOPMANIP_H */
> Index: cfgrtl.c
> ===================================================================
> --- cfgrtl.c (revision 249769)
> +++ cfgrtl.c (working copy)
> @@ -1155,7 +1155,7 @@ try_redirect_by_replacing_jump (edge e,
> else
> e->flags = 0;
>
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = src->count;
>
> if (e->dest != target)
> @@ -1504,12 +1504,10 @@ force_nonfallthru_and_redirect (edge e,
> {
> int prob = XINT (note, 0);
>
> - b->probability = prob;
> + b->probability = profile_probability::from_reg_br_prob_base (prob);
> b->count = e->count.apply_probability (prob);
> e->probability -= e->probability;
> e->count -= b->count;
> - if (e->probability < 0)
> - e->probability = 0;
> }
> }
>
> @@ -1618,7 +1616,7 @@ force_nonfallthru_and_redirect (edge e,
> {
> rtx_insn *new_head;
> profile_count count = e->count;
> - int probability = e->probability;
> + profile_probability probability = e->probability;
> /* Create the new structures. */
>
> /* If the old block ended with a tablejump, skip its table
> @@ -1646,7 +1644,7 @@ force_nonfallthru_and_redirect (edge e,
>
> /* Redirect old edge. */
> redirect_edge_pred (e, jump_block);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
>
> /* If e->src was previously region crossing, it no longer is
> and the reg crossing note should be removed. */
> @@ -1656,7 +1654,7 @@ force_nonfallthru_and_redirect (edge e,
> add also edge from asm goto bb to target. */
> if (asm_goto_edge)
> {
> - new_edge->probability /= 2;
> + new_edge->probability = new_edge->probability.apply_scale (1, 2);
> new_edge->count = new_edge->count.apply_scale (1, 2);
> jump_block->count = jump_block->count.apply_scale (1, 2);
> jump_block->frequency /= 2;
> @@ -2251,12 +2249,13 @@ void
> update_br_prob_note (basic_block bb)
> {
> rtx note;
> - if (!JUMP_P (BB_END (bb)))
> + if (!JUMP_P (BB_END (bb)) || !BRANCH_EDGE (bb)->probability.initialized_p ())
> return;
> note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX);
> - if (!note || XINT (note, 0) == BRANCH_EDGE (bb)->probability)
> + if (!note
> + || XINT (note, 0) == BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ())
> return;
> - XINT (note, 0) = BRANCH_EDGE (bb)->probability;
> + XINT (note, 0) = BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ();
> }
>
> /* Get the last insn associated with block BB (that includes barriers and
> @@ -2447,11 +2446,19 @@ rtl_verify_edges (void)
> && EDGE_COUNT (bb->succs) >= 2
> && any_condjump_p (BB_END (bb)))
> {
> - if (XINT (note, 0) != BRANCH_EDGE (bb)->probability
> - && profile_status_for_fn (cfun) != PROFILE_ABSENT)
> + if (!BRANCH_EDGE (bb)->probability.initialized_p ())
> + {
> + error ("verify_flow_info: "
> + "REG_BR_PROB is set but cfg probability is not");
> + err = 1;
> + }
> + else if (XINT (note, 0)
> + != BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ()
> + && profile_status_for_fn (cfun) != PROFILE_ABSENT)
> {
> error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
> - XINT (note, 0), BRANCH_EDGE (bb)->probability);
> + XINT (note, 0),
> + BRANCH_EDGE (bb)->probability.to_reg_br_prob_base ());
> err = 1;
> }
> }
> @@ -3143,7 +3150,7 @@ purge_dead_edges (basic_block bb)
> /* Redistribute probabilities. */
> if (single_succ_p (bb))
> {
> - single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
> + single_succ_edge (bb)->probability = profile_probability::always ();
> single_succ_edge (bb)->count = bb->count;
> }
> else
> @@ -3154,8 +3161,9 @@ purge_dead_edges (basic_block bb)
>
> b = BRANCH_EDGE (bb);
> f = FALLTHRU_EDGE (bb);
> - b->probability = XINT (note, 0);
> - f->probability = REG_BR_PROB_BASE - b->probability;
> + b->probability = profile_probability::from_reg_br_prob_base
> + (XINT (note, 0));
> + f->probability = profile_probability::always () - b->probability;
> b->count = bb->count.apply_probability (b->probability);
> f->count = bb->count.apply_probability (f->probability);
> }
> @@ -3208,7 +3216,7 @@ purge_dead_edges (basic_block bb)
>
> gcc_assert (single_succ_p (bb));
>
> - single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
> + single_succ_edge (bb)->probability = profile_probability::always ();
> single_succ_edge (bb)->count = bb->count;
>
> if (dump_file)
> @@ -4931,7 +4939,8 @@ rtl_lv_add_condition_to_bb (basic_block
> start_sequence ();
> op0 = force_operand (op0, NULL_RTX);
> op1 = force_operand (op1, NULL_RTX);
> - do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label, -1);
> + do_compare_rtx_and_jump (op0, op1, comp, 0, mode, NULL_RTX, NULL, label,
> + profile_probability::uninitialized ());
> jump = get_last_insn ();
> JUMP_LABEL (jump) = label;
> LABEL_NUSES (label)++;
> Index: cgraph.c
> ===================================================================
> --- cgraph.c (revision 249769)
> +++ cgraph.c (working copy)
> @@ -20,8 +20,9 @@ along with GCC; see the file COPYING3.
>
> /* This file contains basic routines manipulating call graph
>
> - The call-graph is a data structure designed for intra-procedural optimization.
> - It represents a multi-graph where nodes are functions and edges are call sites. */
> + The call-graph is a data structure designed for inter-procedural
> + optimization. It represents a multi-graph where nodes are functions
> + (symbols within symbol table) and edges are call sites. */
>
> #include "config.h"
> #include "system.h"
> @@ -1316,13 +1317,16 @@ cgraph_edge::redirect_call_stmt_to_calle
> push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
> new_stmt = gimple_ic (e->call_stmt,
> dyn_cast<cgraph_node *> (ref->referred),
> + /* FIXME: cleanup. */
> + profile_probability::from_reg_br_prob_base (
> e->count > profile_count::zero ()
> || e2->count > profile_count::zero ()
> - ? e->count.probability_in (e->count + e2->count)
> + ? e->count.probability_in
> + (e->count + e2->count).to_reg_br_prob_base ()
> : e->frequency || e2->frequency
> ? RDIV (e->frequency * REG_BR_PROB_BASE,
> e->frequency + e2->frequency)
> - : REG_BR_PROB_BASE / 2,
> + : REG_BR_PROB_BASE / 2),
> e->count, e->count + e2->count);
> e->speculative = false;
> e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
> Index: cgraphunit.c
> ===================================================================
> --- cgraphunit.c (revision 249769)
> +++ cgraphunit.c (working copy)
> @@ -1506,18 +1506,18 @@ init_lowered_empty_function (tree decl,
>
> /* Create BB for body of the function and connect it properly. */
> ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = count;
> - ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
> + ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
> EXIT_BLOCK_PTR_FOR_FN (cfun)->count = count;
> - EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = REG_BR_PROB_BASE;
> + EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency = BB_FREQ_MAX;
> bb = create_basic_block (NULL, ENTRY_BLOCK_PTR_FOR_FN (cfun));
> bb->count = count;
> bb->frequency = BB_FREQ_MAX;
> e = make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, EDGE_FALLTHRU);
> e->count = count;
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> e->count = count;
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> add_bb_to_loop (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father);
>
> return bb;
> @@ -1891,19 +1891,18 @@ cgraph_node::expand_thunk (bool output_a
> NULL_TREE, NULL_TREE);
> gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
> e = make_edge (bb, then_bb, EDGE_TRUE_VALUE);
> - e->probability = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 16;
> + e->probability = profile_probability::guessed_always ()
> + .apply_scale (1, 16);
> e->count = count - count.apply_scale (1, 16);
> e = make_edge (bb, else_bb, EDGE_FALSE_VALUE);
> - e->probability = REG_BR_PROB_BASE / 16;
> + e->probability = profile_probability::guessed_always ()
> + .apply_scale (1, 16);
> e->count = count.apply_scale (1, 16);
> - e = make_edge (return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = count;
> - e = make_edge (then_bb, return_bb, EDGE_FALLTHRU);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = count - count.apply_scale (1, 16);
> + make_single_succ_edge (return_bb,
> + EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> + make_single_succ_edge (then_bb, return_bb, EDGE_FALLTHRU);
> e = make_edge (else_bb, return_bb, EDGE_FALLTHRU);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = count.apply_scale (1, 16);
> bsi = gsi_last_bb (then_bb);
> }
> Index: cilk-common.c
> ===================================================================
> --- cilk-common.c (revision 249769)
> +++ cilk-common.c (working copy)
> @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.
> #include "stor-layout.h"
> #include "langhooks.h"
> #include "explow.h"
> +#include "profile-count.h"
> #include "expr.h"
> #include "tree-iterator.h"
> #include "gimplify.h"
> Index: dojump.c
> ===================================================================
> --- dojump.c (revision 249769)
> +++ dojump.c (working copy)
> @@ -39,19 +39,13 @@ along with GCC; see the file COPYING3.
>
> static bool prefer_and_bit_test (machine_mode, int);
> static void do_jump_by_parts_greater (tree, tree, int,
> - rtx_code_label *, rtx_code_label *, int);
> + rtx_code_label *, rtx_code_label *,
> + profile_probability);
> static void do_jump_by_parts_equality (tree, tree, rtx_code_label *,
> - rtx_code_label *, int);
> + rtx_code_label *, profile_probability);
> static void do_compare_and_jump (tree, tree, enum rtx_code, enum rtx_code,
> - rtx_code_label *, rtx_code_label *, int);
> -
> -/* Invert probability if there is any. -1 stands for unknown. */
> -
> -static inline int
> -inv (int prob)
> -{
> - return prob == -1 ? -1 : REG_BR_PROB_BASE - prob;
> -}
> + rtx_code_label *, rtx_code_label *,
> + profile_probability);
>
> /* At the start of a function, record that we have no previously-pushed
> arguments waiting to be popped. */
> @@ -128,29 +122,29 @@ restore_pending_stack_adjust (saved_pend
> /* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
>
> void
> -jumpifnot (tree exp, rtx_code_label *label, int prob)
> +jumpifnot (tree exp, rtx_code_label *label, profile_probability prob)
> {
> - do_jump (exp, label, NULL, inv (prob));
> + do_jump (exp, label, NULL, prob.invert ());
> }
>
> void
> jumpifnot_1 (enum tree_code code, tree op0, tree op1, rtx_code_label *label,
> - int prob)
> + profile_probability prob)
> {
> - do_jump_1 (code, op0, op1, label, NULL, inv (prob));
> + do_jump_1 (code, op0, op1, label, NULL, prob.invert ());
> }
>
> /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
>
> void
> -jumpif (tree exp, rtx_code_label *label, int prob)
> +jumpif (tree exp, rtx_code_label *label, profile_probability prob)
> {
> do_jump (exp, NULL, label, prob);
> }
>
> void
> jumpif_1 (enum tree_code code, tree op0, tree op1,
> - rtx_code_label *label, int prob)
> + rtx_code_label *label, profile_probability prob)
> {
> do_jump_1 (code, op0, op1, NULL, label, prob);
> }
> @@ -200,12 +194,12 @@ prefer_and_bit_test (machine_mode mode,
>
> /* Subroutine of do_jump, dealing with exploded comparisons of the type
> OP0 CODE OP1 . IF_FALSE_LABEL and IF_TRUE_LABEL like in do_jump.
> - PROB is probability of jump to if_true_label, or -1 if unknown. */
> + PROB is probability of jump to if_true_label. */
>
> void
> do_jump_1 (enum tree_code code, tree op0, tree op1,
> rtx_code_label *if_false_label, rtx_code_label *if_true_label,
> - int prob)
> + profile_probability prob)
> {
> machine_mode mode;
> rtx_code_label *drop_through_label = 0;
> @@ -222,7 +216,8 @@ do_jump_1 (enum tree_code code, tree op0
> != MODE_COMPLEX_INT);
>
> if (integer_zerop (op1))
> - do_jump (op0, if_true_label, if_false_label, inv (prob));
> + do_jump (op0, if_true_label, if_false_label,
> + prob.invert ());
> else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
> && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
> do_jump_by_parts_equality (op0, op1, if_false_label, if_true_label,
> @@ -247,7 +242,7 @@ do_jump_1 (enum tree_code code, tree op0
> else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
> && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
> do_jump_by_parts_equality (op0, op1, if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> else
> do_compare_and_jump (op0, op1, NE, NE, if_false_label, if_true_label,
> prob);
> @@ -270,7 +265,7 @@ do_jump_1 (enum tree_code code, tree op0
> if (GET_MODE_CLASS (mode) == MODE_INT
> && ! can_compare_p (LE, mode, ccp_jump))
> do_jump_by_parts_greater (op0, op1, 0, if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> else
> do_compare_and_jump (op0, op1, LE, LEU, if_false_label, if_true_label,
> prob);
> @@ -292,7 +287,7 @@ do_jump_1 (enum tree_code code, tree op0
> if (GET_MODE_CLASS (mode) == MODE_INT
> && ! can_compare_p (GE, mode, ccp_jump))
> do_jump_by_parts_greater (op0, op1, 1, if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> else
> do_compare_and_jump (op0, op1, GE, GEU, if_false_label, if_true_label,
> prob);
> @@ -346,17 +341,17 @@ do_jump_1 (enum tree_code code, tree op0
> half of the total probability of being false, so its jump has a false
> probability of half the total, relative to the probability we
> reached it (i.e. the first condition was true). */
> - int op0_prob = -1;
> - int op1_prob = -1;
> - if (prob != -1)
> + profile_probability op0_prob = profile_probability::uninitialized ();
> + profile_probability op1_prob = profile_probability::uninitialized ();
> + if (prob.initialized_p ())
> {
> - int false_prob = inv (prob);
> - int op0_false_prob = false_prob / 2;
> - int op1_false_prob = GCOV_COMPUTE_SCALE ((false_prob / 2),
> - inv (op0_false_prob));
> + profile_probability false_prob = prob.invert ();
> + profile_probability op0_false_prob = false_prob.apply_scale (1, 2);
> + profile_probability op1_false_prob = false_prob.apply_scale (1, 2)
> + / op0_false_prob.invert ();
> /* Get the probability that each jump below is true. */
> - op0_prob = inv (op0_false_prob);
> - op1_prob = inv (op1_false_prob);
> + op0_prob = op0_false_prob.invert ();
> + op1_prob = op1_false_prob.invert ();
> }
> if (if_false_label == NULL)
> {
> @@ -379,12 +374,12 @@ do_jump_1 (enum tree_code code, tree op0
> The second condition has the other half of the total probability,
> so its jump has a probability of half the total, relative to
> the probability we reached it (i.e. the first condition was false). */
> - int op0_prob = -1;
> - int op1_prob = -1;
> - if (prob != -1)
> + profile_probability op0_prob = profile_probability::uninitialized ();
> + profile_probability op1_prob = profile_probability::uninitialized ();
> + if (prob.initialized_p ())
> {
> - op0_prob = prob / 2;
> - op1_prob = GCOV_COMPUTE_SCALE ((prob / 2), inv (op0_prob));
> + op0_prob = prob.apply_scale (1, 2);
> + op1_prob = prob.apply_scale (1, 2) / op0_prob.invert ();
> }
> if (if_true_label == NULL)
> {
> @@ -420,11 +415,11 @@ do_jump_1 (enum tree_code code, tree op0
> actually perform a jump. An example where there is no jump
> is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
>
> - PROB is probability of jump to if_true_label, or -1 if unknown. */
> + PROB is probability of jump to if_true_label. */
>
> void
> do_jump (tree exp, rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label, profile_probability prob)
> {
> enum tree_code code = TREE_CODE (exp);
> rtx temp;
> @@ -481,7 +476,7 @@ do_jump (tree exp, rtx_code_label *if_fa
>
> case TRUTH_NOT_EXPR:
> do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> break;
>
> case COND_EXPR:
> @@ -497,7 +492,8 @@ do_jump (tree exp, rtx_code_label *if_fa
> }
>
> do_pending_stack_adjust ();
> - do_jump (TREE_OPERAND (exp, 0), label1, NULL, -1);
> + do_jump (TREE_OPERAND (exp, 0), label1, NULL,
> + profile_probability::uninitialized ());
> do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
> emit_label (label1);
> do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
> @@ -542,7 +538,7 @@ do_jump (tree exp, rtx_code_label *if_fa
> {
> tree exp0 = TREE_OPERAND (exp, 0);
> rtx_code_label *set_label, *clr_label;
> - int setclr_prob = prob;
> + profile_probability setclr_prob = prob;
>
> /* Strip narrowing integral type conversions. */
> while (CONVERT_EXPR_P (exp0)
> @@ -558,7 +554,7 @@ do_jump (tree exp, rtx_code_label *if_fa
> exp0 = TREE_OPERAND (exp0, 0);
> clr_label = if_true_label;
> set_label = if_false_label;
> - setclr_prob = inv (prob);
> + setclr_prob = prob.invert ();
> }
> else
> {
> @@ -673,7 +669,7 @@ static void
> do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
> rtx op1, rtx_code_label *if_false_label,
> rtx_code_label *if_true_label,
> - int prob)
> + profile_probability prob)
> {
> int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
> rtx_code_label *drop_through_label = 0;
> @@ -703,7 +699,7 @@ do_jump_by_parts_greater_rtx (machine_mo
> if_false_label = drop_through_label;
> drop_through_if_true = false;
> drop_through_if_false = true;
> - prob = inv (prob);
> + prob = prob.invert ();
> }
>
> /* Compare a word at a time, high order first. */
> @@ -733,7 +729,8 @@ do_jump_by_parts_greater_rtx (machine_mo
>
> /* Consider lower words only if these are equal. */
> do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
> - NULL_RTX, NULL, if_false_label, inv (prob));
> + NULL_RTX, NULL, if_false_label,
> + prob.invert ());
> }
>
> if (!drop_through_if_false)
> @@ -750,7 +747,8 @@ do_jump_by_parts_greater_rtx (machine_mo
> static void
> do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label,
> + profile_probability prob)
> {
> rtx op0 = expand_normal (swap ? treeop1 : treeop0);
> rtx op1 = expand_normal (swap ? treeop0 : treeop1);
> @@ -769,7 +767,8 @@ do_jump_by_parts_greater (tree treeop0,
> static void
> do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label,
> + profile_probability prob)
> {
> int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
> rtx part;
> @@ -819,7 +818,8 @@ do_jump_by_parts_zero_rtx (machine_mode
> static void
> do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label,
> + profile_probability prob)
> {
> int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
> rtx_code_label *drop_through_label = NULL;
> @@ -859,7 +859,8 @@ do_jump_by_parts_equality_rtx (machine_m
> static void
> do_jump_by_parts_equality (tree treeop0, tree treeop1,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label,
> + profile_probability prob)
> {
> rtx op0 = expand_normal (treeop0);
> rtx op1 = expand_normal (treeop1);
> @@ -956,7 +957,8 @@ void
> do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
> machine_mode mode, rtx size,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label,
> + profile_probability prob)
> {
> rtx tem;
> rtx_code_label *dummy_label = NULL;
> @@ -983,7 +985,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
> {
> std::swap (if_true_label, if_false_label);
> code = rcode;
> - prob = inv (prob);
> + prob = prob.invert ();
> }
> }
>
> @@ -1035,7 +1037,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
> case LEU:
> do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
> if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> break;
>
> case GTU:
> @@ -1046,7 +1048,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
> case GEU:
> do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
> if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> break;
>
> case LT:
> @@ -1057,7 +1059,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
> case LE:
> do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
> if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> break;
>
> case GT:
> @@ -1068,7 +1070,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op
> case GE:
> do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
> if_true_label, if_false_label,
> - inv (prob));
> + prob.invert ());
> break;
>
> case EQ:
> @@ -1078,7 +1080,8 @@ do_compare_rtx_and_jump (rtx op0, rtx op
>
> case NE:
> do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
> - if_false_label, inv (prob));
> + if_false_label,
> + prob.invert ());
> break;
>
> default:
> @@ -1115,11 +1118,13 @@ do_compare_rtx_and_jump (rtx op0, rtx op
>
> else
> {
> - int first_prob = prob;
> + profile_probability first_prob = prob;
> if (first_code == UNORDERED)
> - first_prob = REG_BR_PROB_BASE / 100;
> + first_prob = profile_probability::guessed_always ().apply_scale
> + (1, 100);
> else if (first_code == ORDERED)
> - first_prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100;
> + first_prob = profile_probability::guessed_always ().apply_scale
> + (99, 100);
> if (and_them)
> {
> rtx_code_label *dest_label;
> @@ -1165,7 +1170,7 @@ static void
> do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
> enum rtx_code unsigned_code,
> rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob)
> + rtx_code_label *if_true_label, profile_probability prob)
> {
> rtx op0, op1;
> tree type;
> Index: dojump.h
> ===================================================================
> --- dojump.h (revision 249769)
> +++ dojump.h (working copy)
> @@ -57,23 +57,26 @@ extern void save_pending_stack_adjust (s
> extern void restore_pending_stack_adjust (saved_pending_stack_adjust *);
>
> /* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
> -extern void jumpifnot (tree exp, rtx_code_label *label, int prob);
> -extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *, int);
> +extern void jumpifnot (tree exp, rtx_code_label *label,
> + profile_probability prob);
> +extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *,
> + profile_probability);
>
> /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
> -extern void jumpif (tree exp, rtx_code_label *label, int prob);
> -extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *, int);
> +extern void jumpif (tree exp, rtx_code_label *label, profile_probability prob);
> +extern void jumpif_1 (enum tree_code, tree, tree, rtx_code_label *,
> + profile_probability);
>
> /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
> the result is zero, or IF_TRUE_LABEL if the result is one. */
> extern void do_jump (tree exp, rtx_code_label *if_false_label,
> - rtx_code_label *if_true_label, int prob);
> + rtx_code_label *if_true_label, profile_probability prob);
> extern void do_jump_1 (enum tree_code, tree, tree, rtx_code_label *,
> - rtx_code_label *, int);
> + rtx_code_label *, profile_probability);
>
> extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
> machine_mode, rtx, rtx_code_label *,
> - rtx_code_label *, int);
> + rtx_code_label *, profile_probability);
>
> extern bool split_comparison (enum rtx_code, machine_mode,
> enum rtx_code *, enum rtx_code *);
> Index: dwarf2cfi.c
> ===================================================================
> --- dwarf2cfi.c (revision 249769)
> +++ dwarf2cfi.c (working copy)
> @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.
> #include "common/common-target.h"
>
> #include "except.h" /* expand_builtin_dwarf_sp_column */
> +#include "profile-count.h" /* For expr.h */
> #include "expr.h" /* init_return_column_size */
> #include "output.h" /* asm_out_file */
> #include "debug.h" /* dwarf2out_do_frame, dwarf2out_do_cfi_asm */
> Index: except.c
> ===================================================================
> --- except.c (revision 249769)
> +++ except.c (working copy)
> @@ -974,7 +974,6 @@ dw2_build_landing_pads (void)
> {
> basic_block bb;
> rtx_insn *seq;
> - edge e;
>
> if (lp == NULL || lp->post_landing_pad == NULL)
> continue;
> @@ -991,9 +990,7 @@ dw2_build_landing_pads (void)
> end_sequence ();
>
> bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
> - e = make_edge (bb, bb->next_bb, e_flags);
> - e->count = bb->count;
> - e->probability = REG_BR_PROB_BASE;
> + make_single_succ_edge (bb, bb->next_bb, e_flags);
> if (current_loops)
> {
> struct loop *loop = bb->next_bb->loop_father;
> @@ -1258,7 +1255,6 @@ sjlj_emit_dispatch_table (rtx_code_label
> rtx_insn *seq;
> basic_block bb;
> eh_region r;
> - edge e;
> int i, disp_index;
> vec<tree> dispatch_labels = vNULL;
>
> @@ -1346,9 +1342,7 @@ sjlj_emit_dispatch_table (rtx_code_label
>
> rtx_insn *before = label_rtx (lp->post_landing_pad);
> bb = emit_to_new_bb_before (seq2, before);
> - e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
> - e->count = bb->count;
> - e->probability = REG_BR_PROB_BASE;
> + make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
> if (current_loops)
> {
> struct loop *loop = bb->next_bb->loop_father;
> @@ -1386,9 +1380,7 @@ sjlj_emit_dispatch_table (rtx_code_label
> bb = emit_to_new_bb_before (seq, first_reachable_label);
> if (num_dispatch == 1)
> {
> - e = make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
> - e->count = bb->count;
> - e->probability = REG_BR_PROB_BASE;
> + make_single_succ_edge (bb, bb->next_bb, EDGE_FALLTHRU);
> if (current_loops)
> {
> struct loop *loop = bb->next_bb->loop_father;
> Index: explow.c
> ===================================================================
> --- explow.c (revision 249769)
> +++ explow.c (working copy)
> @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.
> #include "memmodel.h"
> #include "tm_p.h"
> #include "expmed.h"
> +#include "profile-count.h"
> #include "optabs.h"
> #include "emit-rtl.h"
> #include "recog.h"
> Index: expmed.c
> ===================================================================
> --- expmed.c (revision 249769)
> +++ expmed.c (working copy)
> @@ -5905,7 +5905,8 @@ emit_store_flag_force (rtx target, enum
> {
> label = gen_label_rtx ();
> do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, mode,
> - NULL_RTX, NULL, label, -1);
> + NULL_RTX, NULL, label,
> + profile_probability::uninitialized ());
> emit_move_insn (target, trueval);
> emit_label (label);
> return target;
> @@ -5943,7 +5944,7 @@ emit_store_flag_force (rtx target, enum
> emit_move_insn (target, trueval);
> label = gen_label_rtx ();
> do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, NULL,
> - label, -1);
> + label, profile_probability::uninitialized ());
>
> emit_move_insn (target, falseval);
> emit_label (label);
> @@ -5961,5 +5962,5 @@ do_cmp_and_jump (rtx arg1, rtx arg2, enu
> {
> int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU);
> do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, NULL_RTX,
> - NULL, label, -1);
> + NULL, label, profile_probability::uninitialized ());
> }
> Index: expr.c
> ===================================================================
> --- expr.c (revision 249769)
> +++ expr.c (working copy)
> @@ -96,7 +96,8 @@ static rtx do_store_flag (sepops, rtx, m
> #ifdef PUSH_ROUNDING
> static void emit_single_push_insn (machine_mode, rtx, tree);
> #endif
> -static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
> +static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx,
> + profile_probability);
> static rtx const_vector_from_tree (tree);
> static rtx const_scalar_mask_from_tree (tree);
> static tree tree_expr_size (const_tree);
> @@ -1452,7 +1453,7 @@ compare_by_pieces_d::generate (rtx op0,
> m_accumulator = NULL_RTX;
> }
> do_compare_rtx_and_jump (op0, op1, NE, true, mode, NULL_RTX, NULL,
> - m_fail_label, -1);
> + m_fail_label, profile_probability::uninitialized ());
> }
>
> /* Return true if MODE can be used for a set of moves and comparisons,
> @@ -1484,7 +1485,8 @@ compare_by_pieces_d::finish_mode (machin
> {
> if (m_accumulator != NULL_RTX)
> do_compare_rtx_and_jump (m_accumulator, const0_rtx, NE, true, mode,
> - NULL_RTX, NULL, m_fail_label, -1);
> + NULL_RTX, NULL, m_fail_label,
> + profile_probability::uninitialized ());
> }
>
> /* Generate several move instructions to compare LEN bytes from blocks
> @@ -1845,7 +1847,9 @@ emit_block_move_via_loop (rtx x, rtx y,
> emit_label (cmp_label);
>
> emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
> - true, top_label, REG_BR_PROB_BASE * 90 / 100);
> + true, top_label,
> + profile_probability::guessed_always ()
> + .apply_scale (9, 10));
> }
>
> /* Expand a call to memcpy or memmove or memcmp, and return the result.
> @@ -5402,7 +5406,8 @@ store_expr_with_bounds (tree exp, rtx ta
>
> do_pending_stack_adjust ();
> NO_DEFER_POP;
> - jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
> + jumpifnot (TREE_OPERAND (exp, 0), lab1,
> + profile_probability::uninitialized ());
> store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
> nontemporal, reverse, btarget);
> emit_jump_insn (targetm.gen_jump (lab2));
> @@ -6504,7 +6509,8 @@ store_constructor (tree exp, rtx target,
> /* Generate a conditional jump to exit the loop. */
> exit_cond = build2 (LT_EXPR, integer_type_node,
> index, hi_index);
> - jumpif (exit_cond, loop_end, -1);
> + jumpif (exit_cond, loop_end,
> + profile_probability::uninitialized ());
>
> /* Update the loop counter, and jump to the head of
> the loop. */
> @@ -9043,7 +9049,7 @@ expand_expr_real_2 (sepops ops, rtx targ
> lab = gen_label_rtx ();
> do_compare_rtx_and_jump (target, cmpop1, comparison_code,
> unsignedp, mode, NULL_RTX, NULL, lab,
> - -1);
> + profile_probability::uninitialized ());
> }
> emit_move_insn (target, op1);
> emit_label (lab);
> @@ -9272,7 +9278,8 @@ expand_expr_real_2 (sepops ops, rtx targ
> emit_move_insn (target, const0_rtx);
>
> rtx_code_label *lab1 = gen_label_rtx ();
> - jumpifnot_1 (code, treeop0, treeop1, lab1, -1);
> + jumpifnot_1 (code, treeop0, treeop1, lab1,
> + profile_probability::uninitialized ());
>
> if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
> emit_move_insn (target, constm1_rtx);
> @@ -9523,7 +9530,8 @@ expand_expr_real_2 (sepops ops, rtx targ
> NO_DEFER_POP;
> rtx_code_label *lab0 = gen_label_rtx ();
> rtx_code_label *lab1 = gen_label_rtx ();
> - jumpifnot (treeop0, lab0, -1);
> + jumpifnot (treeop0, lab0,
> + profile_probability::uninitialized ());
> store_expr (treeop1, temp,
> modifier == EXPAND_STACK_PARM,
> false, false);
> @@ -11042,7 +11050,8 @@ expand_expr_real_1 (tree exp, rtx target
> int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
> do_jump (TREE_OPERAND (rhs, 1),
> value ? label : 0,
> - value ? 0 : label, -1);
> + value ? 0 : label,
> + profile_probability::uninitialized ());
> expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
> false);
> do_pending_stack_adjust ();
> @@ -11512,7 +11521,7 @@ do_store_flag (sepops ops, rtx target, m
> int
> try_casesi (tree index_type, tree index_expr, tree minval, tree range,
> rtx table_label, rtx default_label, rtx fallback_label,
> - int default_probability)
> + profile_probability default_probability)
> {
> struct expand_operand ops[5];
> machine_mode index_mode = SImode;
> @@ -11582,7 +11591,7 @@ try_casesi (tree index_type, tree index_
>
> static void
> do_tablejump (rtx index, machine_mode mode, rtx range, rtx table_label,
> - rtx default_label, int default_probability)
> + rtx default_label, profile_probability default_probability)
> {
> rtx temp, vector;
>
> @@ -11645,7 +11654,8 @@ do_tablejump (rtx index, machine_mode mo
>
> int
> try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
> - rtx table_label, rtx default_label, int default_probability)
> + rtx table_label, rtx default_label,
> + profile_probability default_probability)
> {
> rtx index;
>
> Index: expr.h
> ===================================================================
> --- expr.h (revision 249769)
> +++ expr.h (working copy)
> @@ -288,8 +288,8 @@ expand_normal (tree exp)
> extern tree string_constant (tree, tree *);
>
> /* Two different ways of generating switch statements. */
> -extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, int);
> -extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, int);
> +extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
> +extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, profile_probability);
>
> extern int safe_from_p (const_rtx, tree, int);
>
> Index: gimple-pretty-print.c
> ===================================================================
> --- gimple-pretty-print.c (revision 249769)
> +++ gimple-pretty-print.c (working copy)
> @@ -80,7 +80,7 @@ debug_gimple_stmt (gimple *gs)
> by xstrdup_for_dump. */
>
> static const char *
> -dump_probability (int frequency, profile_count &count)
> +dump_profile (int frequency, profile_count &count)
> {
> float minimum = 0.01f;
>
> @@ -102,6 +102,38 @@ dump_probability (int frequency, profile
> return ret;
> }
>
> +/* Return formatted string of a VALUE probability
> + (biased by REG_BR_PROB_BASE). Returned string is allocated
> + by xstrdup_for_dump. */
> +
> +static const char *
> +dump_probability (profile_probability probability, profile_count &count)
> +{
> + float minimum = 0.01f;
> + float fvalue = -1;
> +
> + if (probability.initialized_p ())
> + {
> + fvalue = probability.to_reg_br_prob_base () * 100.0f / REG_BR_PROB_BASE;
> + if (fvalue < minimum && probability.to_reg_br_prob_base ())
> + fvalue = minimum;
> + }
> +
> + char *buf;
> + if (count.initialized_p ())
> + asprintf (&buf, "[%.2f%%] [count: %" PRId64 "]", fvalue,
> + count.to_gcov_type ());
> + else if (probability.initialized_p ())
> + asprintf (&buf, "[%.2f%%] [count: INV]", fvalue);
> + else
> + asprintf (&buf, "[INV] [count: INV]");
> +
> + const char *ret = xstrdup_for_dump (buf);
> + free (buf);
> +
> + return ret;
> +}
> +
> /* Dump E probability to BUFFER. */
>
> static void
> @@ -1090,7 +1122,7 @@ dump_gimple_label (pretty_printer *buffe
> dump_generic_node (buffer, label, spc, flags, false);
> basic_block bb = gimple_bb (gs);
> if (bb && !(flags & TDF_GIMPLE))
> - pp_scalar (buffer, " %s", dump_probability (bb->frequency, bb->count));
> + pp_scalar (buffer, " %s", dump_profile (bb->frequency, bb->count));
> pp_colon (buffer);
> }
> if (flags & TDF_GIMPLE)
> @@ -2670,8 +2702,8 @@ dump_gimple_bb_header (FILE *outf, basic
> fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
> else
> fprintf (outf, "%*s<bb %d> %s:\n",
> - indent, "", bb->index, dump_probability (bb->frequency,
> - bb->count));
> + indent, "", bb->index, dump_profile (bb->frequency,
> + bb->count));
> }
> }
> }
> Index: graph.c
> ===================================================================
> --- graph.c (revision 249769)
> +++ graph.c (working copy)
> @@ -136,12 +136,16 @@ draw_cfg_node_succ_edges (pretty_printer
>
> pp_printf (pp,
> "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n "
> - "[style=%s,color=%s,weight=%d,constraint=%s, label=\"[%i%%]\"];\n",
> + "[style=%s,color=%s,weight=%d,constraint=%s];\n",
> funcdef_no, e->src->index,
> funcdef_no, e->dest->index,
> style, color, weight,
> - (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true",
> - e->probability * 100 / REG_BR_PROB_BASE);
> + (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true");
> + if (e->probability.initialized_p ())
> + pp_printf (pp, ", label=\"[%i%%]\"",
> + e->probability.to_reg_br_prob_base ()
> + * 100 / REG_BR_PROB_BASE);
> + pp_printf (pp, "];\n");
> }
> pp_flush (pp);
> }
> Index: hsa-gen.c
> ===================================================================
> --- hsa-gen.c (revision 249769)
> +++ hsa-gen.c (working copy)
> @@ -6139,7 +6139,7 @@ convert_switch_statements (void)
> auto_vec <edge> new_edges;
> auto_vec <phi_definition *> phi_todo_list;
> auto_vec <profile_count> edge_counts;
> - auto_vec <int> edge_probabilities;
> + auto_vec <profile_probability> edge_probabilities;
>
> /* Investigate all labels that and PHI nodes in these edges which
> should be fixed after we add new collection of edges. */
> @@ -6231,12 +6231,12 @@ convert_switch_statements (void)
> basic_block label_bb
> = label_to_block_fn (func, CASE_LABEL (label));
> edge new_edge = make_edge (cur_bb, label_bb, EDGE_TRUE_VALUE);
> - int prob_sum = sum_slice <int> (edge_probabilities, i, labels, 0) +
> - edge_probabilities[0];
> + profile_probability prob_sum = sum_slice <profile_probability>
> + (edge_probabilities, i, labels, profile_probability::never ())
> + + edge_probabilities[0];
>
> - if (prob_sum)
> - new_edge->probability
> - = RDIV (REG_BR_PROB_BASE * edge_probabilities[i], prob_sum);
> + if (prob_sum.initialized_p ())
> + new_edge->probability = edge_probabilities[i] / prob_sum;
>
> new_edge->count = edge_counts[i];
> new_edges.safe_push (new_edge);
> @@ -6253,8 +6253,7 @@ convert_switch_statements (void)
> }
>
> edge next_edge = make_edge (cur_bb, next_bb, EDGE_FALSE_VALUE);
> - next_edge->probability
> - = inverse_probability (new_edge->probability);
> + next_edge->probability = new_edge->probability.invert ();
> next_edge->count = edge_counts[0]
> + sum_slice <profile_count> (edge_counts, i, labels,
> profile_count::zero ());
> @@ -6265,7 +6264,7 @@ convert_switch_statements (void)
> of the switch. */
> {
> edge e = make_edge (cur_bb, default_label_bb, EDGE_FALSE_VALUE);
> - e->probability = inverse_probability (new_edge->probability);
> + e->probability = new_edge->probability.invert ();
> e->count = edge_counts[0];
> new_edges.safe_insert (0, e);
> }
> Index: ifcvt.c
> ===================================================================
> --- ifcvt.c (revision 249769)
> +++ ifcvt.c (working copy)
> @@ -78,7 +78,7 @@ static int cond_exec_changed_p;
>
> /* Forward references. */
> static int count_bb_insns (const_basic_block);
> -static bool cheap_bb_rtx_cost_p (const_basic_block, int, int);
> +static bool cheap_bb_rtx_cost_p (const_basic_block, profile_probability, int);
> static rtx_insn *first_active_insn (basic_block);
> static rtx_insn *last_active_insn (basic_block, int);
> static rtx_insn *find_active_insn_before (basic_block, rtx_insn *);
> @@ -132,11 +132,14 @@ count_bb_insns (const_basic_block bb)
> plus a small fudge factor. */
>
> static bool
> -cheap_bb_rtx_cost_p (const_basic_block bb, int scale, int max_cost)
> +cheap_bb_rtx_cost_p (const_basic_block bb,
> + profile_probability prob, int max_cost)
> {
> int count = 0;
> rtx_insn *insn = BB_HEAD (bb);
> bool speed = optimize_bb_for_speed_p (bb);
> + int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
> + : REG_BR_PROB_BASE;
>
> /* Set scale to REG_BR_PROB_BASE to void the identical scaling
> applied to insn_rtx_cost when optimizing for size. Only do
> @@ -4807,7 +4810,8 @@ find_if_case_1 (basic_block test_bb, edg
> basic_block then_bb = then_edge->dest;
> basic_block else_bb = else_edge->dest;
> basic_block new_bb;
> - int then_bb_index, then_prob;
> + int then_bb_index;
> + profile_probability then_prob;
> rtx else_target = NULL_RTX;
>
> /* If we are partitioning hot/cold basic blocks, we don't want to
> @@ -4853,10 +4857,7 @@ find_if_case_1 (basic_block test_bb, edg
> "\nIF-CASE-1 found, start %d, then %d\n",
> test_bb->index, then_bb->index);
>
> - if (then_edge->probability)
> - then_prob = REG_BR_PROB_BASE - then_edge->probability;
> - else
> - then_prob = REG_BR_PROB_BASE / 2;
> + then_prob = then_edge->probability.invert ();
>
> /* We're speculating from the THEN path, we want to make sure the cost
> of speculation is within reason. */
> @@ -4927,7 +4928,7 @@ find_if_case_2 (basic_block test_bb, edg
> basic_block then_bb = then_edge->dest;
> basic_block else_bb = else_edge->dest;
> edge else_succ;
> - int then_prob, else_prob;
> + profile_probability then_prob, else_prob;
>
> /* We do not want to speculate (empty) loop latches. */
> if (current_loops
> @@ -4973,16 +4974,8 @@ find_if_case_2 (basic_block test_bb, edg
> if (then_bb->index < NUM_FIXED_BLOCKS)
> return FALSE;
>
> - if (else_edge->probability)
> - {
> - else_prob = else_edge->probability;
> - then_prob = REG_BR_PROB_BASE - else_prob;
> - }
> - else
> - {
> - else_prob = REG_BR_PROB_BASE / 2;
> - then_prob = REG_BR_PROB_BASE / 2;
> - }
> + else_prob = else_edge->probability;
> + then_prob = else_prob.invert ();
>
> /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
> if (else_prob > then_prob)
> Index: internal-fn.c
> ===================================================================
> --- internal-fn.c (revision 249769)
> +++ internal-fn.c (working copy)
> @@ -569,7 +569,7 @@ expand_arith_overflow_result_store (tree
> gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
> do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
> EQ, true, mode, NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> emit_label (done_label);
> }
> @@ -597,7 +597,7 @@ expand_arith_overflow_result_store (tree
> }
> do_compare_rtx_and_jump (res, lres,
> EQ, true, tgtmode, NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> emit_label (done_label);
> }
> @@ -767,7 +767,7 @@ expand_addsub_overflow (location_t loc,
> tem = op1;
> do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
> true, mode, NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -782,7 +782,7 @@ expand_addsub_overflow (location_t loc,
> code == PLUS_EXPR ? res : op0, sgn,
> NULL_RTX, false, OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL,
> - done_label, PROB_VERY_LIKELY);
> + done_label, profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -824,9 +824,9 @@ expand_addsub_overflow (location_t loc,
> else if (pos_neg == 3)
> /* If ARG0 is not known to be always positive, check at runtime. */
> do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
> - NULL, do_error, PROB_VERY_UNLIKELY);
> + NULL, do_error, profile_probability::very_unlikely ());
> do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL,
> - done_label, PROB_VERY_LIKELY);
> + done_label, profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -840,7 +840,7 @@ expand_addsub_overflow (location_t loc,
> rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL,
> - done_label, PROB_VERY_LIKELY);
> + done_label, profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -852,7 +852,7 @@ expand_addsub_overflow (location_t loc,
> res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
> - NULL, do_error, PROB_VERY_UNLIKELY);
> + NULL, do_error, profile_probability::very_unlikely ());
> rtx tem = op1;
> /* The operation is commutative, so we can pick operand to compare
> against. For prec <= BITS_PER_WORD, I think preferring REG operand
> @@ -866,7 +866,7 @@ expand_addsub_overflow (location_t loc,
> : CONST_SCALAR_INT_P (op0))
> tem = op0;
> do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL,
> - done_label, PROB_VERY_LIKELY);
> + done_label, profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -894,7 +894,7 @@ expand_addsub_overflow (location_t loc,
> ? and_optab : ior_optab,
> op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> }
> else
> {
> @@ -902,17 +902,17 @@ expand_addsub_overflow (location_t loc,
> do_compare_rtx_and_jump (op1, const0_rtx,
> code == MINUS_EXPR ? GE : LT, false, mode,
> NULL_RTX, NULL, do_ior_label,
> - PROB_EVEN);
> + profile_probability::even ());
> tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> emit_jump (do_error);
> emit_label (do_ior_label);
> tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> }
> goto do_error_label;
> }
> @@ -926,13 +926,13 @@ expand_addsub_overflow (location_t loc,
> OPTAB_LIB_WIDEN);
> rtx_code_label *op0_geu_op1 = gen_label_rtx ();
> do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL,
> - op0_geu_op1, PROB_EVEN);
> + op0_geu_op1, profile_probability::even ());
> do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> emit_jump (do_error);
> emit_label (op0_geu_op1);
> do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> goto do_error_label;
> }
>
> @@ -960,7 +960,7 @@ expand_addsub_overflow (location_t loc,
> && JUMP_P (last)
> && any_condjump_p (last)
> && !find_reg_note (last, REG_BR_PROB, 0))
> - add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
> + add_int_reg_note (last, REG_BR_PROB, PROB_UNLIKELY);
> emit_jump (done_label);
> goto do_error_label;
> }
> @@ -1020,7 +1020,7 @@ expand_addsub_overflow (location_t loc,
>
> /* No overflow if the result has bit sign cleared. */
> do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> }
>
> /* Compare the result of the operation with the first operand.
> @@ -1031,7 +1031,7 @@ expand_addsub_overflow (location_t loc,
> do_compare_rtx_and_jump (res, op0,
> (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
> false, mode, NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> }
>
> do_error_label:
> @@ -1128,7 +1128,7 @@ expand_neg_overflow (location_t loc, tre
> /* Compare the operand with the most negative value. */
> rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
> do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL,
> - done_label, PROB_VERY_LIKELY);
> + done_label, profile_probability::very_likely ());
> }
>
> emit_label (do_error);
> @@ -1261,15 +1261,15 @@ expand_mul_overflow (location_t loc, tre
> ops.location = loc;
> res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
> do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> goto do_error_label;
> case 3:
> rtx_code_label *do_main_label;
> do_main_label = gen_label_rtx ();
> do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, do_main_label, PROB_VERY_LIKELY);
> + NULL, do_main_label, profile_probability::very_likely ());
> do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
> - NULL, do_main_label, PROB_VERY_LIKELY);
> + NULL, do_main_label, profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> emit_label (do_main_label);
> goto do_main;
> @@ -1306,15 +1306,15 @@ expand_mul_overflow (location_t loc, tre
> ops.location = loc;
> res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
> do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
> - NULL, do_error, PROB_VERY_UNLIKELY);
> + NULL, do_error, profile_probability::very_unlikely ());
> int prec;
> prec = GET_MODE_PRECISION (mode);
> rtx sgn;
> sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
> do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
> - NULL, done_label, PROB_VERY_LIKELY);
> + NULL, done_label, profile_probability::very_likely ());
> goto do_error_label;
> case 3:
> /* Rest of handling of this case after res is computed. */
> @@ -1361,7 +1361,7 @@ expand_mul_overflow (location_t loc, tre
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
> NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> goto do_error_label;
> }
> /* The general case, do all the needed comparisons at runtime. */
> @@ -1378,7 +1378,7 @@ expand_mul_overflow (location_t loc, tre
> tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, after_negate_label, PROB_VERY_LIKELY);
> + NULL, after_negate_label, profile_probability::very_likely ());
> /* Both arguments negative here, negate them and continue with
> normal unsigned overflow checking multiplication. */
> emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
> @@ -1394,13 +1394,13 @@ expand_mul_overflow (location_t loc, tre
> tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
> OPTAB_LIB_WIDEN);
> do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, do_main_label, PROB_VERY_LIKELY);
> + NULL, do_main_label, profile_probability::very_likely ());
> /* One argument is negative here, the other positive. This
> overflows always, unless one of the arguments is 0. But
> if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
> is, thus we can keep do_main code oring in overflow as is. */
> do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
> - NULL, do_main_label, PROB_VERY_LIKELY);
> + NULL, do_main_label, profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> emit_label (do_main_label);
> goto do_main;
> @@ -1467,7 +1467,7 @@ expand_mul_overflow (location_t loc, tre
> HIPART is non-zero. */
> do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
> NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> else
> {
> rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
> @@ -1477,7 +1477,7 @@ expand_mul_overflow (location_t loc, tre
> HIPART is different from RES < 0 ? -1 : 0. */
> do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
> NULL_RTX, NULL, done_label,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> }
> }
> else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
> @@ -1570,12 +1570,12 @@ expand_mul_overflow (location_t loc, tre
> if (!op0_small_p)
> do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
> NULL_RTX, NULL, large_op0,
> - PROB_UNLIKELY);
> + profile_probability::unlikely ());
>
> if (!op1_small_p)
> do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
> NULL_RTX, NULL, small_op0_large_op1,
> - PROB_UNLIKELY);
> + profile_probability::unlikely ());
>
> /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
> hmode to mode, the multiplication will never overflow. We can
> @@ -1621,7 +1621,7 @@ expand_mul_overflow (location_t loc, tre
> if (!op1_small_p)
> do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
> NULL_RTX, NULL, both_ops_large,
> - PROB_UNLIKELY);
> + profile_probability::unlikely ());
>
> /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
> but op0 is not, prepare larger, hipart and lopart pseudos and
> @@ -1658,7 +1658,7 @@ expand_mul_overflow (location_t loc, tre
> else if (larger_sign != -1)
> do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
> NULL_RTX, NULL, after_hipart_neg,
> - PROB_EVEN);
> + profile_probability::even ());
>
> tem = convert_modes (mode, hmode, lopart, 1);
> tem = expand_shift (LSHIFT_EXPR, mode, tem, hprec, NULL_RTX, 1);
> @@ -1674,7 +1674,7 @@ expand_mul_overflow (location_t loc, tre
> else if (smaller_sign != -1)
> do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
> NULL_RTX, NULL, after_lopart_neg,
> - PROB_EVEN);
> + profile_probability::even ());
>
> tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
> 1, OPTAB_DIRECT);
> @@ -1704,7 +1704,7 @@ expand_mul_overflow (location_t loc, tre
>
> do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
> NULL_RTX, NULL, do_overflow,
> - PROB_VERY_UNLIKELY);
> + profile_probability::very_unlikely ());
>
> /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
> rtx loxhishifted = expand_shift (LSHIFT_EXPR, mode, loxhi, hprec,
> @@ -1741,7 +1741,7 @@ expand_mul_overflow (location_t loc, tre
> NULL_RTX, 1, OPTAB_DIRECT);
> do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
> NULL_RTX, NULL, do_error,
> - PROB_VERY_UNLIKELY);
> + profile_probability::very_unlikely ());
> }
>
> if (!op1_medium_p)
> @@ -1750,7 +1750,7 @@ expand_mul_overflow (location_t loc, tre
> NULL_RTX, 1, OPTAB_DIRECT);
> do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
> NULL_RTX, NULL, do_error,
> - PROB_VERY_UNLIKELY);
> + profile_probability::very_unlikely ());
> }
>
> /* At this point hipart{0,1} are both in [-1, 0]. If they are
> @@ -1761,18 +1761,18 @@ expand_mul_overflow (location_t loc, tre
> else if (op0_sign == 1 || op1_sign == 1)
> do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
> NULL_RTX, NULL, hipart_different,
> - PROB_EVEN);
> + profile_probability::even ());
>
> do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
> NULL_RTX, NULL, do_error,
> - PROB_VERY_UNLIKELY);
> + profile_probability::very_unlikely ());
> emit_jump (done_label);
>
> emit_label (hipart_different);
>
> do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
> NULL_RTX, NULL, do_error,
> - PROB_VERY_UNLIKELY);
> + profile_probability::very_unlikely ());
> emit_jump (done_label);
> }
>
> @@ -1817,7 +1817,7 @@ expand_mul_overflow (location_t loc, tre
> {
> rtx_code_label *all_done_label = gen_label_rtx ();
> do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, all_done_label, PROB_VERY_LIKELY);
> + NULL, all_done_label, profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> emit_label (all_done_label);
> }
> @@ -1828,14 +1828,14 @@ expand_mul_overflow (location_t loc, tre
> rtx_code_label *all_done_label = gen_label_rtx ();
> rtx_code_label *set_noovf = gen_label_rtx ();
> do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
> - NULL, all_done_label, PROB_VERY_LIKELY);
> + NULL, all_done_label, profile_probability::very_likely ());
> expand_arith_set_overflow (lhs, target);
> do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
> - NULL, set_noovf, PROB_VERY_LIKELY);
> + NULL, set_noovf, profile_probability::very_likely ());
> do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
> - NULL, all_done_label, PROB_VERY_UNLIKELY);
> + NULL, all_done_label, profile_probability::very_unlikely ());
> do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL,
> - all_done_label, PROB_VERY_UNLIKELY);
> + all_done_label, profile_probability::very_unlikely ());
> emit_label (set_noovf);
> write_complex_part (target, const0_rtx, true);
> emit_label (all_done_label);
> @@ -1977,7 +1977,7 @@ expand_vector_ubsan_overflow (location_t
> emit_move_insn (cntvar, ret);
> do_compare_rtx_and_jump (cntvar, GEN_INT (cnt), NE, false,
> TYPE_MODE (sizetype), NULL_RTX, NULL, loop_lab,
> - PROB_VERY_LIKELY);
> + profile_probability::very_likely ());
> }
> if (lhs && resv == NULL_TREE)
> {
> Index: ipa-cp.c
> ===================================================================
> --- ipa-cp.c (revision 249769)
> +++ ipa-cp.c (working copy)
> @@ -2623,7 +2623,8 @@ good_cloning_opportunity_p (struct cgrap
> struct ipa_node_params *info = IPA_NODE_REF (node);
> if (max_count > profile_count::zero ())
> {
> - int factor = RDIV (count_sum.probability_in (max_count)
> + int factor = RDIV (count_sum.probability_in
> + (max_count).to_reg_br_prob_base ()
> * 1000, REG_BR_PROB_BASE);
> int64_t evaluation = (((int64_t) time_benefit * factor)
> / size_cost);
> Index: ipa-split.c
> ===================================================================
> --- ipa-split.c (revision 249769)
> +++ ipa-split.c (working copy)
> @@ -1292,9 +1292,7 @@ split_function (basic_block return_bb, s
> break;
> }
> }
> - e = make_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = new_return_bb->count;
> + e = make_single_succ_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> add_bb_to_loop (new_return_bb, current_loops->tree_root);
> bitmap_set_bit (split_point->split_bbs, new_return_bb->index);
> retbnd = find_retbnd (return_bb);
> @@ -1527,11 +1525,9 @@ split_function (basic_block return_bb, s
> }
> else
> {
> - e = make_edge (call_bb, return_bb,
> - return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
> - ? 0 : EDGE_FALLTHRU);
> - e->count = call_bb->count;
> - e->probability = REG_BR_PROB_BASE;
> + e = make_single_succ_edge (call_bb, return_bb,
> + return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
> + ? 0 : EDGE_FALLTHRU);
>
> /* If there is return basic block, see what value we need to store
> return value into and put call just before it. */
> Index: ipa-utils.c
> ===================================================================
> --- ipa-utils.c (revision 249769)
> +++ ipa-utils.c (working copy)
> @@ -598,7 +598,8 @@ ipa_merge_profiles (struct cgraph_node *
> }
> }
> int prob = direct->count.probability_in (direct->count
> - + indirect->count);
> + + indirect->count).
> + to_reg_br_prob_base ();
> direct->frequency = RDIV (freq * prob, REG_BR_PROB_BASE);
> indirect->frequency = RDIV (freq * (REG_BR_PROB_BASE - prob),
> REG_BR_PROB_BASE);
> @@ -616,7 +617,8 @@ ipa_merge_profiles (struct cgraph_node *
> e2->speculative_call_info (direct, indirect, ref);
> e->count = count;
> e->frequency = freq;
> - int prob = direct->count.probability_in (e->count);
> + int prob = direct->count.probability_in (e->count)
> + .to_reg_br_prob_base ();
> e->make_speculative (direct->callee, direct->count,
> RDIV (freq * prob, REG_BR_PROB_BASE));
> }
> Index: loop-doloop.c
> ===================================================================
> --- loop-doloop.c (revision 249769)
> +++ loop-doloop.c (working copy)
> @@ -356,7 +356,8 @@ add_test (rtx cond, edge *e, basic_block
> op0 = force_operand (op0, NULL_RTX);
> op1 = force_operand (op1, NULL_RTX);
> label = block_label (dest);
> - do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label, -1);
> + do_compare_rtx_and_jump (op0, op1, code, 0, mode, NULL_RTX, NULL, label,
> + profile_probability::uninitialized ());
>
> jump = get_last_insn ();
> if (!jump || !JUMP_P (jump))
> @@ -575,10 +576,11 @@ doloop_modify (struct loop *loop, struct
> add_reg_note (jump_insn, REG_NONNEG, NULL_RTX);
>
> /* Update the REG_BR_PROB note. */
> - if (true_prob_val)
> + if (true_prob_val && desc->in_edge->probability.initialized_p ())
> {
> /* Seems safer to use the branch probability. */
> - add_int_reg_note (jump_insn, REG_BR_PROB, desc->in_edge->probability);
> + add_int_reg_note (jump_insn, REG_BR_PROB,
> + desc->in_edge->probability.to_reg_br_prob_base ());
> }
> }
>
> Index: loop-unroll.c
> ===================================================================
> --- loop-unroll.c (revision 249769)
> +++ loop-unroll.c (working copy)
> @@ -774,7 +774,8 @@ split_edge_and_insert (edge e, rtx_insn
>
> static rtx_insn *
> compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp,
> - rtx_code_label *label, int prob, rtx_insn *cinsn)
> + rtx_code_label *label, profile_probability prob,
> + rtx_insn *cinsn)
> {
> rtx_insn *seq;
> rtx_jump_insn *jump;
> @@ -808,12 +809,14 @@ compare_and_jump_seq (rtx op0, rtx op1,
> op0 = force_operand (op0, NULL_RTX);
> op1 = force_operand (op1, NULL_RTX);
> do_compare_rtx_and_jump (op0, op1, comp, 0,
> - mode, NULL_RTX, NULL, label, -1);
> + mode, NULL_RTX, NULL, label,
> + profile_probability::uninitialized ());
> jump = as_a <rtx_jump_insn *> (get_last_insn ());
> jump->set_jump_target (label);
> LABEL_NUSES (label)++;
> }
> - add_int_reg_note (jump, REG_BR_PROB, prob);
> + if (prob.initialized_p ())
> + add_int_reg_note (jump, REG_BR_PROB, prob.to_reg_br_prob_base ());
>
> seq = get_insns ();
> end_sequence ();
> @@ -857,7 +860,8 @@ unroll_loop_runtime_iterations (struct l
> {
> rtx old_niter, niter, tmp;
> rtx_insn *init_code, *branch_code;
> - unsigned i, j, p;
> + unsigned i, j;
> + profile_probability p;
> basic_block preheader, *body, swtch, ezc_swtch = NULL;
> int may_exit_copy, iter_freq, new_freq;
> profile_count iter_count, new_count;
> @@ -989,7 +993,7 @@ unroll_loop_runtime_iterations (struct l
>
> /* Create item for switch. */
> j = n_peel - i - (extra_zero_check ? 0 : 1);
> - p = REG_BR_PROB_BASE / (i + 2);
> + p = profile_probability::always ().apply_scale (1, i + 2);
>
> preheader = split_edge (loop_preheader_edge (loop));
> /* Add in frequency/count of edge from switch block. */
> @@ -1006,7 +1010,7 @@ unroll_loop_runtime_iterations (struct l
>
> swtch = split_edge_and_insert (single_pred_edge (swtch), branch_code);
> set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
> - single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
> + single_succ_edge (swtch)->probability = p.invert ();
> single_succ_edge (swtch)->count = new_count;
> new_freq += iter_freq;
> new_count += iter_count;
> @@ -1021,7 +1025,7 @@ unroll_loop_runtime_iterations (struct l
> if (extra_zero_check)
> {
> /* Add branch for zero iterations. */
> - p = REG_BR_PROB_BASE / (max_unroll + 1);
> + p = profile_probability::always ().apply_scale (1, max_unroll + 1);
> swtch = ezc_swtch;
> preheader = split_edge (loop_preheader_edge (loop));
> /* Recompute frequency/count adjustments since initial peel copy may
> @@ -1039,7 +1043,7 @@ unroll_loop_runtime_iterations (struct l
>
> swtch = split_edge_and_insert (single_succ_edge (swtch), branch_code);
> set_immediate_dominator (CDI_DOMINATORS, preheader, swtch);
> - single_succ_edge (swtch)->probability = REG_BR_PROB_BASE - p;
> + single_succ_edge (swtch)->probability = p.invert ();
> single_succ_edge (swtch)->count -= iter_count;
> e = make_edge (swtch, preheader,
> single_succ_edge (swtch)->flags & EDGE_IRREDUCIBLE_LOOP);
> Index: lra-constraints.c
> ===================================================================
> --- lra-constraints.c (revision 249769)
> +++ lra-constraints.c (working copy)
> @@ -6482,7 +6482,8 @@ lra_inheritance (void)
> e = find_fallthru_edge (bb->succs);
> if (! e)
> break;
> - if (e->probability < EBB_PROBABILITY_CUTOFF)
> + if (e->probability.initialized_p ()
> + && e->probability.to_reg_br_prob_base () < EBB_PROBABILITY_CUTOFF)
> break;
> bb = bb->next_bb;
> }
> Index: lto-streamer-in.c
> ===================================================================
> --- lto-streamer-in.c (revision 249769)
> +++ lto-streamer-in.c (working copy)
> @@ -754,12 +754,12 @@ input_cfg (struct lto_input_block *ib, s
> unsigned int dest_index;
> unsigned int edge_flags;
> basic_block dest;
> - int probability;
> + profile_probability probability;
> profile_count count;
> edge e;
>
> dest_index = streamer_read_uhwi (ib);
> - probability = (int) streamer_read_hwi (ib);
> + probability = profile_probability::stream_in (ib);
> count = profile_count::stream_in (ib).apply_scale
> (count_materialization_scale, REG_BR_PROB_BASE);
> edge_flags = streamer_read_uhwi (ib);
> Index: lto-streamer-out.c
> ===================================================================
> --- lto-streamer-out.c (revision 249769)
> +++ lto-streamer-out.c (working copy)
> @@ -1860,7 +1860,7 @@ output_cfg (struct output_block *ob, str
> FOR_EACH_EDGE (e, ei, bb->succs)
> {
> streamer_write_uhwi (ob, e->dest->index);
> - streamer_write_hwi (ob, e->probability);
> + e->probability.stream_out (ob);
> e->count.stream_out (ob);
> streamer_write_uhwi (ob, e->flags);
> }
> Index: mcf.c
> ===================================================================
> --- mcf.c (revision 249769)
> +++ mcf.c (working copy)
> @@ -1231,12 +1231,15 @@ adjust_cfg_counts (fixup_graph_type *fix
> }
>
> if (bb_gcov_count (bb))
> - e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
> - bb_gcov_count (bb));
> + e->probability = profile_probability::probability_in_gcov_type
> + (edge_gcov_count (e), bb_gcov_count (bb));
> if (dump_file)
> - fprintf (dump_file, " = %" PRId64 "\t(%.1f%%)\n",
> - edge_gcov_count (e),
> - e->probability * 100.0 / REG_BR_PROB_BASE);
> + {
> + fprintf (dump_file, " = %" PRId64 "\t",
> + edge_gcov_count (e));
> + e->probability.dump (dump_file);
> + fprintf (dump_file, "\n");
> + }
> }
> }
>
> @@ -1251,31 +1254,8 @@ adjust_cfg_counts (fixup_graph_type *fix
> if (bb_gcov_count (bb))
> {
> FOR_EACH_EDGE (e, ei, bb->succs)
> - e->probability = RDIV (REG_BR_PROB_BASE * edge_gcov_count (e),
> - bb_gcov_count (bb));
> - }
> - else
> - {
> - int total = 0;
> - FOR_EACH_EDGE (e, ei, bb->succs)
> - if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
> - total++;
> - if (total)
> - {
> - FOR_EACH_EDGE (e, ei, bb->succs)
> - {
> - if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
> - e->probability = REG_BR_PROB_BASE / total;
> - else
> - e->probability = 0;
> - }
> - }
> - else
> - {
> - total += EDGE_COUNT (bb->succs);
> - FOR_EACH_EDGE (e, ei, bb->succs)
> - e->probability = REG_BR_PROB_BASE / total;
> - }
> + e->probability = profile_probability::probability_in_gcov_type
> + (edge_gcov_count (e), bb_gcov_count (bb));
> }
> }
>
> Index: modulo-sched.c
> ===================================================================
> --- modulo-sched.c (revision 249769)
> +++ modulo-sched.c (working copy)
> @@ -1713,12 +1713,13 @@ sms_schedule (void)
> rtx comp_rtx = gen_rtx_GT (VOIDmode, count_reg,
> gen_int_mode (stage_count,
> GET_MODE (count_reg)));
> - unsigned prob = (PROB_SMS_ENOUGH_ITERATIONS
> - * REG_BR_PROB_BASE) / 100;
> + profile_probability prob = profile_probability::guessed_always ()
> + .apply_scale (PROB_SMS_ENOUGH_ITERATIONS, 100);
>
> loop_version (loop, comp_rtx, &condition_bb,
> - prob, REG_BR_PROB_BASE - prob,
> - prob, REG_BR_PROB_BASE - prob,
> + prob, prob.invert (),
> + prob.to_reg_br_prob_base (),
> + prob.invert ().to_reg_br_prob_base (),
> true);
> }
>
> Index: omp-expand.c
> ===================================================================
> --- omp-expand.c (revision 249769)
> +++ omp-expand.c (working copy)
> @@ -1741,9 +1741,9 @@ expand_omp_for_init_counts (struct omp_f
> entry_bb);
> }
> ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
> - ne->probability = REG_BR_PROB_BASE / 2000 - 1;
> + ne->probability = profile_probability::very_unlikely ();
> e->flags = EDGE_TRUE_VALUE;
> - e->probability = REG_BR_PROB_BASE - ne->probability;
> + e->probability = ne->probability.invert ();
> if (l2_dom_bb == NULL)
> l2_dom_bb = entry_bb;
> entry_bb = e->dest;
> @@ -1920,7 +1920,7 @@ extract_omp_for_update_vars (struct omp_
> if (i < fd->collapse - 1)
> {
> e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
> - e->probability = REG_BR_PROB_BASE / 8;
> + e->probability = profile_probability::guessed_always ().apply_scale (1, 8);
>
> t = fd->loops[i + 1].n1;
> t = force_gimple_operand_gsi (&gsi, t,
> @@ -1961,7 +1961,7 @@ extract_omp_for_update_vars (struct omp_
> stmt = gimple_build_cond_empty (t);
> gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
> e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
> - e->probability = REG_BR_PROB_BASE * 7 / 8;
> + e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
> }
> else
> make_edge (bb, body_bb, EDGE_FALLTHRU);
> @@ -2219,8 +2219,8 @@ expand_omp_ordered_sink (gimple_stmt_ite
> GSI_CONTINUE_LINKING);
> gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
> edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
> - e3->probability = REG_BR_PROB_BASE / 8;
> - e1->probability = REG_BR_PROB_BASE - e3->probability;
> + e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
> + e1->probability = e3->probability.invert ();
> e1->flags = EDGE_TRUE_VALUE;
> set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
>
> @@ -2373,9 +2373,9 @@ expand_omp_for_ordered_loops (struct omp
> remove_edge (e1);
> make_edge (body_bb, new_header, EDGE_FALLTHRU);
> e3->flags = EDGE_FALSE_VALUE;
> - e3->probability = REG_BR_PROB_BASE / 8;
> + e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
> e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
> - e1->probability = REG_BR_PROB_BASE - e3->probability;
> + e1->probability = e3->probability.invert ();
>
> set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
> set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
> @@ -3149,8 +3149,8 @@ expand_omp_for_generic (struct omp_regio
> e->flags = EDGE_TRUE_VALUE;
> if (e)
> {
> - e->probability = REG_BR_PROB_BASE * 7 / 8;
> - find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
> + e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
> + find_edge (cont_bb, l2_bb)->probability = e->probability.invert ();
> }
> else
> {
> @@ -3351,9 +3351,9 @@ expand_omp_for_static_nochunk (struct om
> ep = split_block (entry_bb, cond_stmt);
> ep->flags = EDGE_TRUE_VALUE;
> entry_bb = ep->dest;
> - ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
> + ep->probability = profile_probability::very_likely ();
> ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
> - ep->probability = REG_BR_PROB_BASE / 2000 - 1;
> + ep->probability = profile_probability::very_unlikely ();
> if (gimple_in_ssa_p (cfun))
> {
> int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
> @@ -3634,10 +3634,10 @@ expand_omp_for_static_nochunk (struct om
>
> /* Connect all the blocks. */
> ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
> - ep->probability = REG_BR_PROB_BASE / 4 * 3;
> + ep->probability = profile_probability::guessed_always ().apply_scale (3, 4);
> ep = find_edge (entry_bb, second_bb);
> ep->flags = EDGE_TRUE_VALUE;
> - ep->probability = REG_BR_PROB_BASE / 4;
> + ep->probability = profile_probability::guessed_always ().apply_scale (1, 4);
> find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
> find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
>
> @@ -3835,9 +3835,9 @@ expand_omp_for_static_chunk (struct omp_
> se = split_block (entry_bb, cond_stmt);
> se->flags = EDGE_TRUE_VALUE;
> entry_bb = se->dest;
> - se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
> + se->probability = profile_probability::very_likely ();
> se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
> - se->probability = REG_BR_PROB_BASE / 2000 - 1;
> + se->probability = profile_probability::very_unlikely ();
> if (gimple_in_ssa_p (cfun))
> {
> int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
> @@ -4448,8 +4448,8 @@ expand_cilk_for (struct omp_region *regi
>
> }
> ne->flags = EDGE_FALSE_VALUE;
> - e->probability = REG_BR_PROB_BASE * 7 / 8;
> - ne->probability = REG_BR_PROB_BASE / 8;
> + e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
> + ne->probability = e->probability.invert ();
>
> set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
> set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
> @@ -4810,8 +4810,8 @@ expand_omp_simd (struct omp_region *regi
>
> }
> ne->flags = EDGE_FALSE_VALUE;
> - e->probability = REG_BR_PROB_BASE * 7 / 8;
> - ne->probability = REG_BR_PROB_BASE / 8;
> + e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
> + ne->probability = e->probability.invert ();
>
> set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
> set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
> @@ -4824,8 +4824,10 @@ expand_omp_simd (struct omp_region *regi
> gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
> make_edge (entry_bb, l2_bb, EDGE_FALSE_VALUE);
> FALLTHRU_EDGE (entry_bb)->flags = EDGE_TRUE_VALUE;
> - FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE * 7 / 8;
> - BRANCH_EDGE (entry_bb)->probability = REG_BR_PROB_BASE / 8;
> + FALLTHRU_EDGE (entry_bb)->probability
> + = profile_probability::guessed_always ().apply_scale (7, 8);
> + BRANCH_EDGE (entry_bb)->probability
> + = FALLTHRU_EDGE (entry_bb)->probability.invert ();
> l2_dom_bb = entry_bb;
> }
> set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
> @@ -5018,9 +5020,9 @@ expand_omp_taskloop_for_outer (struct om
> gsi = gsi_last_bb (exit_bb);
> gsi_remove (&gsi, true);
>
> - FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
> + FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
> remove_edge (BRANCH_EDGE (entry_bb));
> - FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
> + FALLTHRU_EDGE (cont_bb)->probability = profile_probability::always ();
> remove_edge (BRANCH_EDGE (cont_bb));
> set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
> set_immediate_dominator (CDI_DOMINATORS, region->entry,
> @@ -5208,7 +5210,7 @@ expand_omp_taskloop_for_inner (struct om
> gsi = gsi_last_bb (exit_bb);
> gsi_remove (&gsi, true);
>
> - FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
> + FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
> if (!broken_loop)
> remove_edge (BRANCH_EDGE (entry_bb));
> else
> @@ -6604,8 +6606,11 @@ expand_omp_atomic_pipeline (basic_block
> e = single_succ_edge (store_bb);
> e->flags &= ~EDGE_FALLTHRU;
> e->flags |= EDGE_FALSE_VALUE;
> + /* Expect no looping. */
> + e->probability = profile_probability::guessed_always ();
>
> e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
> + e->probability = profile_probability::guessed_never ();
>
> /* Copy the new value to loadedi (we already did that before the condition
> if we are not in SSA). */
> Index: omp-simd-clone.c
> ===================================================================
> --- omp-simd-clone.c (revision 249769)
> +++ omp-simd-clone.c (working copy)
> @@ -1151,8 +1151,7 @@ simd_clone_adjust (struct cgraph_node *n
>
> if (incr_bb)
> {
> - edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> - e->probability = REG_BR_PROB_BASE;
> + make_single_succ_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
> gsi = gsi_last_bb (incr_bb);
> iter2 = make_ssa_name (iter);
> g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
> @@ -1264,7 +1263,10 @@ simd_clone_adjust (struct cgraph_node *n
>
> redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
>
> - make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
> + edge new_e = make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
> +
> + /* FIXME: Do we need to distribute probabilities for the conditional? */
> + new_e->probability = profile_probability::guessed_never ();
> /* The successor of incr_bb is already pointing to latch_bb; just
> change the flags.
> make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
> Index: optabs.c
> ===================================================================
> --- optabs.c (revision 249769)
> +++ optabs.c (working copy)
> @@ -693,7 +693,8 @@ expand_doubleword_shift (machine_mode op
>
> NO_DEFER_POP;
> do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode,
> - 0, 0, subword_label, -1);
> + 0, 0, subword_label,
> + profile_probability::uninitialized ());
> OK_DEFER_POP;
>
> if (!expand_superword_shift (binoptab, outof_input, superword_op1,
> @@ -3187,7 +3188,8 @@ expand_abs (machine_mode mode, rtx op0,
> NO_DEFER_POP;
>
> do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
> - NULL_RTX, NULL, op1, -1);
> + NULL_RTX, NULL, op1,
> + profile_probability::uninitialized ());
>
> op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
> target, target, 0);
> @@ -3979,7 +3981,8 @@ prepare_operand (enum insn_code icode, r
> we can do the branch. */
>
> static void
> -emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob)
> +emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
> + profile_probability prob)
> {
> machine_mode optab_mode;
> enum mode_class mclass;
> @@ -3994,13 +3997,13 @@ emit_cmp_and_jump_insn_1 (rtx test, mach
> gcc_assert (insn_operand_matches (icode, 0, test));
> insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
> XEXP (test, 1), label));
> - if (prob != -1
> + if (prob.initialized_p ()
> && profile_status_for_fn (cfun) != PROFILE_ABSENT
> && insn
> && JUMP_P (insn)
> && any_condjump_p (insn)
> && !find_reg_note (insn, REG_BR_PROB, 0))
> - add_int_reg_note (insn, REG_BR_PROB, prob);
> + add_int_reg_note (insn, REG_BR_PROB, prob.to_reg_br_prob_base ());
> }
>
> /* Generate code to compare X with Y so that the condition codes are
> @@ -4025,7 +4028,7 @@ emit_cmp_and_jump_insn_1 (rtx test, mach
> void
> emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
> machine_mode mode, int unsignedp, rtx label,
> - int prob)
> + profile_probability prob)
> {
> rtx op0 = x, op1 = y;
> rtx test;
> @@ -5856,7 +5859,8 @@ expand_compare_and_swap_loop (rtx mem, r
>
> /* Mark this jump predicted not taken. */
> emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
> - GET_MODE (success), 1, label, 0);
> + GET_MODE (success), 1, label,
> + profile_probability::guessed_never ());
> return true;
> }
>
> Index: optabs.h
> ===================================================================
> --- optabs.h (revision 249769)
> +++ optabs.h (working copy)
> @@ -247,7 +247,9 @@ extern rtx prepare_operand (enum insn_co
> /* Emit a pair of rtl insns to compare two rtx's and to jump
> to a label if the comparison is true. */
> extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
> - machine_mode, int, rtx, int prob=-1);
> + machine_mode, int, rtx,
> + profile_probability prob
> + = profile_probability::uninitialized ());
>
> /* Generate code to indirectly jump to a location given in the rtx LOC. */
> extern void emit_indirect_jump (rtx);
> Index: predict.c
> ===================================================================
> --- predict.c (revision 249769)
> +++ predict.c (working copy)
> @@ -404,11 +404,11 @@ optimize_loop_nest_for_size_p (struct lo
> bool
> predictable_edge_p (edge e)
> {
> - if (profile_status_for_fn (cfun) == PROFILE_ABSENT)
> + if (!e->probability.initialized_p ())
> return false;
> - if ((e->probability
> + if ((e->probability.to_reg_br_prob_base ()
> <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100)
> - || (REG_BR_PROB_BASE - e->probability
> + || (REG_BR_PROB_BASE - e->probability.to_reg_br_prob_base ()
> <= PARAM_VALUE (PARAM_PREDICTABLE_BRANCH_OUTCOME) * REG_BR_PROB_BASE / 100))
> return true;
> return false;
> @@ -539,7 +539,7 @@ probability_reliable_p (int prob)
> bool
> edge_probability_reliable_p (const_edge e)
> {
> - return probability_reliable_p (e->probability);
> + return e->probability.reliable_p ();
> }
>
> /* Same predicate as edge_probability_reliable_p, working on notes. */
> @@ -859,12 +859,13 @@ set_even_probabilities (basic_block bb,
> if (!unlikely_executed_edge_p (e))
> {
> if (unlikely_edges != NULL && unlikely_edges->contains (e))
> - e->probability = PROB_VERY_UNLIKELY;
> + e->probability = profile_probability::very_unlikely ();
> else
> - e->probability = (REG_BR_PROB_BASE + c / 2) / c;
> + e->probability = profile_probability::guessed_always ()
> + .apply_scale (1, c);
> }
> else
> - e->probability = 0;
> + e->probability = profile_probability::never ();
> }
>
> /* Combine all REG_BR_PRED notes into single probability and attach REG_BR_PROB
> @@ -971,20 +972,23 @@ combine_predictions_for_insn (rtx_insn *
> conditional jump. */
> if (!single_succ_p (bb))
> {
> - BRANCH_EDGE (bb)->probability = combined_probability;
> + BRANCH_EDGE (bb)->probability
> + = profile_probability::from_reg_br_prob_base (combined_probability);
> FALLTHRU_EDGE (bb)->probability
> - = REG_BR_PROB_BASE - combined_probability;
> + = BRANCH_EDGE (bb)->probability.invert ();
> }
> }
> else if (!single_succ_p (bb))
> {
> int prob = XINT (prob_note, 0);
>
> - BRANCH_EDGE (bb)->probability = prob;
> - FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
> + BRANCH_EDGE (bb)->probability
> + = profile_probability::from_reg_br_prob_base (prob);
> + FALLTHRU_EDGE (bb)->probability
> + = BRANCH_EDGE (bb)->probability.invert ();
> }
> else
> - single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
> + single_succ_edge (bb)->probability = profile_probability::always ();
> }
>
> /* Edge prediction hash traits. */
> @@ -1129,6 +1133,8 @@ combine_predictions_for_bb (basic_block
> if (!first)
> first = e;
> }
> + else if (!e->probability.initialized_p ())
> + e->probability = profile_probability::never ();
>
> /* When there is no successor or only one choice, prediction is easy.
>
> @@ -1173,8 +1179,8 @@ combine_predictions_for_bb (basic_block
> nedges, bb->index);
> FOR_EACH_EDGE (e, ei, bb->succs)
> if (!unlikely_executed_edge_p (e))
> - dump_prediction (dump_file, PRED_COMBINED, e->probability,
> - bb, REASON_NONE, e);
> + dump_prediction (dump_file, PRED_COMBINED,
> + e->probability.to_reg_br_prob_base (), bb, REASON_NONE, e);
> }
> }
> return;
> @@ -1284,8 +1290,9 @@ combine_predictions_for_bb (basic_block
>
> if (!bb->count.initialized_p () && !dry_run)
> {
> - first->probability = combined_probability;
> - second->probability = REG_BR_PROB_BASE - combined_probability;
> + first->probability
> + = profile_probability::from_reg_br_prob_base (combined_probability);
> + second->probability = first->probability.invert ();
> }
> }
>
> @@ -3042,7 +3049,7 @@ propagate_freq (basic_block head, bitmap
> * BLOCK_INFO (e->src)->frequency /
> REG_BR_PROB_BASE); */
>
> - sreal tmp = e->probability;
> + sreal tmp = e->probability.to_reg_br_prob_base ();
> tmp *= BLOCK_INFO (e->src)->frequency;
> tmp *= real_inv_br_prob_base;
> frequency += tmp;
> @@ -3074,7 +3081,7 @@ propagate_freq (basic_block head, bitmap
> = ((e->probability * BLOCK_INFO (bb)->frequency)
> / REG_BR_PROB_BASE); */
>
> - sreal tmp = e->probability;
> + sreal tmp = e->probability.to_reg_br_prob_base ();
> tmp *= BLOCK_INFO (bb)->frequency;
> EDGE_INFO (e)->back_edge_prob = tmp * real_inv_br_prob_base;
> }
> @@ -3534,7 +3541,7 @@ estimate_bb_frequencies (bool force)
> mark_dfs_back_edges ();
>
> single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->probability =
> - REG_BR_PROB_BASE;
> + profile_probability::always ();
>
> /* Set up block info for each basic block. */
> alloc_aux_for_blocks (sizeof (block_info));
> @@ -3546,7 +3553,8 @@ estimate_bb_frequencies (bool force)
>
> FOR_EACH_EDGE (e, ei, bb->succs)
> {
> - EDGE_INFO (e)->back_edge_prob = e->probability;
> + EDGE_INFO (e)->back_edge_prob
> + = e->probability.to_reg_br_prob_base ();
> EDGE_INFO (e)->back_edge_prob *= real_inv_br_prob_base;
> }
> }
> @@ -3898,16 +3906,18 @@ void
> force_edge_cold (edge e, bool impossible)
> {
> profile_count count_sum = profile_count::zero ();
> - int prob_sum = 0;
> + profile_probability prob_sum = profile_probability::never ();
> edge_iterator ei;
> edge e2;
> profile_count old_count = e->count;
> - int old_probability = e->probability;
> - int prob_scale = REG_BR_PROB_BASE;
> + profile_probability old_probability = e->probability;
> bool uninitialized_exit = false;
>
> + profile_probability goal = (impossible ? profile_probability::never ()
> + : profile_probability::very_unlikely ());
> +
> /* If edge is already improbably or cold, just return. */
> - if (e->probability <= (impossible ? PROB_VERY_UNLIKELY : 0)
> + if (e->probability <= goal
> && (!impossible || e->count == profile_count::zero ()))
> return;
> FOR_EACH_EDGE (e2, ei, e->src->succs)
> @@ -3917,24 +3927,26 @@ force_edge_cold (edge e, bool impossible
> count_sum += e2->count;
> else
> uninitialized_exit = true;
> - prob_sum += e2->probability;
> + if (e2->probability.initialized_p ())
> + prob_sum += e2->probability;
> }
>
> /* If there are other edges out of e->src, redistribute probabilitity
> there. */
> - if (prob_sum)
> + if (prob_sum > profile_probability::never ())
> {
> - e->probability
> - = MIN (e->probability, impossible ? 0 : PROB_VERY_UNLIKELY);
> + if (!(e->probability < goal))
> + e->probability = goal;
> if (impossible)
> e->count = profile_count::zero ();
> - else if (old_probability)
> - e->count = e->count.apply_scale (e->probability, old_probability);
> + else if (old_probability > profile_probability::never ())
> + e->count = e->count.apply_probability (e->probability
> + / old_probability);
> else
> e->count = e->count.apply_scale (1, REG_BR_PROB_BASE);
>
> - prob_scale = RDIV ((REG_BR_PROB_BASE - e->probability) * REG_BR_PROB_BASE,
> - prob_sum);
> + profile_probability prob_comp = prob_sum / e->probability.invert ();
> +
> if (dump_file && (dump_flags & TDF_DETAILS))
> fprintf (dump_file, "Making edge %i->%i %s by redistributing "
> "probability to other edges.\n",
> @@ -3946,15 +3958,14 @@ force_edge_cold (edge e, bool impossible
> {
> if (count_sum > 0)
> e2->count.apply_scale (count_sum2, count_sum);
> - e2->probability = RDIV (e2->probability * prob_scale,
> - REG_BR_PROB_BASE);
> + e2->probability /= prob_comp;
> }
> }
> /* If all edges out of e->src are unlikely, the basic block itself
> is unlikely. */
> else
> {
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> if (e->src->count == profile_count::zero ())
> return;
> if (count_sum == profile_count::zero () && !uninitialized_exit
> @@ -3989,7 +4000,8 @@ 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 == profile_count::zero ()
> + if (!(prob_sum > profile_probability::never ())
> + && count_sum == profile_count::zero ()
> && single_pred_p (e->src) && e->src->frequency > (impossible ? 0 : 1))
> {
> int old_frequency = e->src->frequency;
> Index: profile-count.c
> ===================================================================
> --- profile-count.c (revision 249769)
> +++ profile-count.c (working copy)
> @@ -31,6 +31,8 @@ along with GCC; see the file COPYING3.
> #include "data-streamer.h"
> #include "cgraph.h"
>
> +/* Dump THIS to F. */
> +
> void
> profile_count::dump (FILE *f) const
> {
> @@ -39,43 +41,53 @@ profile_count::dump (FILE *f) const
> else
> {
> fprintf (f, "%" PRId64, m_val);
> - if (m_quality == count_adjusted)
> - fprintf (f, "(adjusted)");
> - else if (m_quality == count_afdo)
> - fprintf (f, "(auto FDO)");
> - else if (m_quality == count_guessed)
> - fprintf (f, "(guessed)");
> + if (m_quality == profile_adjusted)
> + fprintf (f, " (adjusted)");
> + else if (m_quality == profile_afdo)
> + fprintf (f, " (auto FDO)");
> + else if (m_quality == profile_guessed)
> + fprintf (f, " (guessed)");
> }
> }
>
> +/* Dump THIS to stderr. */
> +
> void
> profile_count::debug () const
> {
> dump (stderr);
> + fprintf (stderr, "\n");
> }
>
> +/* Return true if THIS differs from OTHER; tolerate small diferences. */
> +
> bool
> profile_count::differs_from_p (profile_count other) const
> {
> if (!initialized_p () || !other.initialized_p ())
> return false;
> - if (m_val - other.m_val < 100 || other.m_val - m_val < 100)
> + if ((uint64_t)m_val - (uint64_t)other.m_val < 100
> + || (uint64_t)other.m_val - (uint64_t)m_val < 100)
> return false;
> if (!other.m_val)
> return true;
> - int64_t ratio = m_val * 100 / other.m_val;
> + int64_t ratio = (int64_t)m_val * 100 / other.m_val;
> return ratio < 99 || ratio > 101;
> }
>
> +/* Stream THIS from IB. */
> +
> profile_count
> profile_count::stream_in (struct lto_input_block *ib)
> {
> profile_count ret;
> ret.m_val = streamer_read_gcov_count (ib);
> - ret.m_quality = (profile_count_quality) streamer_read_uhwi (ib);
> + ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
> return ret;
> }
>
> +/* Stream THIS to OB. */
> +
> void
> profile_count::stream_out (struct output_block *ob)
> {
> @@ -83,9 +95,102 @@ profile_count::stream_out (struct output
> streamer_write_uhwi (ob, m_quality);
> }
>
> +/* Stream THIS to OB. */
> +
> void
> profile_count::stream_out (struct lto_output_stream *ob)
> {
> streamer_write_gcov_count_stream (ob, m_val);
> streamer_write_uhwi_stream (ob, m_quality);
> }
> +
> +/* Dump THIS to F. */
> +
> +void
> +profile_probability::dump (FILE *f) const
> +{
> + if (!initialized_p ())
> + fprintf (f, "uninitialized");
> + else
> + {
> + /* Make difference between 0.00 as a roundoff error and actual 0.
> + Similarly for 1. */
> + if (m_val == 0)
> + fprintf (f, "never");
> + else if (m_val == max_probability)
> + fprintf (f, "always");
> + else
> + fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
> + if (m_quality == profile_adjusted)
> + fprintf (f, " (adjusted)");
> + else if (m_quality == profile_afdo)
> + fprintf (f, " (auto FDO)");
> + else if (m_quality == profile_guessed)
> + fprintf (f, " (guessed)");
> + }
> +}
> +
> +/* Dump THIS to stderr. */
> +
> +void
> +profile_probability::debug () const
> +{
> + dump (stderr);
> + fprintf (stderr, "\n");
> +}
> +
> +/* Return true if THIS differs from OTHER; tolerate small diferences. */
> +
> +bool
> +profile_probability::differs_from_p (profile_probability other) const
> +{
> + if (!initialized_p () || !other.initialized_p ())
> + return false;
> + if ((uint64_t)m_val - (uint64_t)other.m_val < 10
> + || (uint64_t)other.m_val - (uint64_t)m_val < 10)
> + return false;
> + if (!other.m_val)
> + return true;
> + int64_t ratio = m_val * 100 / other.m_val;
> + return ratio < 99 || ratio > 101;
> +}
> +
> +/* Return true if THIS differs significantly from OTHER. */
> +
> +bool
> +profile_probability::differs_lot_from_p (profile_probability other) const
> +{
> + if (!initialized_p () || !other.initialized_p ())
> + return false;
> + uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
> + return d > max_probability / 2;
> +}
> +
> +/* Stream THIS from IB. */
> +
> +profile_probability
> +profile_probability::stream_in (struct lto_input_block *ib)
> +{
> + profile_probability ret;
> + ret.m_val = streamer_read_uhwi (ib);
> + ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
> + return ret;
> +}
> +
> +/* Stream THIS to OB. */
> +
> +void
> +profile_probability::stream_out (struct output_block *ob)
> +{
> + streamer_write_uhwi (ob, m_val);
> + streamer_write_uhwi (ob, m_quality);
> +}
> +
> +/* Stream THIS to OB. */
> +
> +void
> +profile_probability::stream_out (struct lto_output_stream *ob)
> +{
> + streamer_write_uhwi_stream (ob, m_val);
> + streamer_write_uhwi_stream (ob, m_quality);
> +}
> Index: profile-count.h
> ===================================================================
> --- profile-count.h (revision 249769)
> +++ profile-count.h (working copy)
> @@ -23,19 +23,19 @@ along with GCC; see the file COPYING3.
>
> /* Quality of the proflie count. Because gengtype does not support enums
> inside of clases, this is in global namespace. */
> -enum profile_count_quality {
> +enum profile_quality {
> /* Profile is based on static branch prediction heuristics. It may or may
> not reflect the reality. */
> - count_guessed = 0,
> + profile_guessed = 0,
> /* Profile was determined by autofdo. */
> - count_afdo = 1,
> + profile_afdo = 1,
> /* Profile was originally based on feedback but it was adjusted
> by code duplicating optimization. It may not precisely reflect the
> particular code path. */
> - count_adjusted = 2,
> + profile_adjusted = 2,
> /* Profile was read from profile feedback or determined by accurate static
> method. */
> - count_read = 3
> + profile_precise = 3
> };
>
> /* The base value for branch probability notes and edge probabilities. */
> @@ -43,6 +43,422 @@ enum profile_count_quality {
>
> #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
>
> +/* Data type to hold probabilities. It implement fixed point arithmetics
> + with capping so probability is always in range [0,1] and scaling requiring
> + values greater than 1 needs to be represented otherwise.
> +
> + In addition to actual value the quality of profile is tracked and propagated
> + through all operations. Special value UNINITIALIZED is used for probabilities
> + that has not been detemrined yet (for example bacause of
> + -fno-guess-branch-probability)
> +
> + Typically probabilities are derived from profile feedback (via
> + probability_in_gcov_type), autoFDO or guessed statically and then propagated
> + thorough the compilation.
> +
> + Named probabilities are available:
> + - never (0 probability)
> + - guessed_never
> + - very_unlikely (1/2000 probability)
> + - unlikely (1/5 probablity)
> + - even (1/2 probability)
> + - likely (4/5 probability)
> + - very_likely (1999/2000 probability)
> + - guessed_always
> + - always
> +
> + Named probabilities except for never/always are assumed to be statically
> + guessed and thus not necessarily acurate. The difference between never
> + and guessedn never is that the first one should be used only in case that
> + well behaving program will very likely not execute the "never" path.
> + For example if the path is going to abort () call or it exception handling.
> +
> + Alawyas and guessted_always probabilities are symmetric.
> +
> + For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
> + integer arithmetics. Once the code is converted to branch probabiitlies,
> + these conversions will probably go away because they are lossy.
> +*/
> +
> +class GTY((user)) profile_probability
> +{
> + /* For now use values in range 0...REG_BR_PROB_BASE. Later we can use full
> + precision of 30 bits available. */
> +
> + static const int n_bits = 30;
> + static const uint32_t max_probability = REG_BR_PROB_BASE;
> + static const uint32_t uninitialized_probability = ((uint32_t) 1 << n_bits) - 1;
> +
> + uint32_t m_val : 30;
> + enum profile_quality m_quality : 2;
> +
> + friend class profile_count;
> +public:
> +
> + /* Named probabilities. */
> + static profile_probability never ()
> + {
> + profile_probability ret;
> + ret.m_val = 0;
> + ret.m_quality = profile_precise;
> + return ret;
> + }
> + static profile_probability guessed_never ()
> + {
> + profile_probability ret;
> + ret.m_val = 0;
> + ret.m_quality = profile_guessed;
> + return ret;
> + }
> + static profile_probability very_unlikely ()
> + {
> + /* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
> + profile_probability r
> + = profile_probability::always ().apply_scale (1, 2000);
> + r.m_val--;
> + return r;
> + }
> + static profile_probability unlikely ()
> + {
> + /* Be consistent with PROB_VERY_LIKELY in predict.h. */
> + profile_probability r
> + = profile_probability::always ().apply_scale (1, 5);
> + r.m_val--;
> + return r;
> + }
> + static profile_probability even ()
> + {
> + return profile_probability::always ().apply_scale (1, 2);
> + }
> + static profile_probability very_likely ()
> + {
> + return profile_probability::always () - very_unlikely ();
> + }
> + static profile_probability likely ()
> + {
> + return profile_probability::always () - unlikely ();
> + }
> + static profile_probability guessed_always ()
> + {
> + profile_probability ret;
> + ret.m_val = max_probability;
> + ret.m_quality = profile_guessed;
> + return ret;
> + }
> + static profile_probability always ()
> + {
> + profile_probability ret;
> + ret.m_val = max_probability;
> + ret.m_quality = profile_precise;
> + return ret;
> + }
> + /* Probabilities which has not been initialized. Either because
> + initialization did not happen yet or because profile is unknown. */
> + static profile_probability uninitialized ()
> + {
> + profile_probability c;
> + c.m_val = uninitialized_probability;
> + c.m_quality = profile_guessed;
> + return c;
> + }
> +
> +
> + /* Return true if value has been initialized. */
> + bool initialized_p () const
> + {
> + return m_val != uninitialized_probability;
> + }
> + /* Return true if value can be trusted. */
> + bool reliable_p () const
> + {
> + return initialized_p ();
> + }
> +
> + /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
> + this is mostly to support legacy code and hsould go away. */
> + static profile_probability from_reg_br_prob_base (int v)
> + {
> + profile_probability ret;
> + gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
> + ret.m_val = RDIV (v * max_probability, REG_BR_PROB_BASE);
> + ret.m_quality = profile_guessed;
> + return ret;
> + }
> + int to_reg_br_prob_base () const
> + {
> + gcc_checking_assert (initialized_p ());
> + return RDIV (m_val * REG_BR_PROB_BASE, max_probability);
> + }
> +
> + /* Return VAL1/VAL2. */
> + static profile_probability probability_in_gcov_type
> + (gcov_type val1, gcov_type val2)
> + {
> + profile_probability ret;
> + gcc_checking_assert (val1 >= 0 && val2 > 0);
> + if (val1 > val2)
> + ret.m_val = max_probability;
> + else
> + ret.m_val = RDIV (val1 * max_probability, val2);
> + ret.m_quality = profile_precise;
> + return ret;
> + }
> +
> + /* Basic operations. */
> + bool operator== (const profile_probability &other) const
> + {
> + return m_val == other.m_val && m_quality == other.m_quality;
> + }
> + profile_probability operator+ (const profile_probability &other) const
> + {
> + if (other == profile_probability::never ())
> + return *this;
> + if (*this == profile_probability::never ())
> + return other;
> + if (!initialized_p () || !other.initialized_p ())
> + return profile_probability::uninitialized ();
> +
> + profile_probability ret;
> + ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
> + ret.m_quality = MIN (m_quality, other.m_quality);
> + return ret;
> + }
> + profile_probability &operator+= (const profile_probability &other)
> + {
> + if (other == profile_probability::never ())
> + return *this;
> + if (*this == profile_probability::never ())
> + {
> + *this = other;
> + return *this;
> + }
> + if (!initialized_p () || !other.initialized_p ())
> + return *this = profile_probability::uninitialized ();
> + else
> + {
> + m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
> + m_quality = MIN (m_quality, other.m_quality);
> + }
> + return *this;
> + }
> + profile_probability operator- (const profile_probability &other) const
> + {
> + if (*this == profile_probability::never ()
> + || other == profile_probability::never ())
> + return *this;
> + if (!initialized_p () || !other.initialized_p ())
> + return profile_probability::uninitialized ();
> + profile_probability ret;
> + ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
> + ret.m_quality = MIN (m_quality, other.m_quality);
> + return ret;
> + }
> + profile_probability &operator-= (const profile_probability &other)
> + {
> + if (*this == profile_probability::never ()
> + || other == profile_probability::never ())
> + return *this;
> + if (!initialized_p () || !other.initialized_p ())
> + return *this = profile_probability::uninitialized ();
> + else
> + {
> + m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
> + m_quality = MIN (m_quality, other.m_quality);
> + }
> + return *this;
> + }
> + profile_probability operator* (const profile_probability &other) const
> + {
> + if (*this == profile_probability::never ()
> + || other == profile_probability::never ())
> + return profile_probability::never ();
> + if (!initialized_p () || !other.initialized_p ())
> + return profile_probability::uninitialized ();
> + profile_probability ret;
> + ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
> + ret.m_quality = MIN (m_quality, other.m_quality);
> + return ret;
> + }
> + profile_probability &operator*= (const profile_probability &other)
> + {
> + if (*this == profile_probability::never ()
> + || other == profile_probability::never ())
> + return *this = profile_probability::never ();
> + if (!initialized_p () || !other.initialized_p ())
> + return *this = profile_probability::uninitialized ();
> + else
> + {
> + m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
> + m_quality = MIN (m_quality, other.m_quality);
> + }
> + return *this;
> + }
> + profile_probability operator/ (const profile_probability &other) const
> + {
> + if (*this == profile_probability::never ())
> + return profile_probability::never ();
> + if (!initialized_p () || !other.initialized_p ())
> + return profile_probability::uninitialized ();
> + profile_probability ret;
> + if (m_val >= other.m_val)
> + ret.m_val = max_probability;
> + else if (!m_val)
> + ret.m_val = 0;
> + else
> + {
> + gcc_checking_assert (other.m_val);
> + ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
> + other.m_val),
> + max_probability);
> + }
> + ret.m_quality = MIN (m_quality, other.m_quality);
> + return ret;
> + }
> + profile_probability &operator/= (const profile_probability &other)
> + {
> + if (*this == profile_probability::never ())
> + return *this = profile_probability::never ();
> + if (!initialized_p () || !other.initialized_p ())
> + return *this = profile_probability::uninitialized ();
> + else
> + {
> + if (m_val > other.m_val)
> + m_val = max_probability;
> + else if (!m_val)
> + ;
> + else
> + {
> + gcc_checking_assert (other.m_val);
> + m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
> + other.m_val),
> + max_probability);
> + }
> + m_quality = MIN (m_quality, other.m_quality);
> + }
> + return *this;
> + }
> +
> + gcov_type apply (gcov_type val) const
> + {
> + if (*this == profile_probability::uninitialized ())
> + return val / 2;
> + return RDIV (val * m_val, max_probability);
> + }
> +
> + /* Return 1-*THIS. */
> + profile_probability invert () const
> + {
> + return profile_probability::always() - *this;
> + }
> +
> + profile_probability combine_with_freq (int freq1, profile_probability other,
> + int freq2) const
> + {
> + profile_probability ret;
> +
> + if (*this == profile_probability::uninitialized ()
> + || other == profile_probability::uninitialized ())
> + return profile_probability::uninitialized ();
> +
> + gcc_checking_assert (freq1 >= 0 && freq2 >= 0);
> + if (!freq1 && !freq2)
> + {
> + ret.m_val = (m_val + other.m_val) / 2;
> + }
> + else
> + ret.m_val = RDIV (m_val * (uint64_t) freq1
> + + other.m_val * (uint64_t) freq2, freq1 + freq2);
> + ret.m_quality = MIN (m_quality, other.m_quality);
> + return ret;
> + }
> +
> + /* Return *THIS * NUM / DEN. */
> + profile_probability apply_scale (int64_t num, int64_t den) const
> + {
> + if (*this == profile_probability::never ())
> + return *this;
> + if (!initialized_p ())
> + return profile_probability::uninitialized ();
> + profile_probability ret;
> + ret.m_val = MIN (RDIV (m_val * num, den),
> + max_probability);
> + ret.m_quality = MIN (m_quality, profile_adjusted);
> + return ret;
> + }
> +
> + /* Return true when the probability of edge is reliable.
> +
> + The profile guessing code is good at predicting branch outcome (ie.
> + taken/not taken), that is predicted right slightly over 75% of time.
> + It is however notoriously poor on predicting the probability itself.
> + In general the profile appear a lot flatter (with probabilities closer
> + to 50%) than the reality so it is bad idea to use it to drive optimization
> + such as those disabling dynamic branch prediction for well predictable
> + branches.
> +
> + There are two exceptions - edges leading to noreturn edges and edges
> + predicted by number of iterations heuristics are predicted well. This macro
> + should be able to distinguish those, but at the moment it simply check for
> + noreturn heuristic that is only one giving probability over 99% or bellow
> + 1%. In future we might want to propagate reliability information across the
> + CFG if we find this information useful on multiple places. */
> +
> + bool probably_reliable_p () const
> + {
> + if (m_quality >= profile_adjusted)
> + return true;
> + if (!initialized_p ())
> + return false;
> + return m_val < max_probability / 100
> + || m_val > max_probability - max_probability / 100;
> + }
> +
> + /* Return false if profile_probability is bogus. */
> + bool verify () const
> + {
> + if (m_val == uninitialized_probability)
> + return m_quality == profile_guessed;
> + else
> + return m_val <= REG_BR_PROB_BASE;
> + }
> +
> + /* Comparsions are three-state and conservative. False is returned if
> + the inequality can not be decided. */
> + bool operator< (const profile_probability &other) const
> + {
> + return initialized_p () && other.initialized_p () && m_val < other.m_val;
> + }
> + bool operator> (const profile_probability &other) const
> + {
> + return initialized_p () && other.initialized_p () && m_val > other.m_val;
> + }
> +
> + bool operator<= (const profile_probability &other) const
> + {
> + return initialized_p () && other.initialized_p () && m_val <= other.m_val;
> + }
> + bool operator>= (const profile_probability &other) const
> + {
> + return initialized_p () && other.initialized_p () && m_val >= other.m_val;
> + }
> +
> + /* Output THIS to F. */
> + void dump (FILE *f) const;
> +
> + /* Print THIS to stderr. */
> + void debug () const;
> +
> + /* Return true if THIS is known to differ significantly from OTHER. */
> + bool differs_from_p (profile_probability other) const;
> + /* Return if difference is greater than 50%. */
> + bool differs_lot_from_p (profile_probability other) const;
> +
> + /* LTO streaming support. */
> + static profile_probability stream_in (struct lto_input_block *);
> + void stream_out (struct output_block *);
> + void stream_out (struct lto_output_stream *);
> +};
> +
> /* Main data type to hold profile counters in GCC. In most cases profile
> counts originate from profile feedback. They are 64bit integers
> representing number of executions during the train run.
> @@ -85,7 +501,7 @@ class GTY(()) profile_count
> static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
>
> uint64_t m_val : n_bits;
> - enum profile_count_quality m_quality : 2;
> + enum profile_quality m_quality : 2;
>
> /* Assume numbers smaller than this to multiply. This is set to make
> testsuite pass, in future we may implement precise multiplication in higer
> @@ -108,7 +524,7 @@ public:
> {
> profile_count c;
> c.m_val = uninitialized_count;
> - c.m_quality = count_guessed;
> + c.m_quality = profile_guessed;
> return c;
> }
>
> @@ -120,7 +536,7 @@ public:
> profile_count ret;
> gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
> ret.m_val = v;
> - ret.m_quality = count_read;
> + ret.m_quality = profile_precise;
> return ret;
> }
>
> @@ -207,7 +623,7 @@ public:
> /* Return false if profile_count is bogus. */
> bool verify () const
> {
> - return m_val != uninitialized_count || m_quality == count_guessed;
> + return m_val != uninitialized_count || m_quality == profile_guessed;
> }
>
> /* Comparsions are three-state and conservative. False is returned if
> @@ -237,7 +653,7 @@ public:
> }
> bool operator>= (const profile_count &other) const
> {
> - return initialized_p () && m_val >= other.m_val;
> + return initialized_p () && other.initialized_p () && m_val >= other.m_val;
> }
> bool operator<= (const gcov_type other) const
> {
> @@ -261,7 +677,23 @@ public:
> return profile_count::uninitialized ();
> profile_count ret;
> ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
> - ret.m_quality = MIN (m_quality, count_adjusted);
> + ret.m_quality = MIN (m_quality, profile_adjusted);
> + return ret;
> + }
> +
> + /* Scale counter according to PROB. */
> + profile_count apply_probability (profile_probability prob) const
> + {
> + if (*this == profile_count::zero ())
> + return *this;
> + if (prob == profile_probability::never ())
> + return profile_count::zero ();
> + if (!initialized_p ())
> + return profile_count::uninitialized ();
> + profile_count ret;
> + ret.m_val = RDIV (m_val * prob.m_val,
> + profile_probability::max_probability);
> + ret.m_quality = MIN (m_quality, prob.m_quality);
> return ret;
> }
> /* Return *THIS * NUM / DEN. */
> @@ -277,7 +709,7 @@ public:
> gcc_checking_assert ((num <= REG_BR_PROB_BASE
> || den <= REG_BR_PROB_BASE) || 1);
> ret.m_val = RDIV (m_val * num, den);
> - ret.m_quality = MIN (m_quality, count_adjusted);
> + ret.m_quality = MIN (m_quality, profile_adjusted);
> return ret;
> }
> profile_count apply_scale (profile_count num, profile_count den) const
> @@ -299,23 +731,27 @@ public:
> else
> ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
> den.m_val), max_safe_multiplier);
> - ret.m_quality = MIN (m_quality, count_adjusted);
> + ret.m_quality = MIN (m_quality, profile_adjusted);
> return ret;
> }
>
> /* Return probability of event with counter THIS within event with counter
> OVERALL. */
> - int probability_in (profile_count overall)
> + profile_probability probability_in (const profile_count overall) const
> {
> if (!m_val)
> - return 0;
> - if (!initialized_p () || !overall.initialized_p ())
> - return REG_BR_PROB_BASE / 2;
> - if (overall < *this)
> - return REG_BR_PROB_BASE;
> - if (!overall.m_val)
> - return REG_BR_PROB_BASE / 2;
> - return RDIV (m_val * REG_BR_PROB_BASE, overall.m_val);
> + return profile_probability::never ();
> + if (!initialized_p () || !overall.initialized_p ()
> + || !overall.m_val)
> + return profile_probability::uninitialized ();
> + profile_probability ret;
> + if (overall < m_val)
> + ret.m_val = profile_probability::max_probability;
> + else
> + ret.m_val = RDIV (m_val * profile_probability::max_probability,
> + overall.m_val);
> + ret.m_quality = MIN (m_quality, overall.m_quality);
> + return ret;
> }
>
> /* Output THIS to F. */
> Index: profile.c
> ===================================================================
> --- profile.c (revision 249769)
> +++ profile.c (working copy)
> @@ -768,8 +768,8 @@ compute_branch_probabilities (unsigned c
> if (bb_gcov_count (bb))
> {
> FOR_EACH_EDGE (e, ei, bb->succs)
> - e->probability = GCOV_COMPUTE_SCALE (edge_gcov_count (e),
> - bb_gcov_count (bb));
> + e->probability = profile_probability::probability_in_gcov_type
> + (edge_gcov_count (e), bb_gcov_count (bb));
> if (bb->index >= NUM_FIXED_BLOCKS
> && block_ends_with_condjump_p (bb)
> && EDGE_COUNT (bb->succs) >= 2)
> @@ -784,7 +784,7 @@ compute_branch_probabilities (unsigned c
> if (!(e->flags & (EDGE_FAKE | EDGE_FALLTHRU)))
> break;
>
> - prob = e->probability;
> + prob = e->probability.to_reg_br_prob_base ();
> index = prob * 20 / REG_BR_PROB_BASE;
>
> if (index == 20)
> @@ -810,15 +810,17 @@ compute_branch_probabilities (unsigned c
> {
> FOR_EACH_EDGE (e, ei, bb->succs)
> if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
> - e->probability = REG_BR_PROB_BASE / total;
> + e->probability
> + = profile_probability::guessed_always ().apply_scale (1, total);
> else
> - e->probability = 0;
> + e->probability = profile_probability::never ();
> }
> else
> {
> total += EDGE_COUNT (bb->succs);
> FOR_EACH_EDGE (e, ei, bb->succs)
> - e->probability = REG_BR_PROB_BASE / total;
> + e->probability
> + = profile_probability::guessed_always ().apply_scale (1, total);
> }
> if (bb->index >= NUM_FIXED_BLOCKS
> && block_ends_with_condjump_p (bb)
> Index: recog.c
> ===================================================================
> --- recog.c (revision 249769)
> +++ recog.c (working copy)
> @@ -3460,8 +3460,7 @@ peep2_attempt (basic_block bb, rtx_insn
> flags);
>
> nehe->probability = eh_edge->probability;
> - nfte->probability
> - = REG_BR_PROB_BASE - nehe->probability;
> + nfte->probability = nehe->probability.invert ();
>
> peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
> bb = nfte->src;
> Index: sched-ebb.c
> ===================================================================
> --- sched-ebb.c (revision 249769)
> +++ sched-ebb.c (working copy)
> @@ -648,7 +648,8 @@ schedule_ebbs (void)
> e = find_fallthru_edge (bb->succs);
> if (! e)
> break;
> - if (e->probability <= probability_cutoff)
> + if (e->probability.initialized_p ()
> + && e->probability.to_reg_br_prob_base () <= probability_cutoff)
> break;
> if (e->dest->flags & BB_DISABLE_SCHEDULE)
> break;
> Index: sched-rgn.c
> ===================================================================
> --- sched-rgn.c (revision 249769)
> +++ sched-rgn.c (working copy)
> @@ -507,7 +507,8 @@ find_single_block_region (bool ebbs_p)
> e = find_fallthru_edge (bb->succs);
> if (! e)
> break;
> - if (e->probability <= probability_cutoff)
> + if (e->probability.initialized_p ()
> + && e->probability.to_reg_br_prob_base () <= probability_cutoff)
> break;
> }
>
> @@ -1441,7 +1442,11 @@ compute_dom_prob_ps (int bb)
> FOR_EACH_EDGE (out_edge, out_ei, in_edge->src->succs)
> bitmap_set_bit (pot_split[bb], EDGE_TO_BIT (out_edge));
>
> - prob[bb] += combine_probabilities (prob[pred_bb], in_edge->probability);
> + prob[bb] += combine_probabilities
> + (prob[pred_bb],
> + in_edge->probability.initialized_p ()
> + ? in_edge->probability.to_reg_br_prob_base ()
> + : 0);
> // The rounding divide in combine_probabilities can result in an extra
> // probability increment propagating along 50-50 edges. Eventually when
> // the edges re-merge, the accumulated probability can go slightly above
> @@ -3171,8 +3176,10 @@ schedule_region (int rgn)
> sched_rgn_n_insns += sched_n_insns;
> realloc_bb_state_array (saved_last_basic_block);
> f = find_fallthru_edge (last_bb->succs);
> - if (f && f->probability * 100 / REG_BR_PROB_BASE >=
> - PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF))
> + if (f
> + && (!f->probability.initialized_p ()
> + || f->probability.to_reg_br_prob_base () * 100 / REG_BR_PROB_BASE >=
> + PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF)))
> {
> memcpy (bb_state[f->dest->index], curr_state,
> dfa_state_size);
> Index: sel-sched-ir.c
> ===================================================================
> --- sel-sched-ir.c (revision 249769)
> +++ sel-sched-ir.c (working copy)
> @@ -4747,7 +4747,9 @@ compute_succs_info (insn_t insn, short f
> sinfo->probs_ok.safe_push (
> /* FIXME: Improve calculation when skipping
> inner loop to exits. */
> - si.bb_end ? si.e1->probability : REG_BR_PROB_BASE);
> + si.bb_end && si.e1->probability.initialized_p ()
> + ? si.e1->probability.to_reg_br_prob_base ()
> + : REG_BR_PROB_BASE);
> sinfo->succs_ok_n++;
> }
> else
> @@ -4756,8 +4758,8 @@ compute_succs_info (insn_t insn, short f
> /* Compute all_prob. */
> if (!si.bb_end)
> sinfo->all_prob = REG_BR_PROB_BASE;
> - else
> - sinfo->all_prob += si.e1->probability;
> + else if (si.e1->probability.initialized_p ())
> + sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
>
> sinfo->all_succs_n++;
> }
> Index: stmt.c
> ===================================================================
> --- stmt.c (revision 249769)
> +++ stmt.c (working copy)
> @@ -93,9 +93,9 @@ struct case_node
> tree low; /* Lowest index value for this label */
> tree high; /* Highest index value for this label */
> tree code_label; /* Label to jump to when node matches */
> - int prob; /* Probability of taking this case. */
> + profile_probability prob; /* Probability of taking this case. */
> /* Probability of reaching subtree rooted at this node */
> - int subtree_prob;
> + profile_probability subtree_prob;
> };
>
> typedef struct case_node *case_node_ptr;
> @@ -108,7 +108,8 @@ static void balance_case_nodes (case_nod
> static int node_has_low_bound (case_node_ptr, tree);
> static int node_has_high_bound (case_node_ptr, tree);
> static int node_is_bounded (case_node_ptr, tree);
> -static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *, int, tree);
> +static void emit_case_nodes (rtx, case_node_ptr, rtx_code_label *,
> + profile_probability, tree);
>
> /* Return the rtx-label that corresponds to a LABEL_DECL,
> creating it if necessary. */
> @@ -704,9 +705,8 @@ expand_naked_return (void)
> is the probability of jumping to LABEL. */
> static void
> do_jump_if_equal (machine_mode mode, rtx op0, rtx op1, rtx_code_label *label,
> - int unsignedp, int prob)
> + int unsignedp, profile_probability prob)
> {
> - gcc_assert (prob <= REG_BR_PROB_BASE);
> do_compare_rtx_and_jump (op0, op1, EQ, unsignedp, mode,
> NULL_RTX, NULL, label, prob);
> }
> @@ -722,7 +722,7 @@ do_jump_if_equal (machine_mode mode, rtx
>
> static struct case_node *
> add_case_node (struct case_node *head, tree low, tree high,
> - tree label, int prob,
> + tree label, profile_probability prob,
> object_allocator<case_node> &case_node_pool)
> {
> struct case_node *r;
> @@ -859,7 +859,7 @@ expand_switch_as_decision_tree_p (tree r
> static void
> emit_case_decision_tree (tree index_expr, tree index_type,
> case_node_ptr case_list, rtx_code_label *default_label,
> - int default_prob)
> + profile_probability default_prob)
> {
> rtx index = expand_normal (index_expr);
>
> @@ -902,14 +902,14 @@ emit_case_decision_tree (tree index_expr
>
> /* Return the sum of probabilities of outgoing edges of basic block BB. */
>
> -static int
> +static profile_probability
> get_outgoing_edge_probs (basic_block bb)
> {
> edge e;
> edge_iterator ei;
> - int prob_sum = 0;
> + profile_probability prob_sum = profile_probability::never ();
> if (!bb)
> - return 0;
> + return profile_probability::never ();
> FOR_EACH_EDGE (e, ei, bb->succs)
> prob_sum += e->probability;
> return prob_sum;
> @@ -922,16 +922,11 @@ get_outgoing_edge_probs (basic_block bb)
> BASE_PROB is the probability of reaching the branch instruction relative
> to the same basic block BB. */
>
> -static inline int
> -conditional_probability (int target_prob, int base_prob)
> +static inline profile_probability
> +conditional_probability (profile_probability target_prob,
> + profile_probability base_prob)
> {
> - if (base_prob > 0)
> - {
> - gcc_assert (target_prob >= 0);
> - gcc_assert (target_prob <= base_prob);
> - return GCOV_COMPUTE_SCALE (target_prob, base_prob);
> - }
> - return -1;
> + return target_prob / base_prob;
> }
>
> /* Generate a dispatch tabler, switching on INDEX_EXPR and jumping to
> @@ -960,12 +955,13 @@ emit_case_dispatch_table (tree index_exp
> rtx_code_label *table_label = gen_label_rtx ();
> bool has_gaps = false;
> edge default_edge = stmt_bb ? EDGE_SUCC (stmt_bb, 0) : NULL;
> - int default_prob = default_edge ? default_edge->probability : 0;
> - int base = get_outgoing_edge_probs (stmt_bb);
> + profile_probability default_prob = default_edge ? default_edge->probability
> + : profile_probability::never ();
> + profile_probability base = get_outgoing_edge_probs (stmt_bb);
> bool try_with_tablejump = false;
>
> - int new_default_prob = conditional_probability (default_prob,
> - base);
> + profile_probability new_default_prob = conditional_probability (default_prob,
> + base);
>
> if (! try_casesi (index_type, index_expr, minval, range,
> table_label, default_label, fallback_label,
> @@ -1030,15 +1026,16 @@ emit_case_dispatch_table (tree index_exp
> through the indirect jump or the direct conditional jump
> before that. Split the probability of reaching the
> default label among these two jumps. */
> - new_default_prob = conditional_probability (default_prob/2,
> + new_default_prob = conditional_probability (default_prob.apply_scale
> + (1, 2),
> base);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> base -= default_prob;
> }
> else
> {
> base -= default_prob;
> - default_prob = 0;
> + default_prob = profile_probability::never ();
> }
>
> if (default_edge)
> @@ -1047,12 +1044,12 @@ emit_case_dispatch_table (tree index_exp
> /* We have altered the probability of the default edge. So the probabilities
> of all other edges need to be adjusted so that it sums up to
> REG_BR_PROB_BASE. */
> - if (base)
> + if (base > profile_probability::never ())
> {
> edge e;
> edge_iterator ei;
> FOR_EACH_EDGE (e, ei, stmt_bb->succs)
> - e->probability = GCOV_COMPUTE_SCALE (e->probability, base);
> + e->probability /= base;
> }
>
> if (try_with_tablejump)
> @@ -1150,7 +1147,7 @@ expand_case (gswitch *stmt)
> default_label = jump_target_rtx
> (CASE_LABEL (gimple_switch_default_label (stmt)));
> edge default_edge = EDGE_SUCC (bb, 0);
> - int default_prob = default_edge->probability;
> + profile_probability default_prob = default_edge->probability;
>
> /* Get upper and lower bounds of case values. */
> elt = gimple_switch_label (stmt, 1);
> @@ -1213,7 +1210,7 @@ expand_case (gswitch *stmt)
> edge case_edge = find_edge (bb, case_bb);
> case_list = add_case_node (
> case_list, low, high, lab,
> - case_edge->probability / (intptr_t)(case_edge->aux),
> + case_edge->probability.apply_scale (1, (intptr_t)(case_edge->aux)),
> case_node_pool);
> }
> reset_out_edges_aux (bb);
> @@ -1310,7 +1307,8 @@ expand_sjlj_dispatch_table (rtx dispatch
> {
> tree elt = dispatch_table[i];
> rtx_code_label *lab = jump_target_rtx (CASE_LABEL (elt));
> - do_jump_if_equal (index_mode, index, zero, lab, 0, -1);
> + do_jump_if_equal (index_mode, index, zero, lab, 0,
> + profile_probability::uninitialized ());
> force_expand_binop (index_mode, sub_optab,
> index, CONST1_RTX (index_mode),
> index, 0, OPTAB_DIRECT);
> @@ -1332,7 +1330,10 @@ expand_sjlj_dispatch_table (rtx dispatch
> tree elt = dispatch_table[i];
> tree low = CASE_LOW (elt);
> tree lab = CASE_LABEL (elt);
> - case_list = add_case_node (case_list, low, low, lab, 0, case_node_pool);
> + case_list = add_case_node (case_list, low, low, lab,
> + profile_probability::guessed_always ()
> + .apply_scale (1, ncases),
> + case_node_pool);
> }
>
> emit_case_dispatch_table (index_expr, index_type,
> @@ -1576,12 +1577,12 @@ node_is_bounded (case_node_ptr node, tre
>
> static void
> emit_case_nodes (rtx index, case_node_ptr node, rtx_code_label *default_label,
> - int default_prob, tree index_type)
> + profile_probability default_prob, tree index_type)
> {
> /* If INDEX has an unsigned type, we must make unsigned branches. */
> int unsignedp = TYPE_UNSIGNED (index_type);
> - int probability;
> - int prob = node->prob, subtree_prob = node->subtree_prob;
> + profile_probability probability;
> + profile_probability prob = node->prob, subtree_prob = node->subtree_prob;
> machine_mode mode = GET_MODE (index);
> machine_mode imode = TYPE_MODE (index_type);
>
> @@ -1701,7 +1702,7 @@ emit_case_nodes (rtx index, case_node_pt
> subtree or the left subtree. Divide the probability
> equally. */
> probability = conditional_probability (
> - node->right->subtree_prob + default_prob/2,
> + node->right->subtree_prob + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> /* See if the value is on the right. */
> emit_cmp_and_jump_insns (index,
> @@ -1712,7 +1713,7 @@ emit_case_nodes (rtx index, case_node_pt
> GT, NULL_RTX, mode, unsignedp,
> label_rtx (test_label),
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
>
> /* Value must be on the left.
> Handle the left-hand subtree. */
> @@ -1743,7 +1744,7 @@ emit_case_nodes (rtx index, case_node_pt
> if (!node_has_low_bound (node, index_type))
> {
> probability = conditional_probability (
> - default_prob/2,
> + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> emit_cmp_and_jump_insns (index,
> convert_modes
> @@ -1753,7 +1754,7 @@ emit_case_nodes (rtx index, case_node_pt
> LT, NULL_RTX, mode, unsignedp,
> default_label,
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> }
>
> emit_case_nodes (index, node->right, default_label, default_prob, index_type);
> @@ -1785,7 +1786,7 @@ emit_case_nodes (rtx index, case_node_pt
> if (!node_has_high_bound (node, index_type))
> {
> probability = conditional_probability (
> - default_prob/2,
> + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> emit_cmp_and_jump_insns (index,
> convert_modes
> @@ -1795,7 +1796,7 @@ emit_case_nodes (rtx index, case_node_pt
> GT, NULL_RTX, mode, unsignedp,
> default_label,
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> }
>
> emit_case_nodes (index, node->left, default_label,
> @@ -1858,7 +1859,7 @@ emit_case_nodes (rtx index, case_node_pt
> test_label = build_decl (curr_insn_location (),
> LABEL_DECL, NULL_TREE, void_type_node);
> probability = conditional_probability (
> - node->right->subtree_prob + default_prob/2,
> + node->right->subtree_prob + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> emit_cmp_and_jump_insns (index,
> convert_modes
> @@ -1868,7 +1869,7 @@ emit_case_nodes (rtx index, case_node_pt
> GT, NULL_RTX, mode, unsignedp,
> label_rtx (test_label),
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> }
>
> /* Value belongs to this node or to the left-hand subtree. */
> @@ -1909,7 +1910,7 @@ emit_case_nodes (rtx index, case_node_pt
> if (!node_has_low_bound (node, index_type))
> {
> probability = conditional_probability (
> - default_prob/2,
> + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> emit_cmp_and_jump_insns (index,
> convert_modes
> @@ -1919,7 +1920,7 @@ emit_case_nodes (rtx index, case_node_pt
> LT, NULL_RTX, mode, unsignedp,
> default_label,
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> }
>
> /* Value belongs to this node or to the right-hand subtree. */
> @@ -1946,7 +1947,7 @@ emit_case_nodes (rtx index, case_node_pt
> if (!node_has_high_bound (node, index_type))
> {
> probability = conditional_probability (
> - default_prob/2,
> + default_prob.apply_scale (1, 2),
> subtree_prob + default_prob);
> emit_cmp_and_jump_insns (index,
> convert_modes
> @@ -1956,7 +1957,7 @@ emit_case_nodes (rtx index, case_node_pt
> GT, NULL_RTX, mode, unsignedp,
> default_label,
> probability);
> - default_prob /= 2;
> + default_prob = default_prob.apply_scale (1, 2);
> }
>
> /* Value belongs to this node or to the left-hand subtree. */
> Index: targhooks.c
> ===================================================================
> --- targhooks.c (revision 249769)
> +++ targhooks.c (working copy)
> @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.
> #include "stringpool.h"
> #include "tree-vrp.h"
> #include "tree-ssanames.h"
> +#include "profile-count.h"
> #include "optabs.h"
> #include "regs.h"
> #include "recog.h"
> Index: tracer.c
> ===================================================================
> --- tracer.c (revision 249769)
> +++ tracer.c (working copy)
> @@ -135,10 +135,8 @@ better_p (const_edge e1, const_edge e2)
> if (e1->count.initialized_p () && e2->count.initialized_p ()
> && !(e1->count == e2->count))
> return e1->count > e2->count;
> - if (e1->src->frequency * e1->probability !=
> - e2->src->frequency * e2->probability)
> - return (e1->src->frequency * e1->probability
> - > e2->src->frequency * e2->probability);
> + if (EDGE_FREQUENCY (e1) != EDGE_FREQUENCY (e2))
> + return EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2);
> /* This is needed to avoid changes in the decision after
> CFG is modified. */
> if (e1->src != e2->src)
> @@ -160,7 +158,8 @@ find_best_successor (basic_block bb)
> best = e;
> if (!best || ignore_bb_p (best->dest))
> return NULL;
> - if (best->probability <= probability_cutoff)
> + if (best->probability.initialized_p ()
> + && best->probability.to_reg_br_prob_base () <= probability_cutoff)
> return NULL;
> return best;
> }
> Index: trans-mem.c
> ===================================================================
> --- trans-mem.c (revision 249769)
> +++ trans-mem.c (working copy)
> @@ -2934,9 +2934,9 @@ expand_transaction (struct tm_region *re
> join_bb->frequency = test_bb->frequency = transaction_bb->frequency;
> join_bb->count = test_bb->count = transaction_bb->count;
>
> - ei->probability = PROB_ALWAYS;
> - et->probability = PROB_LIKELY;
> - ef->probability = PROB_UNLIKELY;
> + ei->probability = profile_probability::always ();
> + et->probability = profile_probability::likely ();
> + ef->probability = profile_probability::unlikely ();
> et->count = test_bb->count.apply_probability (et->probability);
> ef->count = test_bb->count.apply_probability (ef->probability);
>
> @@ -2967,20 +2967,20 @@ expand_transaction (struct tm_region *re
> edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU);
> test_bb->frequency = transaction_bb->frequency;
> test_bb->count = transaction_bb->count;
> - ei->probability = PROB_ALWAYS;
> + ei->probability = profile_probability::always ();
>
> // Not abort edge. If both are live, chose one at random as we'll
> // we'll be fixing that up below.
> redirect_edge_pred (fallthru_edge, test_bb);
> fallthru_edge->flags = EDGE_FALSE_VALUE;
> - fallthru_edge->probability = PROB_VERY_LIKELY;
> + fallthru_edge->probability = profile_probability::very_likely ();
> fallthru_edge->count = test_bb->count.apply_probability
> (fallthru_edge->probability);
>
> // Abort/over edge.
> redirect_edge_pred (abort_edge, test_bb);
> abort_edge->flags = EDGE_TRUE_VALUE;
> - abort_edge->probability = PROB_VERY_UNLIKELY;
> + abort_edge->probability = profile_probability::unlikely ();
> abort_edge->count = test_bb->count.apply_probability
> (abort_edge->probability);
>
> @@ -3020,13 +3020,13 @@ expand_transaction (struct tm_region *re
> // use the uninst path when falling back to serial mode.
> redirect_edge_pred (inst_edge, test_bb);
> inst_edge->flags = EDGE_FALSE_VALUE;
> - inst_edge->probability = REG_BR_PROB_BASE / 2;
> + inst_edge->probability = profile_probability::even ();
> inst_edge->count
> = test_bb->count.apply_probability (inst_edge->probability);
>
> redirect_edge_pred (uninst_edge, test_bb);
> uninst_edge->flags = EDGE_TRUE_VALUE;
> - uninst_edge->probability = REG_BR_PROB_BASE / 2;
> + uninst_edge->probability = profile_probability::even ();
> uninst_edge->count
> = test_bb->count.apply_probability (uninst_edge->probability);
> }
> Index: tree-call-cdce.c
> ===================================================================
> --- tree-call-cdce.c (revision 249769)
> +++ tree-call-cdce.c (working copy)
> @@ -752,10 +752,6 @@ gen_shrink_wrap_conditions (gcall *bi_ca
> return;
> }
>
> -
> -/* Probability of the branch (to the call) is taken. */
> -#define ERR_PROB 0.01
> -
> /* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
> conditions in CONDS is false. */
>
> @@ -916,14 +912,15 @@ shrink_wrap_one_built_in_call_with_conds
> basic_block src_bb = call_edge->src;
> gcc_assert (src_bb == nocall_edge->src);
>
> - call_edge->probability = REG_BR_PROB_BASE * ERR_PROB;
> + call_edge->probability = profile_probability::very_unlikely ();
> call_edge->count
> = src_bb->count.apply_probability (call_edge->probability);
> - nocall_edge->probability = inverse_probability (call_edge->probability);
> + nocall_edge->probability = profile_probability::always ()
> + - call_edge->probability;
> nocall_edge->count = src_bb->count - call_edge->count;
>
> - unsigned int call_frequency = apply_probability (src_bb->frequency,
> - call_edge->probability);
> + unsigned int call_frequency
> + = call_edge->probability.apply (src_bb->frequency);
>
> bi_call_bb->count += call_edge->count;
> bi_call_bb->frequency += call_frequency;
> Index: tree-cfg.c
> ===================================================================
> --- tree-cfg.c (revision 249769)
> +++ tree-cfg.c (working copy)
> @@ -2837,9 +2837,7 @@ gimple_split_edge (edge edge_in)
> new_bb = create_empty_bb (after_bb);
> new_bb->frequency = EDGE_FREQUENCY (edge_in);
> new_bb->count = edge_in->count;
> - new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
> - new_edge->probability = REG_BR_PROB_BASE;
> - new_edge->count = edge_in->count;
> + new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU);
>
> e = redirect_edge_and_branch (edge_in, new_bb);
> gcc_assert (e == edge_in);
> @@ -7244,7 +7242,7 @@ move_sese_region_to_fn (struct function
> basic_block after, bb, *entry_pred, *exit_succ, abb;
> struct function *saved_cfun = cfun;
> int *entry_flag, *exit_flag;
> - unsigned *entry_prob, *exit_prob;
> + profile_probability *entry_prob, *exit_prob;
> unsigned i, num_entry_edges, num_exit_edges, num_nodes;
> edge e;
> edge_iterator ei;
> @@ -7282,7 +7280,7 @@ move_sese_region_to_fn (struct function
> num_entry_edges = EDGE_COUNT (entry_bb->preds);
> entry_pred = XNEWVEC (basic_block, num_entry_edges);
> entry_flag = XNEWVEC (int, num_entry_edges);
> - entry_prob = XNEWVEC (unsigned, num_entry_edges);
> + entry_prob = XNEWVEC (profile_probability, num_entry_edges);
> i = 0;
> for (ei = ei_start (entry_bb->preds); (e = ei_safe_edge (ei)) != NULL;)
> {
> @@ -7297,7 +7295,7 @@ move_sese_region_to_fn (struct function
> num_exit_edges = EDGE_COUNT (exit_bb->succs);
> exit_succ = XNEWVEC (basic_block, num_exit_edges);
> exit_flag = XNEWVEC (int, num_exit_edges);
> - exit_prob = XNEWVEC (unsigned, num_exit_edges);
> + exit_prob = XNEWVEC (profile_probability, num_exit_edges);
> i = 0;
> for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
> {
> Index: tree-cfgcleanup.c
> ===================================================================
> --- tree-cfgcleanup.c (revision 249769)
> +++ tree-cfgcleanup.c (working copy)
> @@ -155,8 +155,6 @@ cleanup_control_expr_graph (basic_block
> }
> if (!warned)
> fold_undefer_and_ignore_overflow_warnings ();
> - if (taken_edge->probability > REG_BR_PROB_BASE)
> - taken_edge->probability = REG_BR_PROB_BASE;
> }
> else
> taken_edge = single_succ_edge (bb);
> Index: tree-eh.c
> ===================================================================
> --- tree-eh.c (revision 249769)
> +++ tree-eh.c (working copy)
> @@ -3244,9 +3244,7 @@ lower_resx (basic_block bb, gresx *stmt,
> }
>
> gcc_assert (EDGE_COUNT (bb->succs) == 0);
> - e = make_edge (bb, new_bb, EDGE_FALLTHRU);
> - e->count = bb->count;
> - e->probability = REG_BR_PROB_BASE;
> + e = make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
> }
> else
> {
> @@ -3262,7 +3260,7 @@ lower_resx (basic_block bb, gresx *stmt,
> e = single_succ_edge (bb);
> gcc_assert (e->flags & EDGE_EH);
> e->flags = (e->flags & ~EDGE_EH) | EDGE_FALLTHRU;
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = bb->count;
>
> /* If there are no more EH users of the landing pad, delete it. */
> @@ -4283,7 +4281,7 @@ cleanup_empty_eh_move_lp (basic_block bb
>
> /* Clean up E_OUT for the fallthru. */
> e_out->flags = (e_out->flags & ~EDGE_EH) | EDGE_FALLTHRU;
> - e_out->probability = REG_BR_PROB_BASE;
> + e_out->probability = profile_probability::always ();
> e_out->count = e_out->src->count;
> }
>
> Index: tree-if-conv.c
> ===================================================================
> --- tree-if-conv.c (revision 249769)
> +++ tree-if-conv.c (working copy)
> @@ -2564,7 +2564,8 @@ version_loop_for_if_conversion (struct l
> /* At this point we invalidate porfile confistency until IFN_LOOP_VECTORIZED
> is re-merged in the vectorizer. */
> new_loop = loop_version (loop, cond, &cond_bb,
> - REG_BR_PROB_BASE, REG_BR_PROB_BASE,
> + profile_probability::always (),
> + profile_probability::always (),
> REG_BR_PROB_BASE, REG_BR_PROB_BASE, true);
> free_original_copy_tables ();
>
> Index: tree-inline.c
> ===================================================================
> --- tree-inline.c (revision 249769)
> +++ tree-inline.c (working copy)
> @@ -2291,10 +2291,44 @@ copy_edges_for_bb (basic_block bb, profi
> }
> }
>
> + bool update_probs = false;
> +
> if (gimple_code (copy_stmt) == GIMPLE_EH_DISPATCH)
> - make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
> + {
> + make_eh_dispatch_edges (as_a <geh_dispatch *> (copy_stmt));
> + update_probs = true;
> + }
> else if (can_throw)
> - make_eh_edges (copy_stmt);
> + {
> + make_eh_edges (copy_stmt);
> + update_probs = true;
> + }
> +
> + /* EH edges may not match old edges. Copy as much as possible. */
> + if (update_probs)
> + {
> + edge e;
> + edge_iterator ei;
> + basic_block copy_stmt_bb = gimple_bb (copy_stmt);
> +
> + FOR_EACH_EDGE (old_edge, ei, bb->succs)
> + if ((old_edge->flags & EDGE_EH)
> + && (e = find_edge (copy_stmt_bb,
> + (basic_block) old_edge->dest->aux))
> + && (e->flags & EDGE_EH))
> + {
> + e->probability = old_edge->probability;
> + e->count = old_edge->count;
> + }
> +
> + FOR_EACH_EDGE (e, ei, copy_stmt_bb->succs)
> + if ((e->flags & EDGE_EH) && !e->probability.initialized_p ())
> + {
> + e->probability = profile_probability::never ();
> + e->count = profile_count::zero ();
> + }
> + }
> +
>
> /* If the call we inline cannot make abnormal goto do not add
> additional abnormal edges but only retain those already present
> @@ -2317,7 +2351,8 @@ copy_edges_for_bb (basic_block bb, profi
> && gimple_call_arg (copy_stmt, 0) == boolean_true_node)
> nonlocal_goto = false;
> else
> - make_edge (copy_stmt_bb, abnormal_goto_dest, EDGE_ABNORMAL);
> + make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest,
> + EDGE_ABNORMAL);
> }
>
> if ((can_throw || nonlocal_goto)
> @@ -2789,7 +2824,7 @@ copy_cfg_body (copy_body_data * id, prof
> if (new_entry)
> {
> edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = incoming_count;
> }
>
> Index: tree-parloops.c
> ===================================================================
> --- tree-parloops.c (revision 249769)
> +++ tree-parloops.c (working copy)
> @@ -2115,10 +2115,12 @@ create_parallel_loop (struct loop *loop,
> gcc_assert (exit == single_dom_exit (loop));
>
> guard = make_edge (for_bb, ex_bb, 0);
> + /* FIXME: What is the probability? */
> + guard->probability = profile_probability::guessed_never ();
> /* Split the latch edge, so LOOPS_HAVE_SIMPLE_LATCHES is still valid. */
> loop->latch = split_edge (single_succ_edge (loop->latch));
> single_pred_edge (loop->latch)->flags = 0;
> - end = make_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
> + end = make_single_succ_edge (single_pred (loop->latch), ex_bb, EDGE_FALLTHRU);
> rescan_loop_exit (end, true, false);
>
> for (gphi_iterator gpi = gsi_start_phis (ex_bb);
> @@ -2358,7 +2360,9 @@ gen_parallel_loop (struct loop *loop,
> /* We assume that the loop usually iterates a lot. */
> prob = 4 * REG_BR_PROB_BASE / 5;
> loop_version (loop, many_iterations_cond, NULL,
> - prob, REG_BR_PROB_BASE - prob,
> + profile_probability::from_reg_br_prob_base (prob),
> + profile_probability::from_reg_br_prob_base
> + (REG_BR_PROB_BASE - prob),
> prob, REG_BR_PROB_BASE - prob, true);
> update_ssa (TODO_update_ssa);
> free_original_copy_tables ();
> @@ -3132,6 +3136,8 @@ oacc_entry_exit_single_gang (bitmap in_l
> gsi_insert_after (&gsi2, cond, GSI_NEW_STMT);
>
> edge e3 = make_edge (bb, bb3, EDGE_FALSE_VALUE);
> + /* FIXME: What is the probability? */
> + e3->probability = profile_probability::guessed_never ();
> e->flags = EDGE_TRUE_VALUE;
>
> tree vdef = gimple_vdef (stmt);
> Index: tree-profile.c
> ===================================================================
> --- tree-profile.c (revision 249769)
> +++ tree-profile.c (working copy)
> @@ -436,16 +436,16 @@ gimple_gen_ic_func_profiler (void)
> edge true_edge = single_succ_edge (cond_bb);
> true_edge->flags = EDGE_TRUE_VALUE;
>
> - int probability;
> + profile_probability probability;
> if (DECL_VIRTUAL_P (current_function_decl))
> - probability = PROB_VERY_LIKELY;
> + probability = profile_probability::very_likely ();
> else
> - probability = PROB_UNLIKELY;
> + probability = profile_probability::unlikely ();
>
> true_edge->probability = probability;
> edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest,
> EDGE_FALSE_VALUE);
> - e->probability = REG_BR_PROB_BASE - true_edge->probability;
> + e->probability = true_edge->probability.invert ();
>
> /* Insert code:
>
> @@ -497,10 +497,10 @@ gimple_gen_time_profiler (unsigned tag,
>
> edge true_edge = single_succ_edge (cond_bb);
> true_edge->flags = EDGE_TRUE_VALUE;
> - true_edge->probability = PROB_UNLIKELY;
> + true_edge->probability = profile_probability::unlikely ();
> edge e
> = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
> - e->probability = REG_BR_PROB_BASE - true_edge->probability;
> + e->probability = true_edge->probability.invert ();
>
> gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
> tree original_ref = tree_coverage_counter_ref (tag, base);
> Index: tree-ssa-dce.c
> ===================================================================
> --- tree-ssa-dce.c (revision 249769)
> +++ tree-ssa-dce.c (working copy)
> @@ -1054,7 +1054,7 @@ remove_dead_stmt (gimple_stmt_iterator *
> e = e2;
> }
> gcc_assert (e);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = bb->count;
>
> /* The edge is no longer associated with a conditional, so it does
> Index: tree-ssa-ifcombine.c
> ===================================================================
> --- tree-ssa-ifcombine.c (revision 249769)
> +++ tree-ssa-ifcombine.c (working copy)
> @@ -363,18 +363,14 @@ update_profile_after_ifcombine (basic_bl
> inner_taken->count += outer2->count;
> outer2->count = profile_count::zero ();
>
> - inner_taken->probability = outer2->probability
> - + RDIV (outer_to_inner->probability
> - * inner_taken->probability,
> - REG_BR_PROB_BASE);
> - if (inner_taken->probability > REG_BR_PROB_BASE)
> - inner_taken->probability = REG_BR_PROB_BASE;
> - inner_not_taken->probability = REG_BR_PROB_BASE
> + inner_taken->probability = outer2->probability + outer_to_inner->probability
> + * inner_taken->probability;
> + inner_not_taken->probability = profile_probability::always ()
> - inner_taken->probability;
>
> - outer_to_inner->probability = REG_BR_PROB_BASE;
> + outer_to_inner->probability = profile_probability::always ();
> inner_cond_bb->frequency = outer_cond_bb->frequency;
> - outer2->probability = 0;
> + outer2->probability = profile_probability::never ();
> }
>
> /* If-convert on a and pattern with a common else block. The inner
> Index: tree-ssa-loop-im.c
> ===================================================================
> --- tree-ssa-loop-im.c (revision 249769)
> +++ tree-ssa-loop-im.c (working copy)
> @@ -1801,7 +1801,7 @@ execute_sm_if_changed (edge ex, tree mem
> int freq_sum = 0;
> profile_count count_sum = profile_count::zero ();
> int nbbs = 0, ncount = 0;
> - int flag_probability = -1;
> + profile_probability flag_probability = profile_probability::uninitialized ();
>
> /* Flag is set in FLAG_BBS. Determine probability that flag will be true
> at loop exit.
> @@ -1824,27 +1824,29 @@ execute_sm_if_changed (edge ex, tree mem
> if ((*it)->count.initialized_p ())
> count_sum += (*it)->count, ncount ++;
> if (dominated_by_p (CDI_DOMINATORS, ex->src, *it))
> - flag_probability = REG_BR_PROB_BASE;
> + flag_probability = profile_probability::always ();
> nbbs++;
> }
>
> - if (flag_probability != -1)
> + profile_probability cap = profile_probability::always ().apply_scale (2, 3);
> +
> + if (flag_probability.initialized_p ())
> ;
> else if (ncount == nbbs && count_sum > 0 && preheader->count >= count_sum)
> {
> flag_probability = count_sum.probability_in (preheader->count);
> - if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
> - flag_probability = REG_BR_PROB_BASE * 2 / 3;
> + if (flag_probability > cap)
> + flag_probability = cap;
> }
> else if (freq_sum > 0 && EDGE_FREQUENCY (preheader) >= freq_sum)
> {
> - flag_probability = GCOV_COMPUTE_SCALE (freq_sum,
> - EDGE_FREQUENCY (preheader));
> - if (flag_probability > REG_BR_PROB_BASE * 2 / 3)
> - flag_probability = REG_BR_PROB_BASE * 2 / 3;
> + flag_probability = profile_probability::from_reg_br_prob_base
> + (GCOV_COMPUTE_SCALE (freq_sum, EDGE_FREQUENCY (preheader)));
> + if (flag_probability > cap)
> + flag_probability = cap;
> }
> else
> - flag_probability = REG_BR_PROB_BASE * 2 / 3;
> + flag_probability = cap;
>
> /* ?? Insert store after previous store if applicable. See note
> below. */
> @@ -1876,7 +1878,7 @@ execute_sm_if_changed (edge ex, tree mem
> old_dest = ex->dest;
> new_bb = split_edge (ex);
> then_bb = create_empty_bb (new_bb);
> - then_bb->frequency = apply_probability (new_bb->frequency, flag_probability);
> + then_bb->frequency = flag_probability.apply (new_bb->frequency);
> then_bb->count = new_bb->count.apply_probability (flag_probability);
> if (irr)
> then_bb->flags = BB_IRREDUCIBLE_LOOP;
> @@ -1901,13 +1903,11 @@ execute_sm_if_changed (edge ex, tree mem
> e1->flags |= EDGE_FALSE_VALUE | (irr ? EDGE_IRREDUCIBLE_LOOP : 0);
> e1->flags &= ~EDGE_FALLTHRU;
>
> - e1->probability = REG_BR_PROB_BASE - flag_probability;
> + e1->probability = flag_probability.invert ();
> e1->count = new_bb->count - then_bb->count;
>
> - then_old_edge = make_edge (then_bb, old_dest,
> + then_old_edge = make_single_succ_edge (then_bb, old_dest,
> EDGE_FALLTHRU | (irr ? EDGE_IRREDUCIBLE_LOOP : 0));
> - then_old_edge->probability = REG_BR_PROB_BASE;
> - then_old_edge->count = then_bb->count;
>
> set_immediate_dominator (CDI_DOMINATORS, then_bb, new_bb);
>
> Index: tree-ssa-loop-ivcanon.c
> ===================================================================
> --- tree-ssa-loop-ivcanon.c (revision 249769)
> +++ tree-ssa-loop-ivcanon.c (working copy)
> @@ -529,7 +529,7 @@ remove_exits_and_undefined_stmts (struct
> }
> if (!loop_exit_edge_p (loop, exit_edge))
> exit_edge = EDGE_SUCC (bb, 1);
> - exit_edge->probability = REG_BR_PROB_BASE;
> + exit_edge->probability = profile_probability::always ();
> exit_edge->count = exit_edge->src->count;
> gcc_checking_assert (loop_exit_edge_p (loop, exit_edge));
> gcond *cond_stmt = as_a <gcond *> (elt->stmt);
> @@ -642,7 +642,7 @@ unloop_loops (bitmap loop_closed_ssa_inv
> it in. */
> stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
> latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags);
> - latch_edge->probability = 0;
> + latch_edge->probability = profile_probability::never ();
> latch_edge->count = profile_count::zero ();
> latch_edge->flags |= flags;
> latch_edge->goto_locus = locus;
> @@ -1106,7 +1106,7 @@ try_peel_loop (struct loop *loop,
> }
> int scale = 1;
> if (loop->header->count > 0)
> - scale = entry_count.probability_in (loop->header->count);
> + scale = entry_count.probability_in (loop->header->count).to_reg_br_prob_base ();
> else if (loop->header->frequency)
> scale = RDIV (entry_freq * REG_BR_PROB_BASE, loop->header->frequency);
> scale_loop_profile (loop, scale, 0);
> Index: tree-ssa-loop-manip.c
> ===================================================================
> --- tree-ssa-loop-manip.c (revision 249769)
> +++ tree-ssa-loop-manip.c (working copy)
> @@ -1244,7 +1244,10 @@ tree_transform_and_unroll_loop (struct l
> scale_rest = REG_BR_PROB_BASE;
>
> new_loop = loop_version (loop, enter_main_cond, NULL,
> - prob_entry, REG_BR_PROB_BASE - prob_entry,
> + profile_probability::from_reg_br_prob_base
> + (prob_entry),
> + profile_probability::from_reg_br_prob_base
> + (REG_BR_PROB_BASE - prob_entry),
> scale_unrolled, scale_rest, true);
> gcc_assert (new_loop != NULL);
> update_ssa (TODO_update_ssa);
> @@ -1259,9 +1262,11 @@ tree_transform_and_unroll_loop (struct l
> /* Since the exit edge will be removed, the frequency of all the blocks
> in the loop that are dominated by it must be scaled by
> 1 / (1 - exit->probability). */
> - scale_dominated_blocks_in_loop (loop, exit->src,
> - REG_BR_PROB_BASE,
> - REG_BR_PROB_BASE - exit->probability);
> + if (exit->probability.initialized_p ())
> + scale_dominated_blocks_in_loop (loop, exit->src,
> + REG_BR_PROB_BASE,
> + REG_BR_PROB_BASE
> + - exit->probability.to_reg_br_prob_base ());
>
> bsi = gsi_last_bb (exit_bb);
> exit_if = gimple_build_cond (EQ_EXPR, integer_zero_node,
> @@ -1278,11 +1283,13 @@ tree_transform_and_unroll_loop (struct l
> new_exit->count = exit->count;
> new_exit->probability = exit->probability;
> new_nonexit = single_pred_edge (loop->latch);
> - new_nonexit->probability = REG_BR_PROB_BASE - exit->probability;
> + new_nonexit->probability = exit->probability.invert ();
> new_nonexit->flags = EDGE_TRUE_VALUE;
> new_nonexit->count -= exit->count;
> - scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
> - REG_BR_PROB_BASE);
> + if (new_nonexit->probability.initialized_p ())
> + scale_bbs_frequencies_int (&loop->latch, 1,
> + new_nonexit->probability.to_reg_br_prob_base (),
> + REG_BR_PROB_BASE);
>
> old_entry = loop_preheader_edge (loop);
> new_entry = loop_preheader_edge (new_loop);
> @@ -1368,24 +1375,29 @@ tree_transform_and_unroll_loop (struct l
> if (freq_e == profile_count::zero ())
> freq_e = profile_count::from_gcov_type (1);
> /* This should not overflow. */
> - scale = freq_e.probability_in (freq_h);
> + scale = freq_e.probability_in (freq_h).to_reg_br_prob_base ();
> scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
> }
>
> exit_bb = single_pred (loop->latch);
> new_exit = find_edge (exit_bb, rest);
> new_exit->count = loop_preheader_edge (loop)->count;
> - new_exit->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
> + new_exit->probability = profile_probability::always ()
> + .apply_scale (1, new_est_niter + 1);
>
> rest->count += new_exit->count;
> rest->frequency += EDGE_FREQUENCY (new_exit);
>
> new_nonexit = single_pred_edge (loop->latch);
> - prob = new_nonexit->probability;
> - new_nonexit->probability = REG_BR_PROB_BASE - new_exit->probability;
> + if (new_nonexit->probability.initialized_p ())
> + prob = new_nonexit->probability.to_reg_br_prob_base ();
> + else
> + prob = 0;
> + new_nonexit->probability = new_exit->probability.invert ();
> new_nonexit->count = exit_bb->count - new_exit->count;
> if (prob > 0)
> - scale_bbs_frequencies_int (&loop->latch, 1, new_nonexit->probability,
> + scale_bbs_frequencies_int (&loop->latch, 1,
> + new_nonexit->probability.to_reg_br_prob_base (),
> prob);
>
> /* Finally create the new counter for number of iterations and add the new
> Index: tree-ssa-loop-split.c
> ===================================================================
> --- tree-ssa-loop-split.c (revision 249769)
> +++ tree-ssa-loop-split.c (working copy)
> @@ -354,10 +354,10 @@ connect_loops (struct loop *loop1, struc
> }
>
> new_e->count = skip_bb->count;
> - new_e->probability = PROB_LIKELY;
> + new_e->probability = profile_probability::likely ();
> new_e->count = skip_e->count.apply_probability (PROB_LIKELY);
> skip_e->count -= new_e->count;
> - skip_e->probability = inverse_probability (PROB_LIKELY);
> + skip_e->probability = profile_probability::unlikely ();
>
> return new_e;
> }
> @@ -559,8 +559,11 @@ split_loop (struct loop *loop1, struct t
> them, and fix up SSA form for that. */
> initialize_original_copy_tables ();
> basic_block cond_bb;
> +
> + /* FIXME: probabilities seems wrong here. */
> struct loop *loop2 = loop_version (loop1, cond, &cond_bb,
> - REG_BR_PROB_BASE, REG_BR_PROB_BASE,
> + profile_probability::always (),
> + profile_probability::always (),
> REG_BR_PROB_BASE, REG_BR_PROB_BASE,
> true);
> gcc_assert (loop2);
> Index: tree-ssa-loop-unswitch.c
> ===================================================================
> --- tree-ssa-loop-unswitch.c (revision 249769)
> +++ tree-ssa-loop-unswitch.c (working copy)
> @@ -480,7 +480,7 @@ static struct loop *
> tree_unswitch_loop (struct loop *loop,
> basic_block unswitch_on, tree cond)
> {
> - unsigned prob_true;
> + profile_probability prob_true;
> edge edge_true, edge_false;
>
> /* Some sanity checking. */
> @@ -490,9 +490,13 @@ tree_unswitch_loop (struct loop *loop,
>
> extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
> prob_true = edge_true->probability;
> + int p = prob_true.initialized_p () ? prob_true.to_reg_br_prob_base ()
> + : REG_BR_PROB_BASE / 2;
> return loop_version (loop, unshare_expr (cond),
> - NULL, prob_true, REG_BR_PROB_BASE - prob_true, prob_true,
> - REG_BR_PROB_BASE - prob_true, false);
> + NULL, prob_true,
> + prob_true.invert (),
> + p, REG_BR_PROB_BASE - p,
> + false);
> }
>
> /* Unswitch outer loops by hoisting invariant guard on
> @@ -818,10 +822,13 @@ hoist_guard (struct loop *loop, edge gua
> /* Create new loop pre-header. */
> e = split_block (pre_header, last_stmt (pre_header));
> if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " Moving guard %i->%i (prob %i) to bb %i, "
> - "new preheader is %i\n",
> - guard->src->index, guard->dest->index, guard->probability,
> - e->src->index, e->dest->index);
> + {
> + fprintf (dump_file, " Moving guard %i->%i (prob ",
> + guard->src->index, guard->dest->index);
> + guard->probability.dump (dump_file);
> + fprintf (dump_file, ") to bb %i, new preheader is %i\n",
> + e->src->index, e->dest->index);
> + }
>
> gcc_assert (loop_preheader_edge (loop)->src == e->dest);
>
> @@ -854,23 +861,26 @@ hoist_guard (struct loop *loop, edge gua
> }
> new_edge->count = skip_count;
> if (dump_file && (dump_flags & TDF_DETAILS))
> - fprintf (dump_file, " Estimated probability of skipping loop is %i\n",
> - new_edge->probability);
> + {
> + fprintf (dump_file, " Estimated probability of skipping loop is ");
> + new_edge->probability.dump (dump_file);
> + fprintf (dump_file, "\n");
> + }
>
> /* Update profile after the transform:
>
> First decrease count of path from newly hoisted loop guard
> to loop header... */
> e->count -= skip_count;
> - e->probability = REG_BR_PROB_BASE - new_edge->probability;
> + e->probability = new_edge->probability.invert ();
> e->dest->count = e->count;
> e->dest->frequency = EDGE_FREQUENCY (e);
>
> /* ... now update profile to represent that original guard will be optimized
> away ... */
> - guard->probability = 0;
> + guard->probability = profile_probability::never ();
> guard->count = profile_count::zero ();
> - not_guard->probability = REG_BR_PROB_BASE;
> + not_guard->probability = profile_probability::always ();
> /* This count is wrong (frequency of not_guard does not change),
> but will be scaled later. */
> not_guard->count = guard->src->count;
> @@ -888,7 +898,10 @@ hoist_guard (struct loop *loop, edge gua
> {
> if (dump_file && (dump_flags & TDF_DETAILS))
> fprintf (dump_file, " %i", bb->index);
> - scale_bbs_frequencies_int (&bb, 1, e->probability, REG_BR_PROB_BASE);
> + if (e->probability.initialized_p ())
> + scale_bbs_frequencies_int (&bb, 1,
> + e->probability.to_reg_br_prob_base (),
> + REG_BR_PROB_BASE);
> }
> }
>
> Index: tree-ssa-phionlycprop.c
> ===================================================================
> --- tree-ssa-phionlycprop.c (revision 249769)
> +++ tree-ssa-phionlycprop.c (working copy)
> @@ -313,8 +313,6 @@ propagate_rhs_into_lhs (gimple *stmt, tr
> te->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
> te->flags &= ~EDGE_ABNORMAL;
> te->flags |= EDGE_FALLTHRU;
> - if (te->probability > REG_BR_PROB_BASE)
> - te->probability = REG_BR_PROB_BASE;
> }
> }
> }
> Index: tree-ssa-phiopt.c
> ===================================================================
> --- tree-ssa-phiopt.c (revision 249769)
> +++ tree-ssa-phiopt.c (working copy)
> @@ -374,7 +374,7 @@ replace_phi_edge_with_variable (basic_bl
> {
> EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
> EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
> - EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
> + EDGE_SUCC (cond_block, 0)->probability = profile_probability::always ();
> EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
>
> block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
> @@ -384,7 +384,7 @@ replace_phi_edge_with_variable (basic_bl
> EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
> EDGE_SUCC (cond_block, 1)->flags
> &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
> - EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
> + EDGE_SUCC (cond_block, 1)->probability = profile_probability::always ();
> EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
>
> block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
> @@ -1017,7 +1017,7 @@ value_replacement (basic_block cond_bb,
> if (optimize_bb_for_speed_p (cond_bb)
> /* The special case is useless if it has a low probability. */
> && profile_status_for_fn (cfun) != PROFILE_ABSENT
> - && EDGE_PRED (middle_bb, 0)->probability < PROB_EVEN
> + && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
> /* If assign is cheap, there is no point avoiding it. */
> && estimate_num_insns (assign, &eni_time_weights)
> >= 3 * estimate_num_insns (cond, &eni_time_weights))
> Index: tree-ssa-reassoc.c
> ===================================================================
> --- tree-ssa-reassoc.c (revision 249769)
> +++ tree-ssa-reassoc.c (working copy)
> @@ -5843,7 +5843,7 @@ branch_fixup (void)
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>
> edge etrue = make_edge (cond_bb, merge_bb, EDGE_TRUE_VALUE);
> - etrue->probability = REG_BR_PROB_BASE / 2;
> + etrue->probability = profile_probability::even ();
> etrue->count = cond_bb->count.apply_scale (1, 2);
> edge efalse = find_edge (cond_bb, then_bb);
> efalse->flags = EDGE_FALSE_VALUE;
> Index: tree-ssa-tail-merge.c
> ===================================================================
> --- tree-ssa-tail-merge.c (revision 249769)
> +++ tree-ssa-tail-merge.c (working copy)
> @@ -1592,9 +1592,10 @@ replace_block_by (basic_block bb1, basic
> else if (bb2->frequency && !bb1->frequency)
> ;
> else if (out_freq_sum)
> - e2->probability = GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
> - + EDGE_FREQUENCY (e2),
> - out_freq_sum);
> + e2->probability = profile_probability::from_reg_br_prob_base
> + (GCOV_COMPUTE_SCALE (EDGE_FREQUENCY (e1)
> + + EDGE_FREQUENCY (e2),
> + out_freq_sum));
> out_sum += e2->count;
> }
> bb2->frequency += bb1->frequency;
> Index: tree-ssa-threadupdate.c
> ===================================================================
> --- tree-ssa-threadupdate.c (revision 249769)
> +++ tree-ssa-threadupdate.c (working copy)
> @@ -302,7 +302,7 @@ remove_ctrl_stmt_and_useless_edges (basi
> }
> else
> {
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = bb->count;
> ei_next (&ei);
> }
> @@ -546,11 +546,9 @@ static void
> create_edge_and_update_destination_phis (struct redirection_data *rd,
> basic_block bb, int idx)
> {
> - edge e = make_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
> + edge e = make_single_succ_edge (bb, rd->path->last ()->e->dest, EDGE_FALLTHRU);
>
> rescan_loop_exit (e, true, false);
> - e->probability = REG_BR_PROB_BASE;
> - e->count = bb->count;
>
> /* We used to copy the thread path here. That was added in 2007
> and dutifully updated through the representation changes in 2013.
> @@ -765,7 +763,8 @@ compute_path_counts (struct redirection_
> /* Handle incoming profile insanities. */
> if (total_count < path_in_count)
> path_in_count = total_count;
> - int onpath_scale = path_in_count.probability_in (total_count);
> + int onpath_scale
> + = path_in_count.probability_in (total_count).to_reg_br_prob_base ();
>
> /* Walk the entire path to do some more computation in order to estimate
> how much of the path_in_count will flow out of the duplicated threading
> @@ -919,7 +918,7 @@ recompute_probabilities (basic_block bb)
> get a flow verification error.
> Not much we can do to make counts/freqs sane without
> redoing the profile estimation. */
> - esucc->probability = REG_BR_PROB_BASE;
> + esucc->probability = profile_probability::guessed_always ();
> }
> }
>
> @@ -978,7 +977,8 @@ update_joiner_offpath_counts (edge epath
> among the duplicated off-path edges based on their original
> ratio to the full off-path count (total_orig_off_path_count).
> */
> - int scale = enonpath->count.probability_in (total_orig_off_path_count);
> + int scale = enonpath->count.probability_in (total_orig_off_path_count)
> + .to_reg_br_prob_base ();
> /* Give the duplicated offpath edge a portion of the duplicated
> total. */
> enonpathdup->count = total_dup_off_path_count.apply_probability (scale);
> @@ -1048,9 +1048,13 @@ freqs_to_counts_path (struct redirection
> /* Scale up the frequency by REG_BR_PROB_BASE, to avoid rounding
> errors applying the probability when the frequencies are very
> small. */
> - ein->count = profile_count::from_gcov_type
> - (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
> - ein->probability));
> + if (ein->probability.initialized_p ())
> + ein->count = profile_count::from_gcov_type
> + (apply_probability (ein->src->frequency * REG_BR_PROB_BASE,
> + ein->probability.to_reg_br_prob_base ()));
> + else
> + /* FIXME: this is hack; we should track uninitialized values. */
> + ein->count = profile_count::zero ();
> }
>
> for (unsigned int i = 1; i < path->length (); i++)
> @@ -2358,7 +2362,7 @@ duplicate_thread_path (edge entry, edge
> if (e)
> {
> rescan_loop_exit (e, true, false);
> - e->probability = REG_BR_PROB_BASE;
> + e->probability = profile_probability::always ();
> e->count = region_copy[n_region - 1]->count;
> }
>
> Index: tree-switch-conversion.c
> ===================================================================
> --- tree-switch-conversion.c (revision 249769)
> +++ tree-switch-conversion.c (working copy)
> @@ -103,7 +103,7 @@ hoist_edge_and_branch_if_true (gimple_st
>
> e_false->flags &= ~EDGE_FALLTHRU;
> e_false->flags |= EDGE_FALSE_VALUE;
> - e_false->probability = REG_BR_PROB_BASE - e_true->probability;
> + e_false->probability = e_true->probability.invert ();
> e_false->count = split_bb->count - e_true->count;
> new_bb->count = e_false->count;
>
> @@ -556,7 +556,7 @@ struct switch_conv_info
> basic_block final_bb;
>
> /* The probability of the default edge in the replaced switch. */
> - int default_prob;
> + profile_probability default_prob;
>
> /* The count of the default edge in the replaced switch. */
> profile_count default_count;
> @@ -1422,7 +1422,7 @@ gen_inbound_check (gswitch *swtch, struc
> /* flags and profiles of the edge for in-range values */
> if (!info->default_case_nonstandard)
> e01 = make_edge (bb0, bb1, EDGE_TRUE_VALUE);
> - e01->probability = REG_BR_PROB_BASE - info->default_prob;
> + e01->probability = info->default_prob.invert ();
> e01->count = info->other_count;
>
> /* flags and profiles of the edge taking care of out-of-range values */
> @@ -1434,7 +1434,7 @@ gen_inbound_check (gswitch *swtch, struc
> bbf = info->final_bb;
>
> e1f = make_edge (bb1, bbf, EDGE_FALLTHRU);
> - e1f->probability = REG_BR_PROB_BASE;
> + e1f->probability = profile_probability::always ();
> e1f->count = info->other_count;
>
> if (info->default_case_nonstandard)
> @@ -1442,7 +1442,7 @@ gen_inbound_check (gswitch *swtch, struc
> else
> {
> e2f = make_edge (bb2, bbf, EDGE_FALLTHRU);
> - e2f->probability = REG_BR_PROB_BASE;
> + e2f->probability = profile_probability::always ();
> e2f->count = info->default_count;
> }
>
> Index: tree-vect-loop-manip.c
> ===================================================================
> --- tree-vect-loop-manip.c (revision 249769)
> +++ tree-vect-loop-manip.c (working copy)
> @@ -540,7 +540,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (
> static edge
> slpeel_add_loop_guard (basic_block guard_bb, tree cond,
> basic_block guard_to, basic_block dom_bb,
> - int probability, bool irreducible_p)
> + profile_probability probability, bool irreducible_p)
> {
> gimple_stmt_iterator gsi;
> edge new_e, enter_e;
> @@ -571,7 +571,7 @@ slpeel_add_loop_guard (basic_block guard
> new_e->flags |= EDGE_IRREDUCIBLE_LOOP;
>
> enter_e->count -= new_e->count;
> - enter_e->probability = inverse_probability (probability);
> + enter_e->probability = probability.invert ();
> set_immediate_dominator (CDI_DOMINATORS, guard_to, dom_bb);
>
> /* Split enter_e to preserve LOOPS_HAVE_PREHEADERS. */
> @@ -1660,7 +1660,7 @@ vect_do_peeling (loop_vec_info loop_vinf
> edge e, guard_e;
> tree type = TREE_TYPE (niters), guard_cond;
> basic_block guard_bb, guard_to;
> - int prob_prolog, prob_vector, prob_epilog;
> + profile_probability prob_prolog, prob_vector, prob_epilog;
> int bound_prolog = 0, bound_scalar = 0, bound = 0;
> int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
> int prolog_peeling = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo);
> @@ -1670,10 +1670,11 @@ vect_do_peeling (loop_vec_info loop_vinf
> if (!prolog_peeling && !epilog_peeling)
> return NULL;
>
> - prob_vector = 9 * REG_BR_PROB_BASE / 10;
> + prob_vector = profile_probability::guessed_always ().apply_scale (9, 10);
> if ((vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo)) == 2)
> vf = 3;
> - prob_prolog = prob_epilog = (vf - 1) * REG_BR_PROB_BASE / vf;
> + prob_prolog = prob_epilog = profile_probability::guessed_always ()
> + .apply_scale (vf - 1, vf);
> vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
>
> struct loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo);
> @@ -1718,9 +1719,11 @@ vect_do_peeling (loop_vec_info loop_vinf
> separately. Note in this case, the probability of epilog loop
> needs to be scaled back later. */
> basic_block bb_before_loop = loop_preheader_edge (loop)->src;
> - scale_bbs_frequencies_int (&bb_before_loop, 1, prob_vector,
> + if (prob_vector.initialized_p ())
> + scale_bbs_frequencies_int (&bb_before_loop, 1,
> + prob_vector.to_reg_br_prob_base (),
> REG_BR_PROB_BASE);
> - scale_loop_profile (loop, prob_vector, bound);
> + scale_loop_profile (loop, prob_vector.to_reg_br_prob_base (), bound);
> }
>
> tree niters_prolog = build_int_cst (type, 0);
> @@ -1762,15 +1765,17 @@ vect_do_peeling (loop_vec_info loop_vinf
> guard_to = split_edge (loop_preheader_edge (loop));
> guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
> guard_to, guard_bb,
> - inverse_probability (prob_prolog),
> + prob_prolog.invert (),
> irred_flag);
> e = EDGE_PRED (guard_to, 0);
> e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
> slpeel_update_phi_nodes_for_guard1 (prolog, loop, guard_e, e);
>
> - scale_bbs_frequencies_int (&bb_after_prolog, 1, prob_prolog,
> + scale_bbs_frequencies_int (&bb_after_prolog, 1,
> + prob_prolog.to_reg_br_prob_base (),
> REG_BR_PROB_BASE);
> - scale_loop_profile (prolog, prob_prolog, bound_prolog);
> + scale_loop_profile (prolog, prob_prolog.to_reg_br_prob_base (),
> + bound_prolog);
> }
> /* Update init address of DRs. */
> vect_update_inits_of_drs (loop_vinfo, niters_prolog);
> @@ -1834,7 +1839,7 @@ vect_do_peeling (loop_vec_info loop_vinf
> guard_to = split_edge (loop_preheader_edge (epilog));
> guard_e = slpeel_add_loop_guard (guard_bb, guard_cond,
> guard_to, guard_bb,
> - inverse_probability (prob_vector),
> + prob_vector.invert (),
> irred_flag);
> e = EDGE_PRED (guard_to, 0);
> e = (e != guard_e ? e : EDGE_PRED (guard_to, 1));
> @@ -1846,7 +1851,8 @@ vect_do_peeling (loop_vec_info loop_vinf
> guard_to->count = guard_bb->count;
> single_succ_edge (guard_to)->count = guard_to->count;
> /* Scale probability of epilog loop back. */
> - int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE / prob_vector;
> + int scale_up = REG_BR_PROB_BASE * REG_BR_PROB_BASE
> + / prob_vector.to_reg_br_prob_base ();
> scale_loop_frequencies (epilog, scale_up, REG_BR_PROB_BASE);
> }
>
> @@ -1875,7 +1881,7 @@ vect_do_peeling (loop_vec_info loop_vinf
> guard_to = split_edge (single_exit (epilog));
> guard_e = slpeel_add_loop_guard (guard_bb, guard_cond, guard_to,
> skip_vector ? anchor : guard_bb,
> - inverse_probability (prob_epilog),
> + prob_epilog.invert (),
> irred_flag);
> slpeel_update_phi_nodes_for_guard2 (loop, epilog, guard_e,
> single_exit (epilog));
> @@ -1883,13 +1889,13 @@ vect_do_peeling (loop_vec_info loop_vinf
> the guard_bb, which is the case when skip_vector is true. */
> if (guard_bb != bb_before_epilog)
> {
> - prob_epilog = (combine_probabilities (prob_vector, prob_epilog)
> - + inverse_probability (prob_vector));
> + prob_epilog = prob_vector * prob_epilog + prob_vector.invert ();
>
> - scale_bbs_frequencies_int (&bb_before_epilog, 1, prob_epilog,
> + scale_bbs_frequencies_int (&bb_before_epilog, 1,
> + prob_epilog.to_reg_br_prob_base (),
> REG_BR_PROB_BASE);
> }
> - scale_loop_profile (epilog, prob_epilog, bound);
> + scale_loop_profile (epilog, prob_epilog.to_reg_br_prob_base (), bound);
> }
> else
> slpeel_update_phi_nodes_for_lcssa (epilog);
> @@ -2171,7 +2177,10 @@ vect_loop_versioning (loop_vec_info loop
> /* We don't want to scale SCALAR_LOOP's frequencies, we need to
> scale LOOP's frequencies instead. */
> nloop = loop_version (scalar_loop, cond_expr, &condition_bb,
> - prob, REG_BR_PROB_BASE - prob,
> + profile_probability::guessed_always ().apply_scale
> + (prob, REG_BR_PROB_BASE),
> + profile_probability::guessed_always ().apply_scale
> + (REG_BR_PROB_BASE - prob, REG_BR_PROB_BASE),
> REG_BR_PROB_BASE, REG_BR_PROB_BASE - prob, true);
> scale_loop_frequencies (loop, prob, REG_BR_PROB_BASE);
> /* CONDITION_BB was created above SCALAR_LOOP's preheader,
> @@ -2200,7 +2209,10 @@ vect_loop_versioning (loop_vec_info loop
> }
> else
> nloop = loop_version (loop, cond_expr, &condition_bb,
> - prob, REG_BR_PROB_BASE - prob,
> + profile_probability::guessed_always ().apply_scale
> + (prob, REG_BR_PROB_BASE),
> + profile_probability::guessed_always ().apply_scale
> + (REG_BR_PROB_BASE - prob, REG_BR_PROB_BASE),
> prob, REG_BR_PROB_BASE - prob, true);
>
> if (version_niter)
> Index: tree-vect-loop.c
> ===================================================================
> --- tree-vect-loop.c (revision 249769)
> +++ tree-vect-loop.c (working copy)
> @@ -7121,21 +7121,25 @@ scale_profile_for_vect_loop (struct loop
> if (!(freq_e > profile_count::from_gcov_type (1)))
> freq_e = profile_count::from_gcov_type (1);
> /* This should not overflow. */
> - scale = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h);
> + scale = freq_e.apply_scale (new_est_niter + 1, 1).probability_in (freq_h)
> + .to_reg_br_prob_base ();
> scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
> }
>
> basic_block exit_bb = single_pred (loop->latch);
> edge exit_e = single_exit (loop);
> exit_e->count = loop_preheader_edge (loop)->count;
> - exit_e->probability = REG_BR_PROB_BASE / (new_est_niter + 1);
> + exit_e->probability = profile_probability::always ()
> + .apply_scale (1, new_est_niter + 1);
>
> edge exit_l = single_pred_edge (loop->latch);
> - int prob = exit_l->probability;
> - exit_l->probability = REG_BR_PROB_BASE - exit_e->probability;
> + int prob = exit_l->probability.initialized_p ()
> + ? exit_l->probability.to_reg_br_prob_base () : 0;
> + exit_l->probability = exit_e->probability.invert ();
> exit_l->count = exit_bb->count - exit_e->count;
> if (prob > 0)
> - scale_bbs_frequencies_int (&loop->latch, 1, exit_l->probability, prob);
> + scale_bbs_frequencies_int (&loop->latch, 1,
> + exit_l->probability.to_reg_br_prob_base (), prob);
> }
>
> /* Function vect_transform_loop.
> @@ -7658,7 +7662,7 @@ optimize_mask_stores (struct loop *loop)
> e->flags = EDGE_TRUE_VALUE;
> efalse = make_edge (bb, store_bb, EDGE_FALSE_VALUE);
> /* Put STORE_BB to likely part. */
> - efalse->probability = PROB_UNLIKELY;
> + efalse->probability = profile_probability::unlikely ();
> store_bb->frequency = PROB_ALWAYS - EDGE_FREQUENCY (efalse);
> make_edge (store_bb, join_bb, EDGE_FALLTHRU);
> if (dom_info_available_p (CDI_DOMINATORS))
> Index: ubsan.c
> ===================================================================
> --- ubsan.c (revision 249769)
> +++ ubsan.c (working copy)
> @@ -799,7 +799,7 @@ ubsan_expand_null_ifn (gimple_stmt_itera
> /* Make an edge coming from the 'cond block' into the 'then block';
> this edge is unlikely taken, so set up the probability accordingly. */
> e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
> - e->probability = PROB_VERY_UNLIKELY;
> + e->probability = profile_probability::very_unlikely ();
>
> /* Connect 'then block' with the 'else block'. This is needed
> as the ubsan routines we call in the 'then block' are not noreturn.
> @@ -810,7 +810,7 @@ ubsan_expand_null_ifn (gimple_stmt_itera
> e = find_edge (cond_bb, fallthru_bb);
> e->flags = EDGE_FALSE_VALUE;
> e->count = cond_bb->count;
> - e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
> + e->probability = profile_probability::very_likely ();
>
> /* Update dominance info for the newly created then_bb; note that
> fallthru_bb's dominance info has already been updated by
> @@ -873,13 +873,13 @@ ubsan_expand_null_ifn (gimple_stmt_itera
> this edge is unlikely taken, so set up the probability
> accordingly. */
> e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
> - e->probability = PROB_VERY_UNLIKELY;
> + e->probability = profile_probability::very_unlikely ();
>
> /* Set up the fallthrough basic block. */
> e = find_edge (cond1_bb, cond2_bb);
> e->flags = EDGE_FALSE_VALUE;
> e->count = cond1_bb->count;
> - e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
> + e->probability = profile_probability::very_likely ();
>
> /* Update dominance info. */
> if (dom_info_available_p (CDI_DOMINATORS))
> Index: value-prof.c
> ===================================================================
> --- value-prof.c (revision 249769)
> +++ value-prof.c (working copy)
> @@ -104,11 +104,6 @@ along with GCC; see the file COPYING3.
> and gimple_value_profile_transformations table-driven, perhaps...
> */
>
> -static tree gimple_divmod_fixed_value (gassign *, tree, int, gcov_type,
> - gcov_type);
> -static tree gimple_mod_pow2 (gassign *, int, gcov_type, gcov_type);
> -static tree gimple_mod_subtract (gassign *, int, int, int, gcov_type,
> - gcov_type, gcov_type);
> static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
> static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
> static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
> @@ -693,7 +688,7 @@ gimple_value_profile_transformations (vo
> alter the original STMT. */
>
> static tree
> -gimple_divmod_fixed_value (gassign *stmt, tree value, int prob,
> +gimple_divmod_fixed_value (gassign *stmt, tree value, profile_probability prob,
> gcov_type count, gcov_type all)
> {
> gassign *stmt1, *stmt2;
> @@ -753,16 +748,16 @@ gimple_divmod_fixed_value (gassign *stmt
> e12->count = profile_count::from_gcov_type (count);
>
> e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
> - e13->probability = REG_BR_PROB_BASE - prob;
> + e13->probability = prob.invert ();
> e13->count = profile_count::from_gcov_type (all - count);
>
> remove_edge (e23);
>
> e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
> - e24->probability = REG_BR_PROB_BASE;
> + e24->probability = profile_probability::always ();
> e24->count = profile_count::from_gcov_type (count);
>
> - e34->probability = REG_BR_PROB_BASE;
> + e34->probability = profile_probability::always ();
> e34->count = profile_count::from_gcov_type (all - count);
>
> return tmp2;
> @@ -777,7 +772,7 @@ gimple_divmod_fixed_value_transform (gim
> enum tree_code code;
> gcov_type val, count, all;
> tree result, value, tree_val;
> - gcov_type prob;
> + profile_probability prob;
> gassign *stmt;
>
> stmt = dyn_cast <gassign *> (gsi_stmt (*si));
> @@ -816,9 +811,9 @@ gimple_divmod_fixed_value_transform (gim
>
> /* Compute probability of taking the optimal path. */
> if (all > 0)
> - prob = GCOV_COMPUTE_SCALE (count, all);
> + prob = profile_probability::probability_in_gcov_type (count, all);
> else
> - prob = 0;
> + prob = profile_probability::never ();
>
> if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT))
> tree_val = build_int_cst (get_gcov_type (), val);
> @@ -855,7 +850,7 @@ gimple_divmod_fixed_value_transform (gim
> the temp; it does not replace or alter the original STMT. */
>
> static tree
> -gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all)
> +gimple_mod_pow2 (gassign *stmt, profile_probability prob, gcov_type count, gcov_type all)
> {
> gassign *stmt1, *stmt2, *stmt3;
> gcond *stmt4;
> @@ -918,16 +913,16 @@ gimple_mod_pow2 (gassign *stmt, int prob
> e12->count = profile_count::from_gcov_type (count);
>
> e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
> - e13->probability = REG_BR_PROB_BASE - prob;
> + e13->probability = prob.invert ();
> e13->count = profile_count::from_gcov_type (all - count);
>
> remove_edge (e23);
>
> e24 = make_edge (bb2, bb4, EDGE_FALLTHRU);
> - e24->probability = REG_BR_PROB_BASE;
> + e24->probability = profile_probability::always ();
> e24->count = profile_count::from_gcov_type (count);
>
> - e34->probability = REG_BR_PROB_BASE;
> + e34->probability = profile_probability::always ();
> e34->count = profile_count::from_gcov_type (all - count);
>
> return result;
> @@ -942,7 +937,7 @@ gimple_mod_pow2_value_transform (gimple_
> enum tree_code code;
> gcov_type count, wrong_values, all;
> tree lhs_type, result, value;
> - gcov_type prob;
> + profile_probability prob;
> gassign *stmt;
>
> stmt = dyn_cast <gassign *> (gsi_stmt (*si));
> @@ -987,9 +982,9 @@ gimple_mod_pow2_value_transform (gimple_
> return false;
>
> if (all > 0)
> - prob = GCOV_COMPUTE_SCALE (count, all);
> + prob = profile_probability::probability_in_gcov_type (count, all);
> else
> - prob = 0;
> + prob = profile_probability::never ();
>
> result = gimple_mod_pow2 (stmt, prob, count, all);
>
> @@ -1009,7 +1004,8 @@ gimple_mod_pow2_value_transform (gimple_
> /* FIXME: Generalize the interface to handle NCOUNTS > 1. */
>
> static tree
> -gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts,
> +gimple_mod_subtract (gassign *stmt, profile_probability prob1,
> + profile_probability prob2, int ncounts,
> gcov_type count1, gcov_type count2, gcov_type all)
> {
> gassign *stmt1;
> @@ -1079,7 +1075,7 @@ gimple_mod_subtract (gassign *stmt, int
>
> e12->flags &= ~EDGE_FALLTHRU;
> e12->flags |= EDGE_FALSE_VALUE;
> - e12->probability = REG_BR_PROB_BASE - prob1;
> + e12->probability = prob1.invert ();
> e12->count = profile_count::from_gcov_type (all - count1);
>
> e14 = make_edge (bb, bb4, EDGE_TRUE_VALUE);
> @@ -1091,14 +1087,14 @@ gimple_mod_subtract (gassign *stmt, int
> e23->flags &= ~EDGE_FALLTHRU;
> e23->flags |= EDGE_FALSE_VALUE;
> e23->count = profile_count::from_gcov_type (all - count1 - count2);
> - e23->probability = REG_BR_PROB_BASE - prob2;
> + e23->probability = prob2.invert ();
>
> e24 = make_edge (bb2, bb4, EDGE_TRUE_VALUE);
> e24->probability = prob2;
> e24->count = profile_count::from_gcov_type (count2);
> }
>
> - e34->probability = REG_BR_PROB_BASE;
> + e34->probability = profile_probability::always ();
> e34->count = profile_count::from_gcov_type (all - count1 - count2);
>
> return result;
> @@ -1113,7 +1109,7 @@ gimple_mod_subtract_transform (gimple_st
> enum tree_code code;
> gcov_type count, wrong_values, all;
> tree lhs_type, result;
> - gcov_type prob1, prob2;
> + profile_probability prob1, prob2;
> unsigned int i, steps;
> gcov_type count1, count2;
> gassign *stmt;
> @@ -1181,12 +1177,12 @@ gimple_mod_subtract_transform (gimple_st
> /* Compute probability of taking the optimal path(s). */
> if (all > 0)
> {
> - prob1 = GCOV_COMPUTE_SCALE (count1, all);
> - prob2 = GCOV_COMPUTE_SCALE (count2, all);
> + prob1 = profile_probability::probability_in_gcov_type (count1, all);
> + prob2 = profile_probability::probability_in_gcov_type (count2, all);
> }
> else
> {
> - prob1 = prob2 = 0;
> + prob1 = prob2 = profile_probability::never ();
> }
>
> /* In practice, "steps" is always 2. This interface reflects this,
> @@ -1316,7 +1312,7 @@ check_ic_target (gcall *call_stmt, struc
>
> gcall *
> gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
> - int prob, profile_count count, profile_count all)
> + profile_probability prob, profile_count count, profile_count all)
> {
> gcall *dcall_stmt;
> gassign *load_stmt;
> @@ -1386,7 +1382,7 @@ gimple_ic (gcall *icall_stmt, struct cgr
> /* The indirect call might be noreturn. */
> if (e_ij != NULL)
> {
> - e_ij->probability = REG_BR_PROB_BASE;
> + e_ij->probability = profile_probability::always ();
> e_ij->count = all - count;
> e_ij = single_pred_edge (split_edge (e_ij));
> }
> @@ -1402,7 +1398,7 @@ gimple_ic (gcall *icall_stmt, struct cgr
> e_cd->count = count;
>
> e_ci = make_edge (cond_bb, icall_bb, EDGE_FALSE_VALUE);
> - e_ci->probability = REG_BR_PROB_BASE - prob;
> + e_ci->probability = prob.invert ();
> e_ci->count = all - count;
>
> remove_edge (e_di);
> @@ -1414,12 +1410,12 @@ gimple_ic (gcall *icall_stmt, struct cgr
> else
> {
> e_dj = make_edge (dcall_bb, join_bb, EDGE_FALLTHRU);
> - e_dj->probability = REG_BR_PROB_BASE;
> + e_dj->probability = profile_probability::always ();
> e_dj->count = count;
>
> e_ij->count = all - count;
> }
> - e_ij->probability = REG_BR_PROB_BASE;
> + e_ij->probability = profile_probability::always ();
> }
>
> /* Insert PHI node for the call result if necessary. */
> @@ -1497,6 +1493,8 @@ gimple_ic (gcall *icall_stmt, struct cgr
> if (e_eh->flags & (EDGE_EH | EDGE_ABNORMAL))
> {
> e = make_edge (dcall_bb, e_eh->dest, e_eh->flags);
> + e->probability = e_eh->probability;
> + e->count = e_eh->count;
> for (gphi_iterator psi = gsi_start_phis (e_eh->dest);
> !gsi_end_p (psi); gsi_next (&psi))
> {
> @@ -1645,7 +1643,7 @@ interesting_stringop_to_profile_p (gcall
> assuming we'll propagate a true constant into ICALL_SIZE later. */
>
> static void
> -gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob,
> +gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, profile_probability prob,
> gcov_type count, gcov_type all)
> {
> gassign *tmp_stmt;
> @@ -1709,16 +1707,16 @@ gimple_stringop_fixed_value (gcall *vcal
> e_ci->count = profile_count::from_gcov_type (count);
>
> e_cv = make_edge (cond_bb, vcall_bb, EDGE_FALSE_VALUE);
> - e_cv->probability = REG_BR_PROB_BASE - prob;
> + e_cv->probability = prob.invert ();
> e_cv->count = profile_count::from_gcov_type (all - count);
>
> remove_edge (e_iv);
>
> e_ij = make_edge (icall_bb, join_bb, EDGE_FALLTHRU);
> - e_ij->probability = REG_BR_PROB_BASE;
> + e_ij->probability = profile_probability::always ();
> e_ij->count = profile_count::from_gcov_type (count);
>
> - e_vj->probability = REG_BR_PROB_BASE;
> + e_vj->probability = profile_probability::always ();
> e_vj->count = profile_count::from_gcov_type (all - count);
>
> /* Insert PHI node for the call result if necessary. */
> @@ -1753,7 +1751,7 @@ gimple_stringops_transform (gimple_stmt_
> gcov_type count, all, val;
> tree dest, src;
> unsigned int dest_align, src_align;
> - gcov_type prob;
> + profile_probability prob;
> tree tree_val;
> int size_arg;
>
> @@ -1788,9 +1786,9 @@ gimple_stringops_transform (gimple_stmt_
> if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count))
> return false;
> if (all > 0)
> - prob = GCOV_COMPUTE_SCALE (count, all);
> + prob = profile_probability::probability_in_gcov_type (count, all);
> else
> - prob = 0;
> + prob = profile_probability::never ();
>
> dest = gimple_call_arg (stmt, 0);
> dest_align = get_pointer_alignment (dest);
> Index: value-prof.h
> ===================================================================
> --- value-prof.h (revision 249769)
> +++ value-prof.h (working copy)
> @@ -90,8 +90,8 @@ void gimple_move_stmt_histograms (struct
> void verify_histograms (void);
> void free_histograms (function *);
> void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
> -gcall *gimple_ic (gcall *, struct cgraph_node *, int, profile_count,
> - profile_count);
> +gcall *gimple_ic (gcall *, struct cgraph_node *, profile_probability,
> + profile_count, profile_count);
> bool check_ic_target (gcall *, struct cgraph_node *);
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 18:28 ` Christophe Lyon
@ 2017-06-29 22:19 ` Jan Hubicka
2017-06-29 22:22 ` Ramana Radhakrishnan
0 siblings, 1 reply; 19+ messages in thread
From: Jan Hubicka @ 2017-06-29 22:19 UTC (permalink / raw)
To: Christophe Lyon; +Cc: Jan Hubicka, gcc-patches, Jakub Jelinek, Martin Li?ka
> After this commit (r249800), GCC builds fail for arm and aarch64:
>
> /gccsrc/gcc/except.c: In function ???void
> sjlj_emit_function_enter(rtx_code_label*)???:
> /gcc-fsf/gccsrc/gcc/except.c:1183: error: conversion from ???int??? to
> non-scalar type ???profile_probability??? requested
> make[2]: *** [except.o] Error 1
The following patch should help
Index: except.c
===================================================================
--- except.c (revision 249800)
+++ except.c (working copy)
@@ -1180,7 +1180,7 @@ sjlj_emit_function_enter (rtx_code_label
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0,
- dispatch_label, REG_BR_PROB_BASE / 100);
+ dispatch_label, profile_probability::unlikely ());
#else
expand_builtin_setjmp_setup (addr, dispatch_label);
#endif
I will verify that cross compiler builds and commit it.
Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 22:19 ` Jan Hubicka
@ 2017-06-29 22:22 ` Ramana Radhakrishnan
2017-06-29 22:24 ` Jan Hubicka
0 siblings, 1 reply; 19+ messages in thread
From: Ramana Radhakrishnan @ 2017-06-29 22:22 UTC (permalink / raw)
To: Jan Hubicka; +Cc: Christophe Lyon, gcc-patches, Jakub Jelinek, Martin Li?ka
On Thu, Jun 29, 2017 at 11:19 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> After this commit (r249800), GCC builds fail for arm and aarch64:
>>
>> /gccsrc/gcc/except.c: In function ???void
>> sjlj_emit_function_enter(rtx_code_label*)???:
>> /gcc-fsf/gccsrc/gcc/except.c:1183: error: conversion from ???int??? to
>> non-scalar type ???profile_probability??? requested
>> make[2]: *** [except.o] Error 1
>
> The following patch should help
> Index: except.c
> ===================================================================
> --- except.c (revision 249800)
> +++ except.c (working copy)
> @@ -1180,7 +1180,7 @@ sjlj_emit_function_enter (rtx_code_label
>
> emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
> TYPE_MODE (integer_type_node), 0,
> - dispatch_label, REG_BR_PROB_BASE / 100);
> + dispatch_label, profile_probability::unlikely ());
> #else
> expand_builtin_setjmp_setup (addr, dispatch_label);
> #endif
>
>
> I will verify that cross compiler builds and commit it.
I also see on arm-none-eabi:
In file included from
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/config/arm/arm-builtins.c:30:0:
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:251:10:
error: 'profile_probability' has not been declared
profile_probability prob
^
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:252:8:
error: 'profile_probability' has not been declared
= profile_probability::uninitialized ());
^
In file included from
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/config/arm/arm-builtins.c:37:0:
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/expr.h:291:63:
error: 'profile_probability' has not been declared
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx,
profile_probability);
^
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/expr.h:292:61:
error: 'profile_probability' has not been declared
extern int try_tablejump (tree, tree, tree, tree, rtx, rtx,
profile_probability);
^
g++ -fno-PIE -c -O1 -g -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE
-fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall
-Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute
-Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros
-Wno-overlength-strings -fno-common -DHAVE_CONFIG_H -I. -I.
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/.
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/../include
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/../libcpp/include
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/build-arm-none-eabi/host-tools/include
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/build-arm-none-eabi/host-tools/include
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/build-arm-none-eabi/host-tools/include
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/../libdecnumber
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/../libdecnumber/dpd
-I../libdecnumber
-I/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/../libbacktrace
-o hooks.o -MT hooks.o -MMD -MP -MF ./.deps/hooks.TPo
/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/hooks.c
make[1]: *** [arm-builtins.o] Error 1
make[1]: *** Waiting for unfinished jobs....
rm gcov-tool.pod gcov.pod gfdl.pod cpp.pod gpl.pod gcov-dump.pod
fsf-funding.pod gcc.pod
make[1]: Leaving directory
`/tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/build-arm-none-eabi/obj/gcc1/gcc'
Ramana
>
> Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 22:22 ` Ramana Radhakrishnan
@ 2017-06-29 22:24 ` Jan Hubicka
2017-06-29 22:29 ` Ramana Radhakrishnan
0 siblings, 1 reply; 19+ messages in thread
From: Jan Hubicka @ 2017-06-29 22:24 UTC (permalink / raw)
To: Ramana Radhakrishnan
Cc: Christophe Lyon, gcc-patches, Jakub Jelinek, Martin Li?ka
> On Thu, Jun 29, 2017 at 11:19 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> >> After this commit (r249800), GCC builds fail for arm and aarch64:
> >>
> >> /gccsrc/gcc/except.c: In function ???void
> >> sjlj_emit_function_enter(rtx_code_label*)???:
> >> /gcc-fsf/gccsrc/gcc/except.c:1183: error: conversion from ???int??? to
> >> non-scalar type ???profile_probability??? requested
> >> make[2]: *** [except.o] Error 1
> >
> > The following patch should help
> > Index: except.c
> > ===================================================================
> > --- except.c (revision 249800)
> > +++ except.c (working copy)
> > @@ -1180,7 +1180,7 @@ sjlj_emit_function_enter (rtx_code_label
> >
> > emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
> > TYPE_MODE (integer_type_node), 0,
> > - dispatch_label, REG_BR_PROB_BASE / 100);
> > + dispatch_label, profile_probability::unlikely ());
> > #else
> > expand_builtin_setjmp_setup (addr, dispatch_label);
> > #endif
> >
> >
> > I will verify that cross compiler builds and commit it.
>
> I also see on arm-none-eabi:
>
>
> In file included from
> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/config/arm/arm-builtins.c:30:0:
> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:251:10:
> error: 'profile_probability' has not been declared
> profile_probability prob
> ^
> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:252:8:
> error: 'profile_probability' has not been declared
> = profile_probability::uninitialized ());
> ^
Yep, this is because we opted to not have #includes in include files which makes it quite painful
to introduce new data types in their own types which are used elsewhere.
I will add #include <profile-count.h> into arm-builtins.c as well.
Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 22:24 ` Jan Hubicka
@ 2017-06-29 22:29 ` Ramana Radhakrishnan
2017-06-29 22:39 ` Jan Hubicka
0 siblings, 1 reply; 19+ messages in thread
From: Ramana Radhakrishnan @ 2017-06-29 22:29 UTC (permalink / raw)
To: Jan Hubicka; +Cc: Christophe Lyon, gcc-patches, Jakub Jelinek, Martin Li?ka
On Thu, Jun 29, 2017 at 11:24 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> On Thu, Jun 29, 2017 at 11:19 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> >> After this commit (r249800), GCC builds fail for arm and aarch64:
>> >>
>> >> /gccsrc/gcc/except.c: In function ???void
>> >> sjlj_emit_function_enter(rtx_code_label*)???:
>> >> /gcc-fsf/gccsrc/gcc/except.c:1183: error: conversion from ???int??? to
>> >> non-scalar type ???profile_probability??? requested
>> >> make[2]: *** [except.o] Error 1
>> >
>> > The following patch should help
>> > Index: except.c
>> > ===================================================================
>> > --- except.c (revision 249800)
>> > +++ except.c (working copy)
>> > @@ -1180,7 +1180,7 @@ sjlj_emit_function_enter (rtx_code_label
>> >
>> > emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
>> > TYPE_MODE (integer_type_node), 0,
>> > - dispatch_label, REG_BR_PROB_BASE / 100);
>> > + dispatch_label, profile_probability::unlikely ());
>> > #else
>> > expand_builtin_setjmp_setup (addr, dispatch_label);
>> > #endif
>> >
>> >
>> > I will verify that cross compiler builds and commit it.
>>
>> I also see on arm-none-eabi:
>>
>>
>> In file included from
>> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/config/arm/arm-builtins.c:30:0:
>> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:251:10:
>> error: 'profile_probability' has not been declared
>> profile_probability prob
>> ^
>> /tmp/66508161.tmpdir/buildbot/rhe6x86_64--arm-none-eabi/build/src/gcc/gcc/optabs.h:252:8:
>> error: 'profile_probability' has not been declared
>> = profile_probability::uninitialized ());
>> ^
>
> Yep, this is because we opted to not have #includes in include files which makes it quite painful
> to introduce new data types in their own types which are used elsewhere.
> I will add #include <profile-count.h> into arm-builtins.c as well.
It is what it is. I really wish we had a buildbot to do some
pre-commit testing of such major patches .
Ramana
>
> Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 22:29 ` Ramana Radhakrishnan
@ 2017-06-29 22:39 ` Jan Hubicka
2017-06-30 23:06 ` Joseph Myers
0 siblings, 1 reply; 19+ messages in thread
From: Jan Hubicka @ 2017-06-29 22:39 UTC (permalink / raw)
To: Ramana Radhakrishnan
Cc: Christophe Lyon, gcc-patches, Jakub Jelinek, Martin Li?ka
Hi,
this patch makes cross compiler for all three targets to build again.
Comitted as obvious.
* arm/arm-builtins.c: Include profile-count.h
* except.c (sjlj_emit_function_enter): Use
profile_probability::unlikely.
Index: config/arm/arm-builtins.c
===================================================================
--- config/arm/arm-builtins.c (revision 249799)
+++ config/arm/arm-builtins.c (working copy)
@@ -27,6 +27,7 @@
#include "gimple-expr.h"
#include "memmodel.h"
#include "tm_p.h"
+#include "profile-count.h"
#include "optabs.h"
#include "emit-rtl.h"
#include "recog.h"
Index: except.c
===================================================================
--- except.c (revision 249800)
+++ except.c (working copy)
@@ -1180,7 +1180,8 @@ sjlj_emit_function_enter (rtx_code_label
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0,
- dispatch_label, REG_BR_PROB_BASE / 100);
+ dispatch_label,
+ profile_probability::unlikely ());
#else
expand_builtin_setjmp_setup (addr, dispatch_label);
#endif
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Committed] S/390: Adjust to the recent branch probability changes.
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
2017-06-29 18:28 ` Christophe Lyon
@ 2017-06-30 6:51 ` Andreas Krebbel
2017-06-30 6:53 ` [Committed] profile-count.h: Fix typos and whitespace issues Andreas Krebbel
` (2 subsequent siblings)
4 siblings, 0 replies; 19+ messages in thread
From: Andreas Krebbel @ 2017-06-30 6:51 UTC (permalink / raw)
To: gcc-patches
This fixes the bootstrap failure triggered by the recent changes wrt
branch probabilities aka emit_cmp_and_jump_insns does not accept
integers as branch probability anymore.
Regressiontested on s390x.
gcc/ChangeLog:
2017-06-30 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/s390/s390.c (s390_expand_setmem): Adjust to the new data
type for branch probabilities.
---
gcc/config/s390/s390.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index bfc38db..958ee3b 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5349,8 +5349,6 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
void
s390_expand_setmem (rtx dst, rtx len, rtx val)
{
- const int very_unlikely = REG_BR_PROB_BASE / 100 - 1;
-
if (GET_CODE (len) == CONST_INT && INTVAL (len) <= 0)
return;
@@ -5424,7 +5422,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
convert_move (count, len, 1);
emit_cmp_and_jump_insns (count, const0_rtx,
EQ, NULL_RTX, mode, 1, zerobyte_end_label,
- very_unlikely);
+ profile_probability::very_unlikely ());
/* We need to make a copy of the target address since memset is
supposed to return it unmodified. We have to make it here
@@ -5441,7 +5439,8 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
dstp1 = adjust_address (dst, VOIDmode, 1);
emit_cmp_and_jump_insns (count,
const1_rtx, EQ, NULL_RTX, mode, 1,
- onebyte_end_label, very_unlikely);
+ onebyte_end_label,
+ profile_probability::very_unlikely ());
}
/* There is one unconditional (mvi+mvc)/xc after the loop
--
2.9.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Committed] profile-count.h: Fix typos and whitespace issues.
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
2017-06-29 18:28 ` Christophe Lyon
2017-06-30 6:51 ` [Committed] S/390: Adjust to the recent branch probability changes Andreas Krebbel
@ 2017-06-30 6:53 ` Andreas Krebbel
2017-06-30 16:33 ` Convert profile probabilities to new type Andreas Schwab
2017-07-13 20:39 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared (was: Convert profile probabilities to new type) Jan-Benedict Glaw
4 siblings, 0 replies; 19+ messages in thread
From: Andreas Krebbel @ 2017-06-30 6:53 UTC (permalink / raw)
To: gcc-patches
I noticed a couple of typos and whitespace issues in profile-count.h.
I've committed the following patch to fix them.
gcc/ChangeLog:
2017-06-30 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* profile-count.h (enum profile_quality): Fix typos and whitespace
issues.
---
gcc/profile-count.h | 46 +++++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 461dac6..6a10315 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -21,15 +21,15 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_PROFILE_COUNT_H
#define GCC_PROFILE_COUNT_H
-/* Quality of the proflie count. Because gengtype does not support enums
- inside of clases, this is in global namespace. */
+/* Quality of the profile count. Because gengtype does not support enums
+ inside of classes, this is in global namespace. */
enum profile_quality {
/* Profile is based on static branch prediction heuristics. It may or may
not reflect the reality. */
profile_guessed = 0,
/* Profile was determined by autofdo. */
profile_afdo = 1,
- /* Profile was originally based on feedback but it was adjusted
+ /* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
profile_adjusted = 2,
@@ -43,13 +43,13 @@ enum profile_quality {
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
-/* Data type to hold probabilities. It implement fixed point arithmetics
+/* Data type to hold probabilities. It implements fixed point arithmetics
with capping so probability is always in range [0,1] and scaling requiring
values greater than 1 needs to be represented otherwise.
In addition to actual value the quality of profile is tracked and propagated
through all operations. Special value UNINITIALIZED is used for probabilities
- that has not been detemrined yet (for example bacause of
+ that has not been determined yet (for example bacause of
-fno-guess-branch-probability)
Typically probabilities are derived from profile feedback (via
@@ -68,15 +68,15 @@ enum profile_quality {
- always
Named probabilities except for never/always are assumed to be statically
- guessed and thus not necessarily acurate. The difference between never
- and guessedn never is that the first one should be used only in case that
+ guessed and thus not necessarily accurate. The difference between never
+ and guessed_never is that the first one should be used only in case that
well behaving program will very likely not execute the "never" path.
For example if the path is going to abort () call or it exception handling.
- Alawyas and guessted_always probabilities are symmetric.
+ Always and guessed_always probabilities are symmetric.
For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
- integer arithmetics. Once the code is converted to branch probabiitlies,
+ integer arithmetics. Once the code is converted to branch probabilities,
these conversions will probably go away because they are lossy.
*/
@@ -175,7 +175,7 @@ public:
}
/* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
- this is mostly to support legacy code and hsould go away. */
+ this is mostly to support legacy code and should go away. */
static profile_probability from_reg_br_prob_base (int v)
{
profile_probability ret;
@@ -199,7 +199,7 @@ public:
if (val1 > val2)
ret.m_val = max_probability;
else
- ret.m_val = RDIV (val1 * max_probability, val2);
+ ret.m_val = RDIV (val1 * max_probability, val2);
ret.m_quality = profile_precise;
return ret;
}
@@ -237,7 +237,7 @@ public:
else
{
m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -263,7 +263,7 @@ public:
else
{
m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -288,8 +288,8 @@ public:
return *this = profile_probability::uninitialized ();
else
{
- m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
- m_quality = MIN (m_quality, other.m_quality);
+ m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -307,7 +307,7 @@ public:
else
{
gcc_checking_assert (other.m_val);
- ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
other.m_val),
max_probability);
}
@@ -329,11 +329,11 @@ public:
else
{
gcc_checking_assert (other.m_val);
- m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
other.m_val),
max_probability);
}
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -591,7 +591,7 @@ public:
else
{
m_val += other.m_val;
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -615,7 +615,7 @@ public:
else
{
m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
- m_quality = MIN (m_quality, other.m_quality);
+ m_quality = MIN (m_quality, other.m_quality);
}
return *this;
}
@@ -727,9 +727,9 @@ public:
profile_count ret;
/* Take care for overflows! */
if (num.m_val < max_safe_multiplier || m_val < max_safe_multiplier)
- ret.m_val = RDIV (m_val * num.m_val, den.m_val);
+ ret.m_val = RDIV (m_val * num.m_val, den.m_val);
else
- ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
+ ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
den.m_val), max_safe_multiplier);
ret.m_quality = MIN (m_quality, profile_adjusted);
return ret;
@@ -748,7 +748,7 @@ public:
if (overall < m_val)
ret.m_val = profile_probability::max_probability;
else
- ret.m_val = RDIV (m_val * profile_probability::max_probability,
+ ret.m_val = RDIV (m_val * profile_probability::max_probability,
overall.m_val);
ret.m_quality = MIN (m_quality, overall.m_quality);
return ret;
--
2.9.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
` (2 preceding siblings ...)
2017-06-30 6:53 ` [Committed] profile-count.h: Fix typos and whitespace issues Andreas Krebbel
@ 2017-06-30 16:33 ` Andreas Schwab
2017-06-30 18:28 ` Alexander Monakov
2017-07-13 20:39 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared (was: Convert profile probabilities to new type) Jan-Benedict Glaw
4 siblings, 1 reply; 19+ messages in thread
From: Andreas Schwab @ 2017-06-30 16:33 UTC (permalink / raw)
To: Jan Hubicka; +Cc: gcc-patches, jakub, mliska
This breaks ia64, a lot of testsuite failures like this:
FAIL: c-c++-common/torture/pr53505.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error)
FAIL: c-c++-common/torture/pr53505.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (test for excess errors)
Excess errors:
during RTL pass: mach
/usr/local/gcc/gcc-20170630/gcc/testsuite/c-c++-common/torture/pr53505.c:26:1: internal compiler error: in merge_expr, at sel-sched-ir.c:1886
0x40000000010b897f merge_expr(_expr*, _expr*, rtx_insn*)
../../gcc/sel-sched-ir.c:1886
0x40000000010c809f av_set_union_and_live(_list_node**, _list_node**, bitmap_head*, bitmap_head*, rtx_insn*)
../../gcc/sel-sched-ir.c:2278
0x40000000010e430f compute_av_set_at_bb_end
../../gcc/sel-sched.c:2808
0x40000000010e430f compute_av_set_inside_bb
../../gcc/sel-sched.c:2980
0x40000000010e52ff move_op_at_first_insn
../../gcc/sel-sched.c:6070
0x40000000010e889f code_motion_path_driver
../../gcc/sel-sched.c:6659
0x40000000010e90af code_motion_process_successors
../../gcc/sel-sched.c:6346
0x40000000010e90af code_motion_path_driver
../../gcc/sel-sched.c:6612
0x40000000010ea57f move_op
../../gcc/sel-sched.c:6704
0x40000000010ea57f move_exprs_to_boundary
../../gcc/sel-sched.c:5227
0x40000000010ea57f schedule_expr_on_boundary
../../gcc/sel-sched.c:5440
0x40000000010f4e2f fill_insns
../../gcc/sel-sched.c:5582
0x40000000010f4e2f schedule_on_fences
../../gcc/sel-sched.c:7356
0x40000000010f4e2f sel_sched_region_2
../../gcc/sel-sched.c:7494
0x40000000010fe48f sel_sched_region_1
../../gcc/sel-sched.c:7536
0x40000000010fe48f sel_sched_region(int)
../../gcc/sel-sched.c:7637
0x40000000010ff60f run_selective_scheduling()
../../gcc/sel-sched.c:7713
0x4000000001a7e6cf ia64_reorg
../../gcc/config/ia64/ia64.c:9764
0x400000000105564f execute
../../gcc/reorg.c:3946
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-30 16:33 ` Convert profile probabilities to new type Andreas Schwab
@ 2017-06-30 18:28 ` Alexander Monakov
2017-06-30 19:26 ` Jan Hubicka
2017-07-01 7:49 ` Jan Hubicka
0 siblings, 2 replies; 19+ messages in thread
From: Alexander Monakov @ 2017-06-30 18:28 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Jan Hubicka, gcc-patches, jakub, mliska
On Fri, 30 Jun 2017, Andreas Schwab wrote:
> This breaks ia64, a lot of testsuite failures like this:
>
> FAIL: c-c++-common/torture/pr53505.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (internal compiler error)
> FAIL: c-c++-common/torture/pr53505.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (test for excess errors)
> Excess errors:
> during RTL pass: mach
> /usr/local/gcc/gcc-20170630/gcc/testsuite/c-c++-common/torture/pr53505.c:26:1: internal compiler error: in merge_expr, at sel-sched-ir.c:1886
The patch introduced a new inconsistency in sel-sched-ir.c:
@@ -4747,7 +4747,9 @@ compute_succs_info (insn_t insn, short flags)
sinfo->probs_ok.safe_push (
/* FIXME: Improve calculation when skipping
inner loop to exits. */
- si.bb_end ? si.e1->probability : REG_BR_PROB_BASE);
+ si.bb_end && si.e1->probability.initialized_p ()
+ ? si.e1->probability.to_reg_br_prob_base ()
+ : REG_BR_PROB_BASE);
sinfo->succs_ok_n++;
}
else
@@ -4756,8 +4758,8 @@ compute_succs_info (insn_t insn, short flags)
/* Compute all_prob. */
if (!si.bb_end)
sinfo->all_prob = REG_BR_PROB_BASE;
- else
- sinfo->all_prob += si.e1->probability;
+ else if (si.e1->probability.initialized_p ())
+ sinfo->all_prob += si.e1->probability.to_reg_br_prob_base ();
sinfo->all_succs_n++;
}
After the change, edges that fail the predicate contribute REG_BR_PROB_BASE in
the upper hunk, but 0 in the lower hunk. Before the change, they contributed 0
in both cases.
The following patch should restore things:
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index dd72828..fa88259 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -4747,8 +4747,10 @@ compute_succs_info (insn_t insn, short flags)
sinfo->probs_ok.safe_push (
/* FIXME: Improve calculation when skipping
inner loop to exits. */
- si.bb_end && si.e1->probability.initialized_p ()
- ? si.e1->probability.to_reg_br_prob_base ()
+ si.bb_end
+ ? (si.e1->probability.initialized_p ()
+ ? si.e1->probability.to_reg_br_prob_base ()
+ : 0)
: REG_BR_PROB_BASE);
sinfo->succs_ok_n++;
}
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-30 18:28 ` Alexander Monakov
@ 2017-06-30 19:26 ` Jan Hubicka
2017-07-01 7:49 ` Jan Hubicka
1 sibling, 0 replies; 19+ messages in thread
From: Jan Hubicka @ 2017-06-30 19:26 UTC (permalink / raw)
To: Alexander Monakov; +Cc: Andreas Schwab, gcc-patches, jakub, mliska
>
> After the change, edges that fail the predicate contribute REG_BR_PROB_BASE in
> the upper hunk, but 0 in the lower hunk. Before the change, they contributed 0
> in both cases.
>
> The following patch should restore things:
>
> diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
> index dd72828..fa88259 100644
> --- a/gcc/sel-sched-ir.c
> +++ b/gcc/sel-sched-ir.c
> @@ -4747,8 +4747,10 @@ compute_succs_info (insn_t insn, short flags)
> sinfo->probs_ok.safe_push (
> /* FIXME: Improve calculation when skipping
> inner loop to exits. */
> - si.bb_end && si.e1->probability.initialized_p ()
> - ? si.e1->probability.to_reg_br_prob_base ()
> + si.bb_end
> + ? (si.e1->probability.initialized_p ()
> + ? si.e1->probability.to_reg_br_prob_base ()
> + : 0)
> : REG_BR_PROB_BASE);
> sinfo->succs_ok_n++;
> }
Ah, thanks! This looks OK to me.
I was not quite sure what to do with missing probabilities in this case.
Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-29 22:39 ` Jan Hubicka
@ 2017-06-30 23:06 ` Joseph Myers
2017-07-01 7:29 ` Jan Hubicka
0 siblings, 1 reply; 19+ messages in thread
From: Joseph Myers @ 2017-06-30 23:06 UTC (permalink / raw)
To: Jan Hubicka
Cc: Ramana Radhakrishnan, Christophe Lyon, gcc-patches,
Jakub Jelinek, Martin Li?ka
Also seeing a possibly related failure from my glibc bot, building for
hppa-linux-gnu:
/scratch/jmyers/glibc-bot/src/gcc/gcc/config/pa/pa.c: In function 'bool pa_expand_compare_and_swap_loop(rtx, rtx, rtx, rtx)':
/scratch/jmyers/glibc-bot/src/gcc/gcc/config/pa/pa.c:10726:59: error: could not convert '0' from 'int' to 'profile_probability'
GET_MODE (success), 1, label, 0);
^
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-30 23:06 ` Joseph Myers
@ 2017-07-01 7:29 ` Jan Hubicka
0 siblings, 0 replies; 19+ messages in thread
From: Jan Hubicka @ 2017-07-01 7:29 UTC (permalink / raw)
To: Joseph Myers
Cc: Ramana Radhakrishnan, Christophe Lyon, gcc-patches,
Jakub Jelinek, Martin Li?ka
Hi,
I have checked in the following fix.
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c (revision 249854)
+++ config/pa/pa.c (working copy)
@@ -10723,7 +10723,8 @@ pa_expand_compare_and_swap_loop (rtx mem
/* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
- GET_MODE (success), 1, label, 0);
+ GET_MODE (success), 1, label,
+ profile_probability::guessed_never ());
return true;
}
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Convert profile probabilities to new type
2017-06-30 18:28 ` Alexander Monakov
2017-06-30 19:26 ` Jan Hubicka
@ 2017-07-01 7:49 ` Jan Hubicka
1 sibling, 0 replies; 19+ messages in thread
From: Jan Hubicka @ 2017-07-01 7:49 UTC (permalink / raw)
To: Alexander Monakov; +Cc: Andreas Schwab, gcc-patches, jakub, mliska
> The following patch should restore things:
>
> diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
> index dd72828..fa88259 100644
> --- a/gcc/sel-sched-ir.c
> +++ b/gcc/sel-sched-ir.c
> @@ -4747,8 +4747,10 @@ compute_succs_info (insn_t insn, short flags)
> sinfo->probs_ok.safe_push (
> /* FIXME: Improve calculation when skipping
> inner loop to exits. */
> - si.bb_end && si.e1->probability.initialized_p ()
> - ? si.e1->probability.to_reg_br_prob_base ()
> + si.bb_end
> + ? (si.e1->probability.initialized_p ()
> + ? si.e1->probability.to_reg_br_prob_base ()
> + : 0)
> : REG_BR_PROB_BASE);
> sinfo->succs_ok_n++;
> }
Hi,
I have tested that it indeed fixes the ICE and weant ahead and comitted it.
Honza
^ permalink raw reply [flat|nested] 19+ messages in thread
* [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared (was: Convert profile probabilities to new type)
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
` (3 preceding siblings ...)
2017-06-30 16:33 ` Convert profile probabilities to new type Andreas Schwab
@ 2017-07-13 20:39 ` Jan-Benedict Glaw
2017-07-13 20:44 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared Jeff Law
4 siblings, 1 reply; 19+ messages in thread
From: Jan-Benedict Glaw @ 2017-07-13 20:39 UTC (permalink / raw)
To: Jan Hubicka, Kito Cheng, Palmer Dabbelt, Andrew Waterman
Cc: gcc-patches, jakub, mliska
[-- Attachment #1: Type: text/plain, Size: 4193 bytes --]
Hi Jan,
hi Kito, Palmer and Andrew!
On Thu, 2017-06-29 14:27:41 +0200, Jan Hubicka <hubicka@ucw.cz> wrote:
> this is second step of the profile maintenance revamp. It implements
> profile_probability type which is pretty much symmetric to profile_count
> except that it implements fixed point arithmetics for values 0...1.
> It is used to maintain probabilities of edges out of basic blocks.
> In addition it tracks information about quality of the estimate which can
> later be used for optimization.
RISC-V (--enable-languages=c,c++ --target=riscv32-unknown-linux-gnu
--without-headers --disable-threads) fails to build right now,
probably only missing header or header order:
[...]
g++ -fno-PIE -c -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fno-common -DHAVE_CONFIG_H -I. -I. -I/home/jbglaw/repos/gcc/gcc -I/home/jbglaw/repos/gcc/gcc/. -I/home/jbglaw/repos/gcc/gcc/../include -I/home/jbglaw/repos/gcc/gcc/../libcpp/include -I/home/jbglaw/repos/gcc/gcc/../libdecnumber -I/home/jbglaw/repos/gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I/home/jbglaw/repos/gcc/gcc/../libbacktrace -o riscv.o -MT riscv.o -MMD -MP -MF ./.deps/riscv.TPo /home/jbglaw/repos/gcc/gcc/config/riscv/riscv.c
In file included from /home/jbglaw/repos/gcc/gcc/config/riscv/riscv.c:56:0:
/home/jbglaw/repos/gcc/gcc/dojump.h:61:10: error: ‘profile_probability’ has not been declared
profile_probability prob);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:63:5: error: ‘profile_probability’ has not been declared
profile_probability);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:66:54: error: ‘profile_probability’ has not been declared
extern void jumpif (tree exp, rtx_code_label *label, profile_probability prob);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:68:9: error: ‘profile_probability’ has not been declared
profile_probability);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:73:39: error: ‘profile_probability’ has not been declared
rtx_code_label *if_true_label, profile_probability prob);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:75:28: error: ‘profile_probability’ has not been declared
rtx_code_label *, profile_probability);
^
/home/jbglaw/repos/gcc/gcc/dojump.h:79:28: error: ‘profile_probability’ has not been declared
rtx_code_label *, profile_probability);
^
In file included from /home/jbglaw/repos/gcc/gcc/config/riscv/riscv.c:61:0:
/home/jbglaw/repos/gcc/gcc/expr.h:291:63: error: ‘profile_probability’ has not been declared
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
^
/home/jbglaw/repos/gcc/gcc/expr.h:292:61: error: ‘profile_probability’ has not been declared
extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, profile_probability);
^
In file included from /home/jbglaw/repos/gcc/gcc/config/riscv/riscv.c:63:0:
/home/jbglaw/repos/gcc/gcc/optabs.h:251:10: error: ‘profile_probability’ has not been declared
profile_probability prob
^
/home/jbglaw/repos/gcc/gcc/optabs.h:252:8: error: ‘profile_probability’ has not been declared
= profile_probability::uninitialized ());
^
Makefile:2259: recipe for target 'riscv.o' failed
make[1]: *** [riscv.o] Error 1
make[1]: Leaving directory '/home/jbglaw/build/riscv32-unknown-linux-gnu/build-gcc/gcc'
Makefile:4286: recipe for target 'all-gcc' failed
make: *** [all-gcc] Error 2
--
Jan-Benedict Glaw jbglaw@lug-owl.de +49-172-7608481
Signature of: They that give up essential liberty to obtain temporary safety,
the second : deserve neither liberty nor safety. (Ben Franklin)
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared
2017-07-13 20:39 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared (was: Convert profile probabilities to new type) Jan-Benedict Glaw
@ 2017-07-13 20:44 ` Jeff Law
2017-07-13 20:45 ` [BUILDROBOT] RISC-V: âprofile_probabilityâ " Palmer Dabbelt
2017-07-13 21:03 ` [BUILDROBOT] RISC-V: ‘profile_probability’ " Jan-Benedict Glaw
0 siblings, 2 replies; 19+ messages in thread
From: Jeff Law @ 2017-07-13 20:44 UTC (permalink / raw)
To: Jan-Benedict Glaw, Jan Hubicka, Kito Cheng, Palmer Dabbelt,
Andrew Waterman
Cc: gcc-patches, jakub, mliska
[-- Attachment #1.1: Type: text/plain, Size: 815 bytes --]
On 07/13/2017 02:39 PM, Jan-Benedict Glaw wrote:
> Hi Jan,
> hi Kito, Palmer and Andrew!
>
> On Thu, 2017-06-29 14:27:41 +0200, Jan Hubicka <hubicka@ucw.cz> wrote:
>> this is second step of the profile maintenance revamp. It implements
>> profile_probability type which is pretty much symmetric to profile_count
>> except that it implements fixed point arithmetics for values 0...1.
>> It is used to maintain probabilities of edges out of basic blocks.
>> In addition it tracks information about quality of the estimate which can
>> later be used for optimization.
>
> RISC-V (--enable-languages=c,c++ --target=riscv32-unknown-linux-gnu
> --without-headers --disable-threads) fails to build right now,
> probably only missing header or header order:
[ ... ]
I fixed that yesterday :-)
jeff
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [BUILDROBOT] RISC-V: âprofile_probabilityâ has not been declared
2017-07-13 20:44 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared Jeff Law
@ 2017-07-13 20:45 ` Palmer Dabbelt
2017-07-13 21:03 ` [BUILDROBOT] RISC-V: ‘profile_probability’ " Jan-Benedict Glaw
1 sibling, 0 replies; 19+ messages in thread
From: Palmer Dabbelt @ 2017-07-13 20:45 UTC (permalink / raw)
To: law
Cc: jbglaw, hubicka, kito.cheng, Andrew Waterman, gcc-patches, jakub, mliska
On Thu, 13 Jul 2017 13:43:52 PDT (-0700), law@redhat.com wrote:
> On 07/13/2017 02:39 PM, Jan-Benedict Glaw wrote:
>> Hi Jan,
>> hi Kito, Palmer and Andrew!
>>
>> On Thu, 2017-06-29 14:27:41 +0200, Jan Hubicka <hubicka@ucw.cz> wrote:
>>> this is second step of the profile maintenance revamp. It implements
>>> profile_probability type which is pretty much symmetric to profile_count
>>> except that it implements fixed point arithmetics for values 0...1.
>>> It is used to maintain probabilities of edges out of basic blocks.
>>> In addition it tracks information about quality of the estimate which can
>>> later be used for optimization.
>>
>> RISC-V (--enable-languages=c,c++ --target=riscv32-unknown-linux-gnu
>> --without-headers --disable-threads) fails to build right now,
>> probably only missing header or header order:
> [ ... ]
> I fixed that yesterday :-)
Thanks! I was just cloning a fresh version to try and reproduce it.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared
2017-07-13 20:44 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared Jeff Law
2017-07-13 20:45 ` [BUILDROBOT] RISC-V: âprofile_probabilityâ " Palmer Dabbelt
@ 2017-07-13 21:03 ` Jan-Benedict Glaw
1 sibling, 0 replies; 19+ messages in thread
From: Jan-Benedict Glaw @ 2017-07-13 21:03 UTC (permalink / raw)
To: Jeff Law, Jan Hubicka, Kito Cheng, Palmer Dabbelt, Andrew Waterman
Cc: gcc-patches, jakub, mliska
[-- Attachment #1: Type: text/plain, Size: 1190 bytes --]
Hi Jeff!
On Thu, 2017-07-13 14:43:52 -0600, Jeff Law <law@redhat.com> wrote:
> On 07/13/2017 02:39 PM, Jan-Benedict Glaw wrote:
> > On Thu, 2017-06-29 14:27:41 +0200, Jan Hubicka <hubicka@ucw.cz> wrote:
> >> this is second step of the profile maintenance revamp. It implements
> >> profile_probability type which is pretty much symmetric to profile_count
> >> except that it implements fixed point arithmetics for values 0...1.
> >> It is used to maintain probabilities of edges out of basic blocks.
> >> In addition it tracks information about quality of the estimate which can
> >> later be used for optimization.
> >
> > RISC-V (--enable-languages=c,c++ --target=riscv32-unknown-linux-gnu
> > --without-headers --disable-threads) fails to build right now,
> > probably only missing header or header order:
> [ ... ]
> I fixed that yesterday :-)
Took me a bit to look through the logs. Great! to see you're fixing
faster than I'd search for these small break-ups. :)
MfG, JBG
--
Jan-Benedict Glaw jbglaw@lug-owl.de +49-172-7608481
Signature of: Alles wird gut! ...und heute wirds schon ein bißchen besser.
the second :
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2017-07-13 21:03 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-29 12:28 Convert profile probabilities to new type Jan Hubicka
2017-06-29 18:28 ` Christophe Lyon
2017-06-29 22:19 ` Jan Hubicka
2017-06-29 22:22 ` Ramana Radhakrishnan
2017-06-29 22:24 ` Jan Hubicka
2017-06-29 22:29 ` Ramana Radhakrishnan
2017-06-29 22:39 ` Jan Hubicka
2017-06-30 23:06 ` Joseph Myers
2017-07-01 7:29 ` Jan Hubicka
2017-06-30 6:51 ` [Committed] S/390: Adjust to the recent branch probability changes Andreas Krebbel
2017-06-30 6:53 ` [Committed] profile-count.h: Fix typos and whitespace issues Andreas Krebbel
2017-06-30 16:33 ` Convert profile probabilities to new type Andreas Schwab
2017-06-30 18:28 ` Alexander Monakov
2017-06-30 19:26 ` Jan Hubicka
2017-07-01 7:49 ` Jan Hubicka
2017-07-13 20:39 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared (was: Convert profile probabilities to new type) Jan-Benedict Glaw
2017-07-13 20:44 ` [BUILDROBOT] RISC-V: ‘profile_probability’ has not been declared Jeff Law
2017-07-13 20:45 ` [BUILDROBOT] RISC-V: âprofile_probabilityâ " Palmer Dabbelt
2017-07-13 21:03 ` [BUILDROBOT] RISC-V: ‘profile_probability’ " Jan-Benedict Glaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).