Commit 87022a6b by Jan Hubicka Committed by Jan Hubicka

basic-block.h (guess_outgoing_edge_probabilities): Declare.


	* basic-block.h (guess_outgoing_edge_probabilities): Declare.
	* cfgbuild.c (compute_outgoing_frequencies): When probability is missing,
	guess it.
	(find_many_sub_basic_blocks): Do update profile only when it is present.
	* predict.c (set_even_probabilities): Break out from ...
	(combine_predictions_for_insn): ... here; deal with !can_predict_insn_p insns.
	(combine_predictions_for_bb): Use set_even_probabilities.
	(bb_estimate_probability_locally): Break out from ....
	(estimate_probability): ... here.
	(guess_outgoing_edge_probabilities): New entry point.

From-SVN: r87234
parent 3b5edfee
2004-09-09 Jan Hubicka <jh@suse.cz>
* basic-block.h (guess_outgoing_edge_probabilities): Declare.
* cfgbuild.c (compute_outgoing_frequencies): When probability is missing,
guess it.
(find_many_sub_basic_blocks): Do update profile only when it is present.
* predict.c (set_even_probabilities): Break out from ...
(combine_predictions_for_insn): ... here; deal with !can_predict_insn_p insns.
(combine_predictions_for_bb): Use set_even_probabilities.
(bb_estimate_probability_locally): Break out from ....
(estimate_probability): ... here.
(guess_outgoing_edge_probabilities): New entry point.
2004-09-09 Nathan Sidwell <nathan@codesourcery.com>
* gcc.c (add_sysrooted_prefix, execute, do_self_spec, do_spec_1,
......
......@@ -622,6 +622,7 @@ extern bool rtl_predicted_by_p (basic_block, enum br_predictor);
extern void tree_predict_edge (edge, enum br_predictor, int);
extern void rtl_predict_edge (edge, enum br_predictor, int);
extern void predict_edge_def (edge, enum br_predictor, enum prediction);
extern void guess_outgoing_edge_probabilities (basic_block);
/* In flow.c */
extern void init_flow (void);
......
......@@ -646,9 +646,8 @@ compute_outgoing_frequencies (basic_block b)
rtx note = find_reg_note (BB_END (b), REG_BR_PROB, NULL);
int probability;
if (!note)
return;
if (note)
{
probability = INTVAL (XEXP (note, 0));
e = BRANCH_EDGE (b);
e->probability = probability;
......@@ -657,6 +656,8 @@ compute_outgoing_frequencies (basic_block b)
f = FALLTHRU_EDGE (b);
f->probability = REG_BR_PROB_BASE - probability;
f->count = b->count - e->count;
return;
}
}
if (b->succ && !b->succ->succ_next)
......@@ -664,7 +665,13 @@ compute_outgoing_frequencies (basic_block b)
e = b->succ;
e->probability = REG_BR_PROB_BASE;
e->count = b->count;
return;
}
guess_outgoing_edge_probabilities (b);
if (b->count)
for (e = b->succ; e; e = e->succ_next)
e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
/ REG_BR_PROB_BASE);
}
/* Assume that someone emitted code with control flow instructions to the
......@@ -698,6 +705,7 @@ find_many_sub_basic_blocks (sbitmap blocks)
/* Update branch probabilities. Expect only (un)conditional jumps
to be created with only the forward edges. */
if (profile_status != PROFILE_ABSENT)
FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
{
edge e;
......
......@@ -313,14 +313,32 @@ dump_prediction (FILE *file, enum br_predictor predictor, int probability,
fprintf (file, "\n");
}
/* We can not predict the probabilities of ougtoing edges of bb. Set them
evenly and hope for the best. */
static void
set_even_probabilities (basic_block bb)
{
int nedges = 0;
edge e;
for (e = bb->succ; e; e = e->succ_next)
if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
nedges ++;
for (e = bb->succ; e; e = e->succ_next)
if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges;
else
e->probability = 0;
}
/* Combine all REG_BR_PRED notes into single probability and attach REG_BR_PROB
note if not already present. Remove now useless REG_BR_PRED notes. */
static void
combine_predictions_for_insn (rtx insn, basic_block bb)
{
rtx prob_note = find_reg_note (insn, REG_BR_PROB, 0);
rtx *pnote = &REG_NOTES (insn);
rtx prob_note;
rtx *pnote;
rtx note;
int best_probability = PROB_EVEN;
int best_predictor = END_PREDICTORS;
......@@ -329,6 +347,14 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
bool first_match = false;
bool found = false;
if (!can_predict_insn_p (insn))
{
set_even_probabilities (bb);
return;
}
prob_note = find_reg_note (insn, REG_BR_PROB, 0);
pnote = &REG_NOTES (insn);
if (dump_file)
fprintf (dump_file, "Predictions for insn %i bb %i\n", INSN_UID (insn),
bb->index);
......@@ -446,11 +472,8 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
this later. */
if (nedges != 2)
{
for (e = bb->succ; e; e = e->succ_next)
if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges;
else
e->probability = 0;
if (!bb->count)
set_even_probabilities (bb);
bb_ann (bb)->predictions = NULL;
if (file)
fprintf (file, "%i edges in bb %i predicted to even probabilities\n",
......@@ -521,8 +544,11 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
}
bb_ann (bb)->predictions = NULL;
if (!bb->count)
{
first->probability = combined_probability;
second->probability = REG_BR_PROB_BASE - combined_probability;
}
}
/* Predict edge probabilities by exploiting loop structure.
......@@ -615,75 +641,19 @@ predict_loops (struct loops *loops_info, bool simpleloops)
}
}
/* Statically estimate the probability that a branch will be taken and produce
estimated profile. When profile feedback is present never executed portions
of function gets estimated. */
void
estimate_probability (struct loops *loops_info)
/* Attempt to predict probabilities of BB outgoing edges using local
properties. */
static void
bb_estimate_probability_locally (basic_block bb)
{
basic_block bb;
connect_infinite_loops_to_exit ();
calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS);
predict_loops (loops_info, true);
iv_analysis_done ();
/* Attempt to predict conditional jumps using a number of heuristics. */
FOR_EACH_BB (bb)
{
rtx last_insn = BB_END (bb);
rtx cond;
edge e;
if (! can_predict_insn_p (last_insn))
continue;
for (e = bb->succ; e; e = e->succ_next)
{
/* Predict early returns to be probable, as we've already taken
care for error returns and other are often used for fast paths
trought function. */
if ((e->dest == EXIT_BLOCK_PTR
|| (e->dest->succ && !e->dest->succ->succ_next
&& e->dest->succ->dest == EXIT_BLOCK_PTR))
&& !predicted_by_p (bb, PRED_NULL_RETURN)
&& !predicted_by_p (bb, PRED_CONST_RETURN)
&& !predicted_by_p (bb, PRED_NEGATIVE_RETURN)
&& !last_basic_block_p (e->dest))
predict_edge_def (e, PRED_EARLY_RETURN, TAKEN);
/* Look for block we are guarding (ie we dominate it,
but it doesn't postdominate us). */
if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
&& dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
&& !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
{
rtx insn;
/* The call heuristic claims that a guarded function call
is improbable. This is because such calls are often used
to signal exceptional situations such as printing error
messages. */
for (insn = BB_HEAD (e->dest); insn != NEXT_INSN (BB_END (e->dest));
insn = NEXT_INSN (insn))
if (CALL_P (insn)
/* Constant and pure calls are hardly used to signalize
something exceptional. */
&& ! CONST_OR_PURE_CALL_P (insn))
{
predict_edge_def (e, PRED_CALL, NOT_TAKEN);
break;
}
}
}
return;
cond = get_condition (last_insn, NULL, false, false);
if (! cond)
continue;
return;
/* Try "pointer heuristic."
A comparison ptr == 0 is predicted as false.
......@@ -768,6 +738,73 @@ estimate_probability (struct loops *loops_info)
default:
break;
}
}
/* Statically estimate the probability that a branch will be taken and produce
estimated profile. When profile feedback is present never executed portions
of function gets estimated. */
void
estimate_probability (struct loops *loops_info)
{
basic_block bb;
connect_infinite_loops_to_exit ();
calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS);
predict_loops (loops_info, true);
iv_analysis_done ();
/* Attempt to predict conditional jumps using a number of heuristics. */
FOR_EACH_BB (bb)
{
rtx last_insn = BB_END (bb);
edge e;
if (! can_predict_insn_p (last_insn))
continue;
for (e = bb->succ; e; e = e->succ_next)
{
/* Predict early returns to be probable, as we've already taken
care for error returns and other are often used for fast paths
trought function. */
if ((e->dest == EXIT_BLOCK_PTR
|| (e->dest->succ && !e->dest->succ->succ_next
&& e->dest->succ->dest == EXIT_BLOCK_PTR))
&& !predicted_by_p (bb, PRED_NULL_RETURN)
&& !predicted_by_p (bb, PRED_CONST_RETURN)
&& !predicted_by_p (bb, PRED_NEGATIVE_RETURN)
&& !last_basic_block_p (e->dest))
predict_edge_def (e, PRED_EARLY_RETURN, TAKEN);
/* Look for block we are guarding (ie we dominate it,
but it doesn't postdominate us). */
if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
&& dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
&& !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
{
rtx insn;
/* The call heuristic claims that a guarded function call
is improbable. This is because such calls are often used
to signal exceptional situations such as printing error
messages. */
for (insn = BB_HEAD (e->dest); insn != NEXT_INSN (BB_END (e->dest));
insn = NEXT_INSN (insn))
if (CALL_P (insn)
/* Constant and pure calls are hardly used to signalize
something exceptional. */
&& ! CONST_OR_PURE_CALL_P (insn))
{
predict_edge_def (e, PRED_CALL, NOT_TAKEN);
break;
}
}
}
bb_estimate_probability_locally (bb);
}
/* Attach the combined probability to each conditional jump. */
......@@ -809,6 +846,14 @@ estimate_probability (struct loops *loops_info)
profile_status = PROFILE_GUESSED;
}
/* Set edge->probability for each succestor edge of BB. */
void
guess_outgoing_edge_probabilities (basic_block bb)
{
bb_estimate_probability_locally (bb);
combine_predictions_for_insn (BB_END (bb), bb);
}
/* Predict using opcode of the last statement in basic block. */
static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment