OSDN Git Service

* config/alpha/alpha.c (alpha_sa_size): Force procedure type to
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index 41a9ee3..e3b4b83 100644 (file)
@@ -1,5 +1,5 @@
 /* Branch prediction routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -148,7 +148,9 @@ maybe_hot_count_p (gcov_type count)
 bool
 maybe_hot_bb_p (const_basic_block bb)
 {
-  return maybe_hot_count_p (bb->count) && maybe_hot_frequency_p (bb->frequency);
+  if (profile_status == PROFILE_READ)
+    return maybe_hot_count_p (bb->count);
+  return maybe_hot_frequency_p (bb->frequency);
 }
 
 /* Return true if the call can be hot.  */
@@ -166,8 +168,8 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
   if (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl)))
     return true;
   if (flag_guess_branch_prob
-      && edge->frequency < (CGRAPH_FREQ_MAX
-                           / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
+      && edge->frequency <= (CGRAPH_FREQ_BASE
+                            / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
     return false;
   return true;
 }
@@ -178,7 +180,9 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
 bool
 maybe_hot_edge_p (edge e)
 {
-  return maybe_hot_count_p (e->count) && maybe_hot_frequency_p (EDGE_FREQUENCY (e));
+  if (profile_status == PROFILE_READ)
+    return maybe_hot_count_p (e->count);
+  return maybe_hot_frequency_p (EDGE_FREQUENCY (e));
 }
 
 /* Return true in case BB is probably never executed.  */
@@ -199,7 +203,8 @@ bool
 optimize_function_for_size_p (struct function *fun)
 {
   return (optimize_size
-         || fun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED);
+         || (fun && (fun->function_frequency
+                     == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)));
 }
 
 /* Return true when current function should always be optimized for speed.  */
@@ -649,7 +654,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
   rtx *pnote;
   rtx note;
   int best_probability = PROB_EVEN;
-  int best_predictor = END_PREDICTORS;
+  enum br_predictor best_predictor = END_PREDICTORS;
   int combined_probability = REG_BR_PROB_BASE / 2;
   int d;
   bool first_match = false;
@@ -672,7 +677,8 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
     if (REG_NOTE_KIND (note) == REG_BR_PRED)
       {
-       int predictor = INTVAL (XEXP (XEXP (note, 0), 0));
+       enum br_predictor predictor = ((enum br_predictor)
+                                      INTVAL (XEXP (XEXP (note, 0), 0)));
        int probability = INTVAL (XEXP (XEXP (note, 0), 1));
 
        found = true;
@@ -718,7 +724,8 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
     {
       if (REG_NOTE_KIND (*pnote) == REG_BR_PRED)
        {
-         int predictor = INTVAL (XEXP (XEXP (*pnote, 0), 0));
+         enum br_predictor predictor = ((enum br_predictor)
+                                        INTVAL (XEXP (XEXP (*pnote, 0), 0)));
          int probability = INTVAL (XEXP (XEXP (*pnote, 0), 1));
 
          dump_prediction (dump_file, predictor, probability, bb,
@@ -760,7 +767,7 @@ static void
 combine_predictions_for_bb (basic_block bb)
 {
   int best_probability = PROB_EVEN;
-  int best_predictor = END_PREDICTORS;
+  enum br_predictor best_predictor = END_PREDICTORS;
   int combined_probability = REG_BR_PROB_BASE / 2;
   int d;
   bool first_match = false;
@@ -808,15 +815,40 @@ combine_predictions_for_bb (basic_block bb)
         by predictor with smallest index.  */
       for (pred = (struct edge_prediction *) *preds; pred; pred = pred->ep_next)
        {
-         int predictor = pred->ep_predictor;
+         enum br_predictor predictor = pred->ep_predictor;
          int probability = pred->ep_probability;
 
          if (pred->ep_edge != first)
            probability = REG_BR_PROB_BASE - probability;
 
          found = true;
+         /* First match heuristics would be widly confused if we predicted
+            both directions.  */
          if (best_predictor > predictor)
-           best_probability = probability, best_predictor = predictor;
+           {
+              struct edge_prediction *pred2;
+             int prob = probability;
+
+              for (pred2 = (struct edge_prediction *) *preds; pred2; pred2 = pred2->ep_next)
+              if (pred2 != pred && pred2->ep_predictor == pred->ep_predictor)
+                {
+                  int probability2 = pred->ep_probability;
+
+                  if (pred2->ep_edge != first)
+                    probability2 = REG_BR_PROB_BASE - probability2;
+
+                  if ((probability < REG_BR_PROB_BASE / 2) != 
+                      (probability2 < REG_BR_PROB_BASE / 2))
+                    break;
+
+                  /* If the same predictor later gave better result, go for it! */
+                  if ((probability >= REG_BR_PROB_BASE / 2 && (probability2 > probability))
+                      || (probability <= REG_BR_PROB_BASE / 2 && (probability2 < probability)))
+                    prob = probability2;
+                }
+             if (!pred2)
+               best_probability = prob, best_predictor = predictor;
+           }
 
          d = (combined_probability * probability
               + (REG_BR_PROB_BASE - combined_probability)
@@ -858,7 +890,7 @@ combine_predictions_for_bb (basic_block bb)
     {
       for (pred = (struct edge_prediction *) *preds; pred; pred = pred->ep_next)
        {
-         int predictor = pred->ep_predictor;
+         enum br_predictor predictor = pred->ep_predictor;
          int probability = pred->ep_probability;
 
          if (pred->ep_edge != EDGE_SUCC (bb, 0))
@@ -1516,6 +1548,16 @@ static void
 tree_bb_level_predictions (void)
 {
   basic_block bb;
+  bool has_return_edges = false;
+  edge e;
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+    if (!(e->flags & (EDGE_ABNORMAL | EDGE_FAKE | EDGE_EH)))
+      {
+        has_return_edges = true;
+       break;
+      }
 
   apply_return_prediction ();
 
@@ -1530,7 +1572,8 @@ tree_bb_level_predictions (void)
 
          if (is_gimple_call (stmt))
            {
-             if (gimple_call_flags (stmt) & ECF_NORETURN)
+             if ((gimple_call_flags (stmt) & ECF_NORETURN)
+                 && has_return_edges)
                predict_paths_leading_to (bb, PRED_NORETURN,
                                          NOT_TAKEN);
              decl = gimple_call_fndecl (stmt);
@@ -1594,6 +1637,7 @@ tree_estimate_probability (void)
     {
       edge e;
       edge_iterator ei;
+      gimple last;
 
       FOR_EACH_EDGE (e, ei, bb->succs)
        {
@@ -1616,7 +1660,8 @@ tree_estimate_probability (void)
              && e->dest != EXIT_BLOCK_PTR
              && single_succ_p (e->dest)
              && single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
-             && gimple_code (last_stmt (e->dest)) == GIMPLE_RETURN)
+             && (last = last_stmt (e->dest)) != NULL
+             && gimple_code (last) == GIMPLE_RETURN)
            {
              edge e1;
              edge_iterator ei1;
@@ -2009,7 +2054,7 @@ estimate_bb_frequencies (void)
   basic_block bb;
   sreal freq_max;
 
-  if (!flag_branch_probabilities || !counts_to_freqs ())
+  if (profile_status != PROFILE_READ || !counts_to_freqs ())
     {
       static int real_values_initialized = 0;
 
@@ -2142,7 +2187,7 @@ build_predict_expr (enum br_predictor predictor, enum prediction taken)
 {
   tree t = build1 (PREDICT_EXPR, void_type_node,
                   build_int_cst (NULL, predictor));
-  PREDICT_EXPR_OUTCOME (t) = taken;
+  SET_PREDICT_EXPR_OUTCOME (t, taken);
   return t;
 }
 
@@ -2175,7 +2220,7 @@ struct gimple_opt_pass pass_strip_predict_hints =
 {
  {
   GIMPLE_PASS,
-  "",                                  /* name */
+  NULL,                                        /* name */
   NULL,                                        /* gate */
   strip_predict_hints,                 /* execute */
   NULL,                                        /* sub */