diff options
author | Jan Hubicka <jh@suse.cz> | 2006-08-24 00:29:14 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2006-08-23 22:29:14 +0000 |
commit | 2c9e13f37d1b4e6bb027499de9e9d5c7a5d040b5 (patch) | |
tree | f848a4c4747fe1d9158aa3bfedbaa571b97b8c80 /gcc | |
parent | a4d0390b4488cc159cb7389b778cc92a504f6796 (diff) | |
download | gcc-2c9e13f37d1b4e6bb027499de9e9d5c7a5d040b5.zip gcc-2c9e13f37d1b4e6bb027499de9e9d5c7a5d040b5.tar.gz gcc-2c9e13f37d1b4e6bb027499de9e9d5c7a5d040b5.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/basic-block.h | 2 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 3 | ||||
-rw-r--r-- | gcc/predict.c | 72 |
5 files changed, 84 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a15af37..d62c53b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 9be9097..bc9f665 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -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); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 14e85ca..d38a19a 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -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"; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 47734a4..9bae3f8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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)) diff --git a/gcc/predict.c b/gcc/predict.c index 7ac11f0..3c2775c 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -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. */ |