OSDN Git Service

2005-06-14 Doug Rupp <rupp@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index 8611f30..61cc540 100644 (file)
@@ -1,5 +1,6 @@
 /* Branch prediction routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -66,15 +67,15 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
             real_inv_br_prob_base, real_one_half, real_bb_freq_max;
 
 /* Random guesstimation given names.  */
-#define PROB_VERY_UNLIKELY     (REG_BR_PROB_BASE / 10 - 1)
+#define PROB_VERY_UNLIKELY     (REG_BR_PROB_BASE / 100 - 1)
 #define PROB_EVEN              (REG_BR_PROB_BASE / 2)
 #define PROB_VERY_LIKELY       (REG_BR_PROB_BASE - PROB_VERY_UNLIKELY)
 #define PROB_ALWAYS            (REG_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 estimate_loops_at_level (struct loop *loop);
-static void propagate_freq (struct loop *);
+static void estimate_loops_at_level (struct loop *, bitmap);
+static void propagate_freq (struct loop *, bitmap);
 static void estimate_bb_frequencies (struct loops *);
 static void predict_paths_leading_to (basic_block, int *, enum br_predictor, enum prediction);
 static bool last_basic_block_p (basic_block);
@@ -170,18 +171,17 @@ rtl_predicted_by_p (basic_block bb, enum br_predictor predictor)
 bool
 tree_predicted_by_p (basic_block bb, enum br_predictor predictor)
 {
-  struct edge_prediction *i = bb_ann (bb)->predictions;
-  for (i = bb_ann (bb)->predictions; i; i = i->next)
+  struct edge_prediction *i;
+  for (i = bb->predictions; i; i = i->next)
     if (i->predictor == predictor)
       return true;
   return false;
 }
 
-void
+static void
 predict_insn (rtx insn, enum br_predictor predictor, int probability)
 {
-  if (!any_condjump_p (insn))
-    abort ();
+  gcc_assert (any_condjump_p (insn));
   if (!flag_guess_branch_prob)
     return;
 
@@ -231,13 +231,36 @@ rtl_predict_edge (edge e, enum br_predictor predictor, int probability)
 void
 tree_predict_edge (edge e, enum br_predictor predictor, int probability)
 {
-  struct edge_prediction *i = ggc_alloc (sizeof (struct edge_prediction));
+  gcc_assert (profile_status != PROFILE_GUESSED);
+  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));
+
+      i->next = e->src->predictions;
+      e->src->predictions = i;
+      i->probability = probability;
+      i->predictor = predictor;
+      i->edge = e;
+    }
+}
 
-  i->next = bb_ann (e->src)->predictions;
-  bb_ann (e->src)->predictions = i;
-  i->probability = probability;
-  i->predictor = predictor;
-  i->edge = e;
+/* Remove all predictions on given basic block that are attached
+   to edge E.  */
+void
+remove_predictions_associated_with_edge (edge e)
+{
+  if (e->src->predictions)
+    {
+      struct edge_prediction **prediction = &e->src->predictions;
+      while (*prediction)
+       {
+         if ((*prediction)->edge == e)
+           *prediction = (*prediction)->next;
+         else
+           prediction = &((*prediction)->next);
+       }
+    }
 }
 
 /* Return true when we can store prediction on insn INSN.
@@ -433,14 +456,14 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
 
       /* Save the prediction into CFG in case we are seeing non-degenerated
         conditional jump.  */
-      if (EDGE_COUNT (bb->succs) > 1)
+      if (!single_succ_p (bb))
        {
          BRANCH_EDGE (bb)->probability = combined_probability;
          FALLTHRU_EDGE (bb)->probability
            = REG_BR_PROB_BASE - combined_probability;
        }
     }
-  else if (EDGE_COUNT (bb->succs) > 1)
+  else if (!single_succ_p (bb))
     {
       int prob = INTVAL (XEXP (prob_note, 0));
 
@@ -448,7 +471,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb)
       FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
     }
   else
-    EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
+    single_succ_edge (bb)->probability = REG_BR_PROB_BASE;
 }
 
 /* Combine predictions into single probability and store them into CFG.
@@ -488,7 +511,7 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
     {
       if (!bb->count)
        set_even_probabilities (bb);
-      bb_ann (bb)->predictions = NULL;
+      bb->predictions = NULL;
       if (file)
        fprintf (file, "%i edges in bb %i predicted to even probabilities\n",
                 nedges, bb->index);
@@ -500,7 +523,7 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
 
   /* We implement "first match" heuristics and use probability guessed
      by predictor with smallest index.  */
