aboutsummaryrefslogtreecommitdiff
path: root/gcc/predict.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2006-08-24 00:29:14 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2006-08-23 22:29:14 +0000
commit2c9e13f37d1b4e6bb027499de9e9d5c7a5d040b5 (patch)
treef848a4c4747fe1d9158aa3bfedbaa571b97b8c80 /gcc/predict.c
parenta4d0390b4488cc159cb7389b778cc92a504f6796 (diff)
downloadgcc-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/predict.c')
-rw-r--r--gcc/predict.c72
1 files changed, 64 insertions, 8 deletions
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. */