predict.c (probability_reliable_p): New predicate.
authorJan Hubicka <jh@suse.cz>
Wed, 23 Aug 2006 22:29:14 +0000 (00:29 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 23 Aug 2006 22:29:14 +0000 (22:29 +0000)
* 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

gcc/ChangeLog
gcc/basic-block.h
gcc/config/ia64/ia64.c
gcc/config/rs6000/rs6000.c
gcc/predict.c

index a15af37cb51e3dcb69f2fd2356c9e0af567ea13b..d62c53b96232c21d832a1279ef67d23178a6877a 100644 (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
index 9be90975d46fdf8056b1fd4b76ed9ee5ffcb9e91..bc9f6650c9ad61d99b125a6ae93f1ab50c6d8afc 100644 (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);
index 14e85cae3c7b67d737569db2018f5562256905f8..d38a19a1501bd14b57008a1b0b33e7920ed08ec5 100644 (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";
index 47734a418663d95df7f690c589b9179dcdf4789d..9bae3f8b24d4b0c7947bfe836a2f5de00388128d 100644 (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))
index 7ac11f0f2ba9c0cb5c5dcef0797fd1c69731ec55..3c2775cd69a67476f2ea5ac55026e4e055ac69d0 100644 (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.  */