-  for (pred = bb_ann (bb)->predictions; pred; pred = pred->next)
+  for (pred = bb->predictions; pred; pred = pred->next)
     {
       int predictor = pred->predictor;
       int probability = pred->probability;
@@ -546,7 +569,7 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
     combined_probability = best_probability;
   dump_prediction (file, PRED_COMBINED, combined_probability, bb, true);
 
-  for (pred = bb_ann (bb)->predictions; pred; pred = pred->next)
+  for (pred = bb->predictions; pred; pred = pred->next)
     {
       int predictor = pred->predictor;
       int probability = pred->probability;
@@ -556,7 +579,7 @@ combine_predictions_for_bb (FILE *file, basic_block bb)
       dump_prediction (file, predictor, probability, bb,
                       !first_match || best_predictor == predictor);
     }
-  bb_ann (bb)->predictions = NULL;
+  bb->predictions = NULL;
 
   if (!bb->count)
     {
@@ -582,13 +605,13 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
     {
       basic_block bb, *bbs;
       unsigned j;
-      int exits;
+      unsigned n_exits;
       struct loop *loop = loops_info->parray[i];
       struct niter_desc desc;
       unsigned HOST_WIDE_INT niter;
+      edge *exits;
 
-      flow_loop_scan (loop, LOOP_EXIT_EDGES);
-      exits = loop->num_exits;
+      exits = get_loop_exit_edges (loop, &n_exits);
 
       if (rtlsimpleloops)
        {
@@ -614,11 +637,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
        }
       else
        {
-         edge *exits;
-         unsigned j, n_exits;
          struct tree_niter_desc niter_desc;
 
-         exits = get_loop_exit_edges (loop, &n_exits);
          for (j = 0; j < n_exits; j++)
            {
              tree niter = NULL;
@@ -646,8 +666,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
                }
            }
 
-         free (exits);
        }
+      free (exits);
 
       bbs = get_loop_body (loop);
 
@@ -669,13 +689,15 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
 
          /* Loop branch heuristics - predict an edge back to a
             loop's head as taken.  */
-         FOR_EACH_EDGE (e, ei, bb->succs)
-           if (e->dest == loop->header
-               && e->src == loop->latch)
-             {
-               header_found = 1;
-               predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
-             }
+         if (bb == loop->latch)
+           {
+             e = find_edge (loop->latch, loop->header);
+             if (e)
+               {
+                 header_found = 1;
+                 predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
+               }
+           }
 
          /* Loop exit heuristics - predict an edge exiting the loop if the
             conditional has no loop header successors as not taken.  */
@@ -687,7 +709,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
                  (e, PRED_LOOP_EXIT,
                   (REG_BR_PROB_BASE
                    - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
-                  / exits);
+                  / n_exits);
        }
       
       /* Free basic blocks from get_loop_body.  */
@@ -695,7 +717,10 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
     }
 
   if (!rtlsimpleloops)
