OSDN Git Service

2007-08-17 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index 4b5344b..dbdfce4 100644 (file)
@@ -1,12 +1,12 @@
 /* Branch prediction routines for the GNU compiler.
 /* Branch prediction routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* References:
 
 
 /* References:
 
@@ -60,6 +59,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "timevar.h"
 #include "tree-scalar-evolution.h"
 #include "cfgloop.h"
 #include "timevar.h"
 #include "tree-scalar-evolution.h"
 #include "cfgloop.h"
+#include "pointer-set.h"
 
 /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
                   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
 
 /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
                   1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX.  */
@@ -75,11 +75,9 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
 static void combine_predictions_for_insn (rtx, basic_block);
 static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
 static void predict_paths_leading_to (basic_block, int *, enum br_predictor, enum prediction);
 static void combine_predictions_for_insn (rtx, basic_block);
 static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
 static void predict_paths_leading_to (basic_block, int *, enum br_predictor, enum prediction);
-static bool last_basic_block_p (basic_block);
 static void compute_function_frequency (void);
 static void choose_function_section (void);
 static void compute_function_frequency (void);
 static void choose_function_section (void);
-static bool can_predict_insn_p (rtx);
-static void estimate_bb_frequencies (void);
+static bool can_predict_insn_p (const_rtx);
 
 /* Information we hold about each branch predictor.
    Filled using information from predict.def.  */
 
 /* Information we hold about each branch predictor.
    Filled using information from predict.def.  */
