> > > Pat Haugen <[EMAIL PROTECTED]> wrote on 08/21/2006 01:22:25 PM: > > > Jan Hubicka <[EMAIL PROTECTED]> wrote on 08/19/2006 07:51:42 PM: > > > > > Hi, > > > this patch at least hides the ugly details within some abstraction so > we > > > can eventally go for propagating reliability information across CFG if > > > we conclude it is important. How does it work for you? > > > > > > > I like your approach, thanks. I've confirmed that the generated code no > > longer contains the mis-predicted branch hints. Will follow up with > > results from SPEC run once I get them (hosed things up for myself, so > > restarting from scratch) :-( > > > > -Pat > > > > The results with your patch mimicked the results of my initial attempt: > perlbmk improved 7% and a couple others improved a couple percent.
Happy to hear that! I've comitted the attached patch. Thank you for tracking this, very interesting, dead end of predictor machinery. Honza Index: ChangeLog =================================================================== *** ChangeLog (revision 116357) --- ChangeLog (working copy) *************** *** 1,3 **** --- 1,15 ---- + 2006-08-24 Jan Hubicka <[EMAIL PROTECTED]> + + * 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 <[EMAIL PROTECTED]> PR 28825 Index: predict.c =================================================================== *** predict.c (revision 116355) --- predict.c (working copy) *************** tree_predicted_by_p (basic_block bb, enu *** 178,183 **** --- 178,222 ---- 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) { *************** predict_loops (struct loops *loops_info, *** 706,719 **** /* 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); } /* Free basic blocks from get_loop_body. */ --- 745,775 ---- /* Loop exit heuristics - predict an edge exiting the loop if the conditional has no loop header successors as not taken. */ if (!header_found) ! { ! /* 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. */ Index: basic-block.h =================================================================== *** basic-block.h (revision 116355) --- basic-block.h (working copy) *************** extern void rtl_predict_edge (edge, enum *** 880,885 **** --- 880,887 ---- 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); Index: config/ia64/ia64.c =================================================================== *** config/ia64/ia64.c (revision 116355) --- config/ia64/ia64.c (working copy) *************** ia64_print_operand (FILE * file, rtx x, *** 4656,4666 **** int pred_val = INTVAL (XEXP (x, 0)); /* Guess top and bottom 10% statically predicted. */ ! if (pred_val < REG_BR_PROB_BASE / 50) which = ".spnt"; else if (pred_val < REG_BR_PROB_BASE / 2) which = ".dpnt"; ! else if (pred_val < REG_BR_PROB_BASE / 100 * 98) which = ".dptk"; else which = ".sptk"; --- 4656,4668 ---- int pred_val = INTVAL (XEXP (x, 0)); /* Guess top and bottom 10% statically predicted. */ ! 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 ! || !br_prob_note_reliable_p (x)) which = ".dptk"; else which = ".sptk"; Index: config/rs6000/rs6000.c =================================================================== *** config/rs6000/rs6000.c (revision 116355) --- config/rs6000/rs6000.c (working copy) *************** output_cbranch (rtx op, const char *labe *** 11498,11504 **** mispredicted taken branch is more expensive than a mispredicted not-taken branch. */ if (rs6000_always_hint ! || abs (prob) > REG_BR_PROB_BASE / 100 * 48) { if (abs (prob) > REG_BR_PROB_BASE / 20 && ((prob > 0) ^ need_longbranch)) --- 11498,11505 ---- mispredicted taken branch is more expensive than a mispredicted not-taken branch. */ if (rs6000_always_hint ! || (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))