-    scev_reset ();
+    {
+      scev_finalize ();
+      current_loops = NULL;
+    }
 }
 
 /* Attempt to predict probabilities of BB outgoing edges using local
@@ -830,8 +855,8 @@ estimate_probability (struct loops *loops_info)
             care for error returns and other are often used for fast paths
             trought function.  */
          if ((e->dest == EXIT_BLOCK_PTR
-              || (EDGE_COUNT (e->dest->succs) == 1
-                  && EDGE_SUCC (e->dest, 0)->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)
@@ -919,7 +944,7 @@ expr_expected_value (tree expr, bitmap visited)
 
              /* If this PHI has itself as an argument, we cannot
                 determine the string length of this argument.  However,
-                if we can find a expected constant value for the other
+                if we can find an expected constant value for the other
                 PHI args then we can still be sure that this is
                 likely a constant.  So be optimistic and just
                 continue with the next argument.  */
@@ -945,7 +970,8 @@ expr_expected_value (tree expr, bitmap visited)
       tree decl = get_callee_fndecl (expr);
       if (!decl)
        return NULL;
-      if (DECL_BUILT_IN (decl) && 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;
@@ -1004,13 +1030,13 @@ strip_builtin_expect (void)
          if (TREE_CODE (stmt) == MODIFY_EXPR
              && TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR
              && (fndecl = get_callee_fndecl (TREE_OPERAND (stmt, 1)))
-             && DECL_BUILT_IN (fndecl)
+             && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
              && (arglist = TREE_OPERAND (TREE_OPERAND (stmt, 1), 1))
              && TREE_CHAIN (arglist))
            {
              TREE_OPERAND (stmt, 1) = TREE_VALUE (arglist);
-             modify_stmt (stmt);
+             update_stmt (stmt);
            }
        }
     }
@@ -1039,9 +1065,9 @@ tree_predict_by_opcode (basic_block bb)
     return;
   op0 = TREE_OPERAND (cond, 0);
   type = TREE_TYPE (op0);
-  visited = BITMAP_XMALLOC ();
+  visited = BITMAP_ALLOC (NULL);
   val = expr_expected_value (cond, visited);
-  BITMAP_XFREE (visited);
+  BITMAP_FREE (visited);
   if (val)
     {
       if (integer_zerop (val))
@@ -1206,14 +1232,9 @@ apply_return_prediction (int *heads)
       || !SSA_NAME_DEF_STMT (return_val)
       || TREE_CODE (SSA_NAME_DEF_STMT (return_val)) != PHI_NODE)
     return;
-  phi = SSA_NAME_DEF_STMT (return_val);
-  while (phi)
-    {
-      tree next = PHI_CHAIN (phi);
-      if (PHI_RESULT (phi) == return_val)
-       break;
-      phi = next;
-    }
+  for (phi = SSA_NAME_DEF_STMT (return_val); phi; phi = PHI_CHAIN (phi))
+    if (PHI_RESULT (phi) == return_val)
+      break;
   if (!phi)
     return;
   phi_num_args = PHI_NUM_ARGS (phi);
@@ -1289,7 +1310,7 @@ tree_estimate_probability (void)
   basic_block bb;
   struct loops loops_info;
 
-  flow_loops_find (&loops_info, LOOP_TREE);
+  flow_loops_find (&loops_info);
   if (dump_file && (dump_flags & TDF_DETAILS))
     flow_loops_dump (&loops_info, dump_file, NULL, 0);
 
@@ -1300,6 +1321,7 @@ tree_estimate_probability (void)
 
   tree_bb_level_predictions ();
 
+  mark_irreducible_loops (&loops_info);
   predict_loops (&loops_info, false);
 
   FOR_EACH_BB (bb)
@@ -1314,7 +1336,7 @@ tree_estimate_probability (void)
             fast paths trought function.  */
          if (e->dest == EXIT_BLOCK_PTR
              && TREE_CODE (last_stmt (bb)) == RETURN_EXPR
-             && EDGE_COUNT (bb->preds) > 1)
+             && !single_pred_p (bb))
            {
              edge e1;
              edge_iterator ei1;
@@ -1440,8 +1462,7 @@ expected_value_to_br_prob (void)
       cond = simplify_rtx (cond);
 
       /* Turn the condition into a scaled branch probability.  */
-      if (cond != const_true_rtx && cond != const0_rtx)
-       abort ();
+      gcc_assert (cond == const_true_rtx || cond == const0_rtx);
       predict_insn_def (insn, PRED_BUILTIN_EXPECT,
                        cond == const_true_rtx ? TAKEN : NOT_TAKEN);
     }
@@ -1457,8 +1478,8 @@ last_basic_block_p (basic_block bb)
 
   return (bb->next_bb == EXIT_BLOCK_PTR
          || (bb->next_bb->next_bb == EXIT_BLOCK_PTR
-             && EDGE_COUNT (bb->succs) == 1
-             && EDGE_SUCC (bb, 0)->dest->next_bb == EXIT_BLOCK_PTR));
+             && single_succ_p (bb)
+             && single_succ (bb)->next_bb == EXIT_BLOCK_PTR));
 }
 
 /* Sets branch probabilities according to PREDiction and
@@ -1529,9 +1550,6 @@ typedef struct block_info_def
   /* To keep queue of basic blocks to process.  */
   basic_block next;
 