@@ -113,12 +111,19 @@ static const struct predictor_info predictor_info[]= {
    for maximal performance.  */
 
 bool
    for maximal performance.  */
 
 bool
-maybe_hot_bb_p (basic_block bb)
+maybe_hot_bb_p (const_basic_block bb)
 {
   if (profile_info && flag_branch_probabilities
       && (bb->count
          < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return false;
 {
   if (profile_info && flag_branch_probabilities
       && (bb->count
          < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return false;
+  if (!profile_info || !flag_branch_probabilities)
+    {
+      if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+        return false;
+      if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
+        return true;
+    }
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return false;
   return true;
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return false;
   return true;
@@ -127,12 +132,15 @@ maybe_hot_bb_p (basic_block bb)
 /* Return true in case BB is cold and should be optimized for size.  */
 
 bool
 /* Return true in case BB is cold and should be optimized for size.  */
 
 bool
-probably_cold_bb_p (basic_block bb)
+probably_cold_bb_p (const_basic_block bb)
 {
   if (profile_info && flag_branch_probabilities
       && (bb->count
          < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return true;
 {
   if (profile_info && flag_branch_probabilities
       && (bb->count
          < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return true;
+  if ((!profile_info || !flag_branch_probabilities)
+      && cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+    return true;
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return true;
   return false;
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return true;
   return false;
@@ -140,10 +148,13 @@ probably_cold_bb_p (basic_block bb)
 
 /* Return true in case BB is probably never executed.  */
 bool
 
 /* Return true in case BB is probably never executed.  */
 bool
-probably_never_executed_bb_p (basic_block bb)
+probably_never_executed_bb_p (const_basic_block bb)
 {
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
 {
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
+  if ((!profile_info || !flag_branch_probabilities)
+      && cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+    return true;
   return false;
 }
 
   return false;
 }
 
@@ -163,6 +174,11 @@ rtl_predicted_by_p (basic_block bb, enum br_predictor predictor)
   return false;
 }
 
   return false;
 }
 
+/* This map contains for a basic block the list of predictions for the
+   outgoing edges.  */
+
+static struct pointer_map_t *bb_predictions;
+
 /* Return true if the one of outgoing edges is already predicted by
    PREDICTOR.  */
 
 /* Return true if the one of outgoing edges is already predicted by
    PREDICTOR.  */
 
@@ -170,7 +186,12 @@ bool
 tree_predicted_by_p (basic_block bb, enum br_predictor predictor)
 {
   struct edge_prediction *i;
 tree_predicted_by_p (basic_block bb, enum br_predictor predictor)
 {
   struct edge_prediction *i;
-  for (i = bb->predictions; i; i = i->ep_next)
+  void **preds = pointer_map_contains (bb_predictions, bb);
+
+  if (!preds)
+    return false;
+  
+  for (i = *preds; i; i = i->ep_next)
     if (i->ep_predictor == predictor)
       return true;
   return false;
     if (i->ep_predictor == predictor)
       return true;
   return false;
@@ -202,14 +223,14 @@ probability_reliable_p (int prob)
 
 /* Same predicate as above, working on edges.  */
 bool
 
 /* Same predicate as above, working on edges.  */
 bool
-edge_probability_reliable_p (edge e)
+edge_probability_reliable_p (const_edge e)
 {
   return probability_reliable_p (e->probability);
 }
 
 /* Same predicate as edge_probability_reliable_p, working on notes.  */
 bool
 {
   return probability_reliable_p (e->probability);
 }
 
 /* Same predicate as edge_probability_reliable_p, working on notes.  */
 bool
-br_prob_note_reliable_p (rtx note)
+br_prob_note_reliable_p (const_rtx note)
 {
   gcc_assert (REG_NOTE_KIND (note) == REG_BR_PROB);
   return probability_reliable_p (INTVAL (XEXP (note, 0)));
 {
   gcc_assert (REG_NOTE_KIND (note) == REG_BR_PROB);
   return probability_reliable_p (INTVAL (XEXP (note, 0)));
@@ -272,10 +293,11 @@ tree_predict_edge (edge e, enum br_predictor predictor, int probability)
   if ((e->src != ENTRY_BLOCK_PTR && EDGE_COUNT (e->src->succs) > 1)
       && flag_guess_branch_prob && optimize)
     {
   if ((e->src != ENTRY_BLOCK_PTR && EDGE_COUNT (e->src->succs) > 1)
       && flag_guess_branch_prob && optimize)
     {
-      struct edge_prediction *i = ggc_alloc (sizeof (struct edge_prediction));
+      struct edge_prediction *i = XNEW (struct edge_prediction);
+      void **preds = pointer_map_insert (bb_predictions, e->src);
 
 
-      i->ep_next = e->src->predictions;
-      e->src->predictions = i;
+      i->ep_next = *preds;
+      *preds = i;
       i->ep_probability = probability;
       i->ep_predictor = predictor;
       i->ep_edge = e;
       i->ep_probability = probability;
       i->ep_predictor = predictor;
       i->ep_edge = e;
@@ -287,24 +309,56 @@ tree_predict_edge (edge e, enum br_predictor predictor, int probability)
 void
 remove_predictions_associated_with_edge (edge e)
 {
 void
 remove_predictions_associated_with_edge (edge e)
 {
-  if (e->src->predictions)
+  void **preds;
+  
+  if (!bb_predictions)
+    return;
+
+  preds = pointer_map_contains (bb_predictions, e->src);
+
+  if (preds)
     {
     {
-      struct edge_prediction **prediction = &e->src->predictions;
+      struct edge_prediction **prediction = (struct edge_prediction **) preds;
+      struct edge_prediction *next;
+
       while (*prediction)
        {
          if ((*prediction)->ep_edge == e)
       while (*prediction)
        {
          if ((*prediction)->ep_edge == e)
-           *prediction = (*prediction)->ep_next;
+           {
+             next = (*prediction)->ep_next;
+             free (*prediction);
+             *prediction = next;
+           }
          else
            prediction = &((*prediction)->ep_next);
        }
     }
 }
 
          else
            prediction = &((*prediction)->ep_next);
        }
     }
 }
 
+/* Clears the list of predictions stored for BB.  */
+
+static void
+clear_bb_predictions (basic_block bb)
+{
+  void **preds = pointer_map_contains (bb_predictions, bb);
+  struct edge_prediction *pred, *next;
+
+  if (!preds)
+    return;
+
+  for (pred = *preds; pred; pred = next)
+    {
+      next = pred->ep_next;
+      free (pred);
+    }
+  *preds = NULL;
+}
+
 /* Return true when we can store prediction on insn INSN.
    At the moment we represent predictions only on conditional
    jumps, not at computed jump or other complicated cases.  */
 static bool
 /* Return true when we can store prediction on insn INSN.
    At the moment we represent predictions only on conditional
    jumps, not at computed jump or other complicated cases.  */
 static bool
-can_predict_insn_p (rtx insn)
+can_predict_insn_p (const_rtx insn)
 {
   return (JUMP_P (insn)
          && any_condjump_p (insn)
 {
   return (JUMP_P (insn)
          && any_condjump_p (insn)
@@ -527,6 +581,7 @@ combine_predictions_for_bb (basic_block bb)
   int nedges = 0;
   edge e, first = NULL, second = NULL;
   edge_iterator ei;
   int nedges = 0;
   edge e, first = NULL, second = NULL;
   edge_iterator ei;
+  void **preds;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
     if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
 
   FOR_EACH_EDGE (e, ei, bb->succs)
     if (!(e->flags & (EDGE_EH | EDGE_FAKE)))
@@ -548,7 +603,7 @@ combine_predictions_for_bb (basic_block bb)
     {
       if (!bb->count)
        set_even_probabilities (bb);
     {
       if (!bb->count)
        set_even_probabilities (bb);
-      bb->predictions = NULL;
+      clear_bb_predictions (bb);
       if (dump_file)
        fprintf (dump_file, "%i edges in bb %i predicted to even probabilities\n",
                 nedges, bb->index);
       if (dump_file)
        fprintf (dump_file, "%i edges in bb %i predicted to even probabilities\n",
                 nedges, bb->index);
@@ -558,31 +613,36 @@ combine_predictions_for_bb (basic_block bb)
   if (dump_file)
     fprintf (dump_file, "Predictions for bb %i\n", bb->index);
 
   if (dump_file)
     fprintf (dump_file, "Predictions for bb %i\n", bb->index);
 
-  /* We implement "first match" heuristics and use probability guessed
-     by predictor with smallest index.  */
-  for (pred = bb->predictions; pred; pred = pred->ep_next)
+  preds = pointer_map_contains (bb_predictions, bb);
+  if (preds)
     {
     {
-      int predictor = pred->ep_predictor;
-      int probability = pred->ep_probability;
+      /* We implement "first match" heuristics and use probability guessed
+        by predictor with smallest index.  */
+      for (pred = *preds; pred; pred = pred->ep_next)
+       {
+         int predictor = pred->ep_predictor;
+         int probability = pred->ep_probability;
 
 
-      if (pred->ep_edge != first)
-       probability = REG_BR_PROB_BASE - probability;
+         if (pred->ep_edge != first)
+           probability = REG_BR_PROB_BASE - probability;
 
 
-      found = true;
-      if (best_predictor > predictor)
-       best_probability = probability, best_predictor = predictor;
+         found = true;
+         if (best_predictor > predictor)
+           best_probability = probability, best_predictor = predictor;
 
 
-      d = (combined_probability * probability
-          + (REG_BR_PROB_BASE - combined_probability)
-          * (REG_BR_PROB_BASE - probability));
+         d = (combined_probability * probability
+              + (REG_BR_PROB_BASE - combined_probability)
+              * (REG_BR_PROB_BASE - probability));
 
 
-      /* Use FP math to avoid overflows of 32bit integers.  */
-      if (d == 0)
-       /* If one probability is 0% and one 100%, avoid division by zero.  */
-       combined_probability = REG_BR_PROB_BASE / 2;
-      else
-       combined_probability = (((double) combined_probability) * probability
-                               * REG_BR_PROB_BASE / d + 0.5);
+         /* Use FP math to avoid overflows of 32bit integers.  */
+         if (d == 0)
+           /* If one probability is 0% and one 100%, avoid division by zero.  */
+           combined_probability = REG_BR_PROB_BASE / 2;
+         else
+           combined_probability = (((double) combined_probability)
+                                   * probability
+                                   * REG_BR_PROB_BASE / d + 0.5);
+       }
     }
 
   /* Decide which heuristic to use.  In case we didn't match anything,
     }
 
   /* Decide which heuristic to use.  In case we didn't match anything,
@@ -606,17 +666,20 @@ combine_predictions_for_bb (basic_block bb)
     combined_probability = best_probability;
   dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
 
     combined_probability = best_probability;
   dump_prediction (dump_file, PRED_COMBINED, combined_probability, bb, true);
 
-  for (pred = bb->predictions; pred; pred = pred->ep_next)
+  if (preds)
     {
     {
-      int predictor = pred->ep_predictor;
-      int probability = pred->ep_probability;
+      for (pred = *preds; pred; pred = pred->ep_next)
+       {
+         int predictor = pred->ep_predictor;
+         int probability = pred->ep_probability;
 
 
-      if (pred->ep_edge != EDGE_SUCC (bb, 0))
-       probability = REG_BR_PROB_BASE - probability;
-      dump_prediction (dump_file, predictor, probability, bb,
-                      !first_match || best_predictor == predictor);
+         if (pred->ep_edge != EDGE_SUCC (bb, 0))
+           probability = REG_BR_PROB_BASE - probability;
+         dump_prediction (dump_file, predictor, probability, bb,
+                          !first_match || best_predictor == predictor);
+       }
     }
     }
-  bb->predictions = NULL;
+  clear_bb_predictions (bb);
 
   if (!bb->count)
     {
 
   if (!bb->count)
     {
@@ -630,17 +693,17 @@ combine_predictions_for_bb (basic_block bb)
 static void
 predict_loops (void)
 {
 static void
 predict_loops (void)
 {
-  unsigned i;
+  loop_iterator li;
+  struct loop *loop;
 
   scev_initialize ();
 
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
 
   scev_initialize ();
 
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
-  for (i = 1; i < current_loops->num; i++)
+  FOR_EACH_LOOP (li, loop, 0)
     {
       basic_block bb, *bbs;
       unsigned j, n_exits;
     {
       basic_block bb, *bbs;
       unsigned j, n_exits;
-      struct loop *loop = current_loops->parray[i];
       VEC (edge, heap) *exits;
       struct tree_niter_desc niter_desc;
       edge ex;
       VEC (edge, heap) *exits;
       struct tree_niter_desc niter_desc;
       edge ex;
@@ -651,6 +714,10 @@ predict_loops (void)
       for (j = 0; VEC_iterate (edge, exits, j, ex); j++)
        {
          tree niter = NULL;
       for (j = 0; VEC_iterate (edge, exits, j, ex); j++)
        {
          tree niter = NULL;
+         HOST_WIDE_INT nitercst;
+         int max = PARAM_VALUE (PARAM_MAX_PREDICTED_ITERATIONS);
+         int probability;
+         enum br_predictor predictor;
 
          if (number_of_iterations_exit (loop, ex, &niter_desc, false))
            niter = niter_desc.niter;
 
          if (number_of_iterations_exit (loop, ex, &niter_desc, false))
            niter = niter_desc.niter;
@@ -659,21 +726,31 @@ predict_loops (void)
 
          if (TREE_CODE (niter) == INTEGER_CST)
            {
 
          if (TREE_CODE (niter) == INTEGER_CST)
            {
-             int probability;
-             int max = PARAM_VALUE (PARAM_MAX_PREDICTED_ITERATIONS);
              if (host_integerp (niter, 1)
              if (host_integerp (niter, 1)
-                 && tree_int_cst_lt (niter,
-                                     build_int_cstu (NULL_TREE, max - 1)))
-               {
-                 HOST_WIDE_INT nitercst = tree_low_cst (niter, 1) + 1;
-                 probability = ((REG_BR_PROB_BASE + nitercst / 2)
-                                / nitercst);
-               }
+                 && compare_tree_int (niter, max-1) == -1)
+               nitercst = tree_low_cst (niter, 1) + 1;
              else
              else
-               probability = ((REG_BR_PROB_BASE + max / 2) / max);
+               nitercst = max;
+             predictor = PRED_LOOP_ITERATIONS;
+           }
+         /* If we have just one exit and we can derive some information about
+            the number of iterations of the loop from the statements inside
+            the loop, use it to predict this exit.  */
+         else if (n_exits == 1)
+           {
+             nitercst = estimated_loop_iterations_int (loop, false);
+             if (nitercst < 0)
+               continue;
+             if (nitercst > max)
+               nitercst = max;
 
 
-             predict_edge (ex, PRED_LOOP_ITERATIONS, probability);
+             predictor = PRED_LOOP_ITERATIONS_GUESSED;
            }
            }
+         else
+           continue;
+
+         probability = ((REG_BR_PROB_BASE + nitercst / 2) / nitercst);
+         predict_edge (ex, predictor, probability);
        }
       VEC_free (edge, heap, exits);
 
        }
       VEC_free (edge, heap, exits);
 
@@ -708,7 +785,11 @@ predict_loops (void)
 
          /* Loop exit heuristics - predict an edge exiting the loop if the
             conditional has no loop header successors as not taken.  */
 
          /* Loop exit heuristics - predict an edge exiting the loop if the
             conditional has no loop header successors as not taken.  */
-         if (!header_found)
+         if (!header_found
+             /* If we already used more reliable loop exit predictors, do not
+                bother with PRED_LOOP_EXIT.  */
+             && !predicted_by_p (bb, PRED_LOOP_ITERATIONS_GUESSED)
+             && !predicted_by_p (bb, PRED_LOOP_ITERATIONS))
            {
              /* For loop with many exits we don't want to predict all exits
                 with the pretty large probability, because if all exits are
            {
              /* For loop with many exits we don't want to predict all exits
                 with the pretty large probability, because if all exits are
@@ -915,16 +996,14 @@ expr_expected_value (tree expr, bitmap visited)
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
          && DECL_FUNCTION_CODE (decl) == BUILT_IN_EXPECT)
        {
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
          && DECL_FUNCTION_CODE (decl) == BUILT_IN_EXPECT)
        {
-         tree arglist = TREE_OPERAND (expr, 1);
          tree val;
 
          tree val;
 
-         if (arglist == NULL_TREE
-             || TREE_CHAIN (arglist) == NULL_TREE)
-           return NULL; 
-         val = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1)));
+         if (call_expr_nargs (expr) != 2)
+           return NULL;
+         val = CALL_EXPR_ARG (expr, 0);
          if (TREE_CONSTANT (val))
            return val;
          if (TREE_CONSTANT (val))
            return val;
-         return TREE_VALUE (TREE_CHAIN (TREE_OPERAND (expr, 1)));
+         return CALL_EXPR_ARG (expr, 1);
        }
     }
   if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr))
        }
     }
   if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr))
@@ -967,17 +1046,17 @@ strip_builtin_expect (void)
        {
          tree stmt = bsi_stmt (bi);
          tree fndecl;
        {
          tree stmt = bsi_stmt (bi);
          tree fndecl;
-         tree arglist;
+         tree call;
 
          if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
 
          if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
-             && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == CALL_EXPR
-             && (fndecl = get_callee_fndecl (GIMPLE_STMT_OPERAND (stmt, 1)))
+             && (call = GIMPLE_STMT_OPERAND (stmt, 1))
+             && TREE_CODE (call) == CALL_EXPR
+             && (fndecl = get_callee_fndecl (call))
              && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
              && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
-             && (arglist = TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 1))
-             && TREE_CHAIN (arglist))
+             && call_expr_nargs (call) == 2)
            {
            {
-             GIMPLE_STMT_OPERAND (stmt, 1) = TREE_VALUE (arglist);
+             GIMPLE_STMT_OPERAND (stmt, 1) = CALL_EXPR_ARG (call, 0);
              update_stmt (stmt);
            }
        }
              update_stmt (stmt);
            }
        }
@@ -1137,7 +1216,7 @@ return_prediction (tree val, enum prediction *prediction)
          && (!integer_zerop (val) && !integer_onep (val)))
        {
          *prediction = TAKEN;
          && (!integer_zerop (val) && !integer_onep (val)))
        {
          *prediction = TAKEN;
-         return PRED_NEGATIVE_RETURN;
+         return PRED_CONST_RETURN;
        }
     }
   return PRED_NO_PREDICTION;
        }
     }
   return PRED_NO_PREDICTION;
@@ -1160,7 +1239,8 @@ apply_return_prediction (int *heads)
   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
     {
       return_stmt = last_stmt (e->src);
   FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
     {
       return_stmt = last_stmt (e->src);
-      if (TREE_CODE (return_stmt) == RETURN_EXPR)
+      if (return_stmt
+         && TREE_CODE (return_stmt) == RETURN_EXPR)
        break;
     }
   if (!e)
        break;
     }
   if (!e)
@@ -1220,6 +1300,7 @@ tree_bb_level_predictions (void)
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        {
          tree stmt = bsi_stmt (bsi);
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        {
          tree stmt = bsi_stmt (bsi);
+         tree decl;
          switch (TREE_CODE (stmt))
            {
              case GIMPLE_MODIFY_STMT:
          switch (TREE_CODE (stmt))
            {
              case GIMPLE_MODIFY_STMT:
@@ -1234,6 +1315,12 @@ call_expr:;
                if (call_expr_flags (stmt) & ECF_NORETURN)
                  predict_paths_leading_to (bb, heads, PRED_NORETURN,
                                            NOT_TAKEN);
                if (call_expr_flags (stmt) & ECF_NORETURN)
                  predict_paths_leading_to (bb, heads, PRED_NORETURN,
                                            NOT_TAKEN);
+               decl = get_callee_fndecl (stmt);
+               if (decl
+                   && lookup_attribute ("cold",
+                                        DECL_ATTRIBUTES (decl)))
+                 predict_paths_leading_to (bb, heads, PRED_COLD_FUNCTION,
+                                           NOT_TAKEN);
                break;
              default:
                break;
                break;
              default:
                break;
@@ -1244,6 +1331,20 @@ call_expr:;
   free (heads);
 }
 
   free (heads);
 }
 
+#ifdef ENABLE_CHECKING
+
+/* Callback for pointer_map_traverse, asserts that the pointer map is
+   empty.  */
+
+static bool
+assert_is_empty (const void *key ATTRIBUTE_UNUSED, void **value,
+                void *data ATTRIBUTE_UNUSED)
+{
+  gcc_assert (!*value);
+  return false;
+}
+#endif
+
 /* Predict branch probabilities and estimate profile of the tree CFG.  */
 static unsigned int
 tree_estimate_probability (void)
 /* Predict branch probabilities and estimate profile of the tree CFG.  */
 static unsigned int
 tree_estimate_probability (void)
@@ -1251,18 +1352,22 @@ tree_estimate_probability (void)
   basic_block bb;
 
   loop_optimizer_init (0);
   basic_block bb;
 
   loop_optimizer_init (0);
-  if (current_loops && dump_file && (dump_flags & TDF_DETAILS))
+  if (dump_file && (dump_flags & TDF_DETAILS))
     flow_loops_dump (dump_file, NULL, 0);
 
   add_noreturn_fake_exit_edges ();
   connect_infinite_loops_to_exit ();
     flow_loops_dump (dump_file, NULL, 0);
 
   add_noreturn_fake_exit_edges ();
   connect_infinite_loops_to_exit ();
-  calculate_dominance_info (CDI_DOMINATORS);
+  /* We use loop_niter_by_eval, which requires that the loops have
+     preheaders.  */
+  create_preheaders (CP_SIMPLE_PREHEADERS);
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
   calculate_dominance_info (CDI_POST_DOMINATORS);
 
+  bb_predictions = pointer_map_create ();
   tree_bb_level_predictions ();
 
   mark_irreducible_loops ();
   tree_bb_level_predictions ();
 
   mark_irreducible_loops ();
-  if (current_loops)
+  record_loop_exits ();
+  if (number_of_loops () > 1)
     predict_loops ();
 
   FOR_EACH_BB (bb)
     predict_loops ();
 
   FOR_EACH_BB (bb)
@@ -1274,20 +1379,41 @@ 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
        {
          /* Predict early returns to be probable, as we've already taken
             care for error returns and other cases are often used for
-            fast paths through function.  */
-         if (e->dest == EXIT_BLOCK_PTR
-             && TREE_CODE (last_stmt (bb)) == RETURN_EXPR
-             && !single_pred_p (bb))
+            fast paths through function. 
+
+            Since we've already removed the return statements, we are
+            looking for CFG like:
+
+              if (conditional)
+                {
+                  ..
+                  goto return_block
+                }
+              some other blocks
+            return_block:
+              return_stmt.  */
+         if (e->dest != bb->next_bb
+             && e->dest != EXIT_BLOCK_PTR
+             && single_succ_p (e->dest)
+             && single_succ_edge (e->dest)->dest == EXIT_BLOCK_PTR
+             && TREE_CODE (last_stmt (e->dest)) == RETURN_EXPR)
            {
              edge e1;
              edge_iterator ei1;
 
            {
              edge e1;
              edge_iterator ei1;
 
-             FOR_EACH_EDGE (e1, ei1, bb->preds)
-               if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
-                   && !predicted_by_p (e1->src, PRED_CONST_RETURN)
-                   && !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN)
-                   && !last_basic_block_p (e1->src))
-                 predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
+             if (single_succ_p (bb))
+               {
+                 FOR_EACH_EDGE (e1, ei1, bb->preds)
+                   if (!predicted_by_p (e1->src, PRED_NULL_RETURN)
+                       && !predicted_by_p (e1->src, PRED_CONST_RETURN)
+                       && !predicted_by_p (e1->src, PRED_NEGATIVE_RETURN))
+                     predict_edge_def (e1, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
+               }
+              else
+               if (!predicted_by_p (e->src, PRED_NULL_RETURN)
+                   && !predicted_by_p (e->src, PRED_CONST_RETURN)
+                   && !predicted_by_p (e->src, PRED_NEGATIVE_RETURN))
+                 predict_edge_def (e, PRED_TREE_EARLY_RETURN, NOT_TAKEN);
            }
 
          /* Look for block we are guarding (ie we dominate it,
            }
 
          /* Look for block we are guarding (ie we dominate it,
@@ -1325,6 +1451,12 @@ tree_estimate_probability (void)
   FOR_EACH_BB (bb)
     combine_predictions_for_bb (bb);
 
   FOR_EACH_BB (bb)
     combine_predictions_for_bb (bb);
 
+#ifdef ENABLE_CHECKING
+  pointer_map_traverse (bb_predictions, assert_is_empty, NULL);
+#endif
+  pointer_map_destroy (bb_predictions);
+  bb_predictions = NULL;
+
   strip_builtin_expect ();
   estimate_bb_frequencies ();
   free_dominance_info (CDI_POST_DOMINATORS);
   strip_builtin_expect ();
   estimate_bb_frequencies ();
   free_dominance_info (CDI_POST_DOMINATORS);
@@ -1337,20 +1469,6 @@ tree_estimate_probability (void)
   return 0;
 }
 \f
   return 0;
 }
 \f
-/* Check whether this is the last basic block of function.  Commonly
-   there is one extra common cleanup block.  */
-static bool
-last_basic_block_p (basic_block bb)
-{
-  if (bb == EXIT_BLOCK_PTR)
-    return false;
-
-  return (bb->next_bb == EXIT_BLOCK_PTR
-         || (bb->next_bb->next_bb == EXIT_BLOCK_PTR
-             && single_succ_p (bb)
-             && single_succ (bb)->next_bb == EXIT_BLOCK_PTR));
-}
-
 /* Sets branch probabilities according to PREDiction and
    FLAGS. HEADS[bb->index] should be index of basic block in that we
    need to alter branch predictions (i.e. the first of our dominators
 /* Sets branch probabilities according to PREDiction and
    FLAGS. HEADS[bb->index] should be index of basic block in that we
    need to alter branch predictions (i.e. the first of our dominators
@@ -1612,7 +1730,7 @@ estimate_loops (void)
   basic_block bb;
 
   /* Start by estimating the frequencies in the loops.  */
   basic_block bb;
 
   /* Start by estimating the frequencies in the loops.  */
-  if (current_loops)
+  if (number_of_loops () > 1)
     estimate_loops_at_level (current_loops->tree_root->inner);
 
   /* Now propagate the frequencies through all the blocks.  */
     estimate_loops_at_level (current_loops->tree_root->inner);
 
   /* Now propagate the frequencies through all the blocks.  */
@@ -1639,6 +1757,7 @@ counts_to_freqs (void)
   count_max = MAX (true_count_max, 1);
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     bb->frequency = (bb->count * BB_FREQ_MAX + count_max / 2) / count_max;
   count_max = MAX (true_count_max, 1);
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     bb->frequency = (bb->count * BB_FREQ_MAX + count_max / 2) / count_max;
+
   return true_count_max;
 }
 
   return true_count_max;
 }
 
@@ -1685,7 +1804,7 @@ expensive_function_p (int threshold)
 
 /* Estimate basic blocks frequency by given branch probabilities.  */
 
 
 /* Estimate basic blocks frequency by given branch probabilities.  */
 
-static void
+void
 estimate_bb_frequencies (void)
 {
   basic_block bb;
 estimate_bb_frequencies (void)
 {
   basic_block bb;
@@ -1762,7 +1881,15 @@ compute_function_frequency (void)
   basic_block bb;
 
   if (!profile_info || !flag_branch_probabilities)
   basic_block bb;
 
   if (!profile_info || !flag_branch_probabilities)
-    return;
+    {
+      if (lookup_attribute ("cold", DECL_ATTRIBUTES (current_function_decl))
+         != NULL)
+        cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
+      else if (lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl))
+              != NULL)
+        cfun->function_frequency = FUNCTION_FREQUENCY_HOT;
+      return;
+    }
   cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
     {
   cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
     {