predict.c (probability_reliable_p): New predicate.

* predict.c (probability_reliable_p): New predicate.
	(edge_probability_reliable_p, br_prob_note_reliable_p): Likewise.
	(predict_loops): Do not predict loop exit with less than 2%
	probability.
	* basic-block.h (edge_probability_reliable_p,
	br_prob_note_reliable_p): Declare.
	* ia64.h (ia64_print_operand): Do not disable on-chip branch
	prediction when static predictor is not reliable.
	* rs6000.c (output_cbranch): Likewise.

From-SVN: r116358
This commit is contained in:
Jan Hubicka 2006-08-24 00:29:14 +02:00 committed by Jan Hubicka
parent a4d0390b44
commit 2c9e13f37d
5 changed files with 84 additions and 11 deletions

View file

@ -1,3 +1,15 @@
2006-08-24 Jan Hubicka <jh@suse.cz>
* predict.c (probability_reliable_p): New predicate.
(edge_probability_reliable_p, br_prob_note_reliable_p): Likewise.
(predict_loops): Do not predict loop exit with less than 2%
probability.
* basic-block.h (edge_probability_reliable_p,
br_prob_note_reliable_p): Declare.
* ia64.h (ia64_print_operand): Do not disable on-chip branch
prediction when static predictor is not reliable.
* rs6000.c (output_cbranch): Likewise.
2006-08-23 Stuart Hastings <stuart@apple.com>
PR 28825

View file

@ -880,6 +880,8 @@ 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);
extern void remove_predictions_associated_with_edge (edge);
extern bool edge_probability_reliable_p (edge);
extern bool br_prob_note_reliable_p (rtx);
/* In flow.c */
extern void init_flow (void);

View file

@ -4656,11 +4656,13 @@ ia64_print_operand (FILE * file, rtx x, int code)
int pred_val = INTVAL (XEXP (x, 0));
/* Guess top and bottom 10% statically predicted. */
if (pred_val < REG_BR_PROB_BASE / 50)
if (pred_val < REG_BR_PROB_BASE / 50
&& br_prob_note_reliable_p (x))
which = ".spnt";
else if (pred_val < REG_BR_PROB_BASE / 2)
which = ".dpnt";
else if (pred_val < REG_BR_PROB_BASE / 100 * 98)
else if (pred_val < REG_BR_PROB_BASE / 100 * 98
|| !br_prob_note_reliable_p (x))
which = ".dptk";
else
which = ".sptk";

View file

@ -11498,7 +11498,8 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
mispredicted taken branch is more expensive than a
mispredicted not-taken branch. */
if (rs6000_always_hint
|| abs (prob) > REG_BR_PROB_BASE / 100 * 48)
|| (abs (prob) > REG_BR_PROB_BASE / 100 * 48
&& br_prob_note_reliable_p (note)))
{
if (abs (prob) > REG_BR_PROB_BASE / 20
&& ((prob > 0) ^ need_longbranch))

View file

@ -178,6 +178,45 @@ tree_predicted_by_p (basic_block bb, enum br_predictor predictor)
return false;
}
/* 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 notorously 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 reliablity information across the
CFG if we find this information useful on multiple places. */
static bool
probability_reliable_p (int prob)
{
return (profile_status == PROFILE_READ
|| (profile_status == PROFILE_GUESSED
&& (prob <= HITRATE (1) || prob >= HITRATE (99))));
}
/* Same predicate as above, working on edges. */
bool
edge_probability_reliable_p (edge e)
{
return probability_reliable_p (e->probability);
}
/* Same predicate as edge_probability_reliable_p, working on notes. */
bool
br_prob_note_reliable_p (rtx note)
{
gcc_assert (REG_NOTE_KIND (note) == REG_BR_PROB);
return probability_reliable_p (INTVAL (XEXP (note, 0)));
}
static void
predict_insn (rtx insn, enum br_predictor predictor, int probability)
{
@ -706,14 +745,31 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
/* Loop exit heuristics - predict an edge exiting the loop if the
conditional has no loop header successors as not taken. */
if (!header_found)
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest->index < NUM_FIXED_BLOCKS
|| !flow_bb_inside_loop_p (loop, e->dest))
predict_edge
(e, PRED_LOOP_EXIT,
(REG_BR_PROB_BASE
- predictor_info [(int) PRED_LOOP_EXIT].hitrate)
/ n_exits);
{
/* For loop with many exits we don't want to predict all exits
with the pretty large probability, because if all exits are
considered in row, the loop would be predicted to iterate
almost never. The code to divide probability by number of
exits is very rough. It should compute the number of exits
taken in each patch through function (not the overall number
of exits that might be a lot higher for loops with wide switch
statements in them) and compute n-th square root.
We limit the minimal probability by 2% to avoid
EDGE_PROBABILITY_RELIABLE from trusting the branch prediction
as this was causing regression in perl benchmark containing such
a wide loop. */
int probability = ((REG_BR_PROB_BASE
- predictor_info [(int) PRED_LOOP_EXIT].hitrate)
/ n_exits);
if (probability < HITRATE (2))
probability = HITRATE (2);
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->dest->index < NUM_FIXED_BLOCKS
|| !flow_bb_inside_loop_p (loop, e->dest))
predict_edge (e, PRED_LOOP_EXIT, probability);
}
}
/* Free basic blocks from get_loop_body. */