-  /* True if block needs to be visited in propagate_freq.  */
-  unsigned int tovisit:1;
-
   /* Number of predecessors we need to visit first.  */
   int npredecessors;
 } *block_info;
@@ -1554,33 +1572,45 @@ typedef struct edge_info_def
    Propagate the frequencies for LOOP.  */
 
 static void
-propagate_freq (struct loop *loop)
+propagate_freq (struct loop *loop, bitmap tovisit)
 {
   basic_block head = loop->header;
   basic_block bb;
   basic_block last;
+  unsigned i;
   edge e;
   basic_block nextbb;
+  bitmap_iterator bi;
 
   /* For each basic block we need to visit count number of his predecessors
      we need to visit first.  */
-  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+  EXECUTE_IF_SET_IN_BITMAP (tovisit, 0, i, bi)
     {
-      if (BLOCK_INFO (bb)->tovisit)
+      edge_iterator ei;
+      int count = 0;
+
+       /* The outermost "loop" includes the exit block, which we can not
+         look up via BASIC_BLOCK.  Detect this and use EXIT_BLOCK_PTR
+         directly.  Do the same for the entry block.  */
+     if (i == (unsigned)ENTRY_BLOCK)
+       bb = ENTRY_BLOCK_PTR;
+     else if (i == (unsigned)EXIT_BLOCK)
+       bb = EXIT_BLOCK_PTR;
+     else
+       bb = BASIC_BLOCK (i);
+
+      FOR_EACH_EDGE (e, ei, bb->preds)
        {
-         edge_iterator ei;
-         int count = 0;
-
-         FOR_EACH_EDGE (e, ei, bb->preds)
-           if (BLOCK_INFO (e->src)->tovisit && !(e->flags & EDGE_DFS_BACK))
-             count++;
-           else if (BLOCK_INFO (e->src)->tovisit
-                    && dump_file && !EDGE_INFO (e)->back_edge)
-             fprintf (dump_file,
-                      "Irreducible region hit, ignoring edge to %i->%i\n",
-                      e->src->index, bb->index);
-         BLOCK_INFO (bb)->npredecessors = count;
+         bool visit = bitmap_bit_p (tovisit, e->src->index);
+
+         if (visit && !(e->flags & EDGE_DFS_BACK))
+           count++;
+         else if (visit && dump_file && !EDGE_INFO (e)->back_edge)
+           fprintf (dump_file,
+                    "Irreducible region hit, ignoring edge to %i->%i\n",
+                    e->src->index, bb->index);
        }
+      BLOCK_INFO (bb)->npredecessors = count;
     }
 
   memcpy (&BLOCK_INFO (head)->frequency, &real_one, sizeof (real_one));
@@ -1601,8 +1631,8 @@ propagate_freq (struct loop *loop)
        {
 #ifdef ENABLE_CHECKING
          FOR_EACH_EDGE (e, ei, bb->preds)
-           if (BLOCK_INFO (e->src)->tovisit && !(e->flags & EDGE_DFS_BACK))
-             abort ();
+           gcc_assert (!bitmap_bit_p (tovisit, e->src->index)
+                       || (e->flags & EDGE_DFS_BACK));
 #endif
 
          FOR_EACH_EDGE (e, ei, bb->preds)
@@ -1647,23 +1677,22 @@ propagate_freq (struct loop *loop)
            }
        }
 
-      BLOCK_INFO (bb)->tovisit = 0;
+      bitmap_clear_bit (tovisit, bb->index);
 
-      /* Compute back edge frequencies.  */
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       if (e->dest == head)
-         {
-           sreal tmp;
+      e = find_edge (bb, head);
+      if (e)
+       {
+         sreal tmp;
            
-           /* EDGE_INFO (e)->back_edge_prob
-              = ((e->probability * BLOCK_INFO (bb)->frequency)
-              / REG_BR_PROB_BASE); */
+         /* EDGE_INFO (e)->back_edge_prob
+            = ((e->probability * BLOCK_INFO (bb)->frequency)
+            / REG_BR_PROB_BASE); */
            
-           sreal_init (&tmp, e->probability, 0);
-           sreal_mul (&tmp, &tmp, &BLOCK_INFO (bb)->frequency);
-           sreal_mul (&EDGE_INFO (e)->back_edge_prob,
-                      &tmp, &real_inv_br_prob_base);
-         }
+         sreal_init (&tmp, e->probability, 0);
+         sreal_mul (&tmp, &tmp, &BLOCK_INFO (bb)->frequency);
+         sreal_mul (&EDGE_INFO (e)->back_edge_prob,
+                    &tmp, &real_inv_br_prob_base);
+       }
 
       /* Propagate to successor blocks.  */
       FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1687,7 +1716,7 @@ propagate_freq (struct loop *loop)
 /* Estimate probabilities of loopback edges in loops at same nest level.  */
 
 static void
