OSDN Git Service

2009-10-30 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index 73dbcbd..6353fb9 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.
@@ -168,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;
 }
@@ -654,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;
@@ -677,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;
@@ -723,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,
@@ -765,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;
@@ -813,7 +815,7 @@ 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)
@@ -888,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))
@@ -914,8 +916,6 @@ predict_loops (void)
   loop_iterator li;
   struct loop *loop;
 
-  scev_initialize ();
-
   /* Try to predict out blocks in a loop that are not part of a
      natural loop.  */
   FOR_EACH_LOOP (li, loop, 0)
@@ -1038,8 +1038,6 @@ predict_loops (void)
       /* Free basic blocks from get_loop_body.  */
       free (bbs);
     }
-
-  scev_finalize ();
 }
 
 /* Attempt to predict probabilities of BB outgoing edges using local
@@ -1606,16 +1604,96 @@ assert_is_empty (const void *key ATTRIBUTE_UNUSED, void **value,
 }
 #endif
 
-/* Predict branch probabilities and estimate profile of the tree CFG.  */
-static unsigned int
+/* Predict branch probabilities and estimate profile for basic block BB.  */
+
+static void
+tree_estimate_probability_bb (basic_block bb)
+{
+  edge e;
+  edge_iterator ei;
+  gimple last;
+
+  FOR_EACH_EDGE (e, ei, bb->succs)
+    {
+      /* 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.
+
+        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
+         && (last = last_stmt (e->dest)) != NULL
+         && gimple_code (last) == GIMPLE_RETURN)
+       {
+         edge e1;
+         edge_iterator ei1;
+
+         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,
+        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))
+       {
+         gimple_stmt_iterator bi;
+
+         /* 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 (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
+              gsi_next (&bi))
+           {
+             gimple stmt = gsi_stmt (bi);
+             if (is_gimple_call (stmt)
+                 /* Constant and pure calls are hardly used to signalize
+                    something exceptional.  */
+                 && gimple_has_side_effects (stmt))
+               {
+                 predict_edge_def (e, PRED_CALL, NOT_TAKEN);
+                 break;
+               }
+           }
+       }
+    }
+  tree_predict_by_opcode (bb);
+}
+
+/* Predict branch probabilities and estimate profile of the tree CFG.
+   This function can be called from the loop optimizers to recompute
+   the profile information.  */
+
+void
 tree_estimate_probability (void)
 {
   basic_block bb;
 
-  loop_optimizer_init (0);
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    flow_loops_dump (dump_file, NULL, 0);
-
   add_noreturn_fake_exit_edges ();
   connect_infinite_loops_to_exit ();
   /* We use loop_niter_by_eval, which requires that the loops have
@@ -1625,89 +1703,14 @@ tree_estimate_probability (void)
 
   bb_predictions = pointer_map_create ();
   tree_bb_level_predictions ();
-
-  mark_irreducible_loops ();
   record_loop_exits ();
+
   if (number_of_loops () > 1)
     predict_loops ();
 
   FOR_EACH_BB (bb)
-    {
-      edge e;
-      edge_iterator ei;
-      gimple last;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       {
-         /* 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. 
-
-            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
-             && (last = last_stmt (e->dest)) != NULL
-             && gimple_code (last) == GIMPLE_RETURN)
-           {
-             edge e1;
-             edge_iterator ei1;
-
-             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);
-           }
+    tree_estimate_probability_bb (bb);
 
-         /* Look for block we are guarding (ie 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))
-           {
-             gimple_stmt_iterator bi;
-
-             /* 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 (bi = gsi_start_bb (e->dest); !gsi_end_p (bi);
-                  gsi_next (&bi))
-               {
-                 gimple stmt = gsi_stmt (bi);
-                 if (is_gimple_call (stmt)
-                     /* Constant and pure calls are hardly used to signalize
-                        something exceptional.  */
-                     && gimple_has_side_effects (stmt))
-                   {
-                     predict_edge_def (e, PRED_CALL, NOT_TAKEN);
-                     break;
-                   }
-               }
-           }
-       }
-      tree_predict_by_opcode (bb);
-    }
   FOR_EACH_BB (bb)
     combine_predictions_for_bb (bb);
 
@@ -1720,6 +1723,31 @@ tree_estimate_probability (void)
   estimate_bb_frequencies ();
   free_dominance_info (CDI_POST_DOMINATORS);
   remove_fake_exit_edges ();
+}
+
+/* Predict branch probabilities and estimate profile of the tree CFG.
+   This is the driver function for PASS_PROFILE.  */
+
+static unsigned int
+tree_estimate_probability_driver (void)
+{
+  unsigned nb_loops;
+
+  loop_optimizer_init (0);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    flow_loops_dump (dump_file, NULL, 0);
+
+  mark_irreducible_loops ();
+
+  nb_loops = number_of_loops ();
+  if (nb_loops > 1)
+    scev_initialize ();
+
+  tree_estimate_probability ();
+
+  if (nb_loops > 1)
+    scev_finalize ();
+
   loop_optimizer_finalize ();
   if (dump_file && (dump_flags & TDF_DETAILS))
     gimple_dump_cfg (dump_file, dump_flags);
@@ -2052,7 +2080,7 @@ estimate_bb_frequencies (void)
   basic_block bb;
   sreal freq_max;
 
-  if (cfun->function_frequency != PROFILE_READ || !counts_to_freqs ())
+  if (profile_status != PROFILE_READ || !counts_to_freqs ())
     {
       static int real_values_initialized = 0;
 
@@ -2185,7 +2213,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;
 }
 
@@ -2201,7 +2229,7 @@ struct gimple_opt_pass pass_profile =
   GIMPLE_PASS,
   "profile",                           /* name */
   gate_estimate_probability,           /* gate */
-  tree_estimate_probability,           /* execute */
+  tree_estimate_probability_driver,    /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */