OSDN Git Service

* doc/invoke.texi (RS/6000 and PowerPC Options): Add -m to the
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index c59e57b..9030763 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 notoriously 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 reliability 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.  */
@@ -826,85 +882,6 @@ bb_estimate_probability_locally (basic_block bb)
       }
 }
 
-/* Statically estimate the probability that a branch will be taken and produce
-   estimated profile.  When profile feedback is present never executed portions
-   of function gets estimated.  */
-
-void
-estimate_probability (struct loops *loops_info)
-{
-  basic_block bb;
-
-  connect_infinite_loops_to_exit ();
-  calculate_dominance_info (CDI_DOMINATORS);
-  calculate_dominance_info (CDI_POST_DOMINATORS);
-
-  predict_loops (loops_info, true);
-
-  iv_analysis_done ();
-
-  /* Attempt to predict conditional jumps using a number of heuristics.  */
-  FOR_EACH_BB (bb)
-    {
-      rtx last_insn = BB_END (bb);
-      edge e;
-      edge_iterator ei;
-
-      if (! can_predict_insn_p (last_insn))
-       continue;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       {
-         /* Predict early returns to be probable, as we've already taken
-            care for error returns and other are often used for fast paths
-            trought function.  */
-         if ((e->dest == EXIT_BLOCK_PTR
-              || (single_succ_p (e->dest)
-                  && single_succ (e->dest) == EXIT_BLOCK_PTR))
-              && !predicted_by_p (bb, PRED_NULL_RETURN)
-              && !predicted_by_p (bb, PRED_CONST_RETURN)
-              && !predicted_by_p (bb, PRED_NEGATIVE_RETURN)
-              && !last_basic_block_p (e->dest))
-           predict_edge_def (e, PRED_EARLY_RETURN, TAKEN);
-
-         /* Look for block we are guarding (i.e. we dominate it,
-            but it doesn't postdominate us).  */
-         if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
-             && dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
-             && !dominated_by_p (CDI_POST_DOMINATORS, e->src, e->dest))
-           {
-             rtx insn;
-
-             /* The call heuristic claims that a guarded function call
-                is improbable.  This is because such calls are often used
-                to signal exceptional situations such as printing error
-                messages.  */
-             for (insn = BB_HEAD (e->dest); insn != NEXT_INSN (BB_END (e->dest));
-                  insn = NEXT_INSN (insn))
-               if (CALL_P (insn)
-                   /* Constant and pure calls are hardly used to signalize
-                      something exceptional.  */
-                   && ! CONST_OR_PURE_CALL_P (insn))
-                 {
-                   predict_edge_def (e, PRED_CALL, NOT_TAKEN);
-                   break;
-                 }
-           }
-       }
-      bb_estimate_probability_locally (bb);
-    }
-
-  /* Attach the combined probability to each conditional jump.  */
-  FOR_EACH_BB (bb)
-    combine_predictions_for_insn (BB_END (bb), bb);
-
-  remove_fake_edges ();
-  estimate_bb_frequencies (loops_info);
-  free_dominance_info (CDI_POST_DOMINATORS);
-  if (profile_status == PROFILE_ABSENT)
-    profile_status = PROFILE_GUESSED;
-}
-
 /* Set edge->probability for each successor edge of BB.  */
 void
 guess_outgoing_edge_probabilities (basic_block bb)
@@ -1337,7 +1314,7 @@ tree_estimate_probability (void)
        {
          /* Predict early returns to be probable, as we've already taken
             care for error returns and other cases are often used for
-            fast paths trought function.  */
+            fast paths through function.  */
          if (e->dest == EXIT_BLOCK_PTR
              && TREE_CODE (last_stmt (bb)) == RETURN_EXPR
              && !single_pred_p (bb))