-estimate_loops_at_level (struct loop *first_loop)
+estimate_loops_at_level (struct loop *first_loop, bitmap tovisit)
 {
   struct loop *loop;
 
@@ -1697,7 +1726,7 @@ estimate_loops_at_level (struct loop *first_loop)
       basic_block *bbs;
       unsigned i;
 
-      estimate_loops_at_level (loop->inner);
+      estimate_loops_at_level (loop->inner, tovisit);
 
       /* Do not do this for dummy function loop.  */
       if (EDGE_COUNT (loop->latch->succs) > 0)
@@ -1709,9 +1738,9 @@ estimate_loops_at_level (struct loop *first_loop)
 
       bbs = get_loop_body (loop);
       for (i = 0; i < loop->num_nodes; i++)
-       BLOCK_INFO (bbs[i])->tovisit = 1;
+       bitmap_set_bit (tovisit, bbs[i]->index);
       free (bbs);
-      propagate_freq (loop);
+      propagate_freq (loop, tovisit);
     }
 }
 
@@ -1747,8 +1776,7 @@ expensive_function_p (int threshold)
 
   /* We can not compute accurately for large thresholds due to scaled
      frequencies.  */
-  if (threshold > BB_FREQ_MAX)
-    abort ();
+  gcc_assert (threshold <= BB_FREQ_MAX);
 
   /* Frequencies are out of range.  This either means that function contains
      internal loop executing more than BB_FREQ_MAX times or profile feedback
@@ -1786,6 +1814,7 @@ estimate_bb_frequencies (struct loops *loops)
   if (!flag_branch_probabilities || !counts_to_freqs ())
     {
       static int real_values_initialized = 0;
+      bitmap tovisit;
 
       if (!real_values_initialized)
         {
@@ -1801,9 +1830,10 @@ estimate_bb_frequencies (struct loops *loops)
 
       mark_dfs_back_edges ();
 
-      EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->probability = REG_BR_PROB_BASE;
+      single_succ_edge (ENTRY_BLOCK_PTR)->probability = REG_BR_PROB_BASE;
 
       /* Set up block info for each basic block.  */
+      tovisit = BITMAP_ALLOC (NULL);
       alloc_aux_for_blocks (sizeof (struct block_info_def));
       alloc_aux_for_edges (sizeof (struct edge_info_def));
       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
@@ -1811,7 +1841,6 @@ estimate_bb_frequencies (struct loops *loops)
          edge e;
          edge_iterator ei;
 
-         BLOCK_INFO (bb)->tovisit = 0;
          FOR_EACH_EDGE (e, ei, bb->succs)
            {
              sreal_init (&EDGE_INFO (e)->back_edge_prob, e->probability, 0);
@@ -1823,7 +1852,7 @@ estimate_bb_frequencies (struct loops *loops)
 
       /* First compute probabilities locally for each loop from innermost
          to outermost to examine probabilities for back edges.  */
-      estimate_loops_at_level (loops->tree_root);
+      estimate_loops_at_level (loops->tree_root, tovisit);
 
       memcpy (&freq_max, &real_zero, sizeof (real_zero));
       FOR_EACH_BB (bb)
@@ -1842,6 +1871,7 @@ estimate_bb_frequencies (struct loops *loops)
 
       free_aux_for_blocks ();
       free_aux_for_edges ();
+      BITMAP_FREE (tovisit);
     }
   compute_function_frequency ();
   if (flag_reorder_functions)
@@ -1897,11 +1927,16 @@ choose_function_section (void)
                    UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
 }
 
+static bool
+gate_estimate_probability (void)
+{
+  return flag_guess_branch_prob;
+}
 
 struct tree_opt_pass pass_profile = 
 {
   "profile",                           /* name */
-  NULL,                                        /* gate */
+  gate_estimate_probability,           /* gate */
   tree_estimate_probability,           /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */