OSDN Git Service

* c-decl.c (finish_decl): When setting the DECL_ASSEMBLER_NAME
[pf3gnuchains/gcc-fork.git] / gcc / predict.c
index 71950ee..80ad41e 100644 (file)
@@ -1,5 +1,5 @@
 /* Branch prediction routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -30,6 +30,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -45,23 +47,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "recog.h"
 #include "expr.h"
 #include "predict.h"
-#include "profile.h"
-#include "real.h"
+#include "coverage.h"
+#include "sreal.h"
 #include "params.h"
 #include "target.h"
 #include "loop.h"
+#include "cfgloop.h"
 
-/* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE, 0.5,
-                   REAL_BB_FREQ_MAX.  */
-static REAL_VALUE_TYPE real_zero, real_one, real_almost_one, real_br_prob_base,
-                      real_one_half, real_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.  */
+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_NEVER             (0)
 #define PROB_VERY_UNLIKELY     (REG_BR_PROB_BASE / 10 - 1)
-#define PROB_UNLIKELY          (REG_BR_PROB_BASE * 4 / 10 - 1)
 #define PROB_EVEN              (REG_BR_PROB_BASE / 2)
-#define PROB_LIKELY            (REG_BR_PROB_BASE - PROB_UNLIKELY)
 #define PROB_VERY_LIKELY       (REG_BR_PROB_BASE - PROB_VERY_UNLIKELY)
 #define PROB_ALWAYS            (REG_BR_PROB_BASE)
 
@@ -83,6 +83,7 @@ static void process_note_prediction    PARAMS ((basic_block, int *,
 static bool last_basic_block_p           PARAMS ((basic_block));
 static void compute_function_frequency  PARAMS ((void));
 static void choose_function_section     PARAMS ((void));
+static bool can_predict_insn_p          PARAMS ((rtx));
 
 /* Information we hold about each branch predictor.
    Filled using information from predict.def.  */
@@ -113,17 +114,15 @@ static const struct predictor_info predictor_info[]= {
 #undef DEF_PREDICTOR
 
 /* Return true in case BB can be CPU intensive and should be optimized
-   for maximal perofmrance.  */
+   for maximal performance.  */
 
 bool
 maybe_hot_bb_p (bb)
      basic_block bb;
 {
-  if (profile_info.count_profiles_merged
-      && flag_branch_probabilities
+  if (profile_info && flag_branch_probabilities
       && (bb->count
-         < profile_info.max_counter_in_program
-         / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
+         < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return false;
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return false;
@@ -136,11 +135,9 @@ bool
 probably_cold_bb_p (bb)
      basic_block bb;
 {
-  if (profile_info.count_profiles_merged
-      && flag_branch_probabilities
+  if (profile_info && flag_branch_probabilities
       && (bb->count
-         < profile_info.max_counter_in_program
-         / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
+         < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
     return true;
   if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
     return true;
@@ -152,10 +149,8 @@ bool
 probably_never_executed_bb_p (bb)
        basic_block bb;
 {
-  if (profile_info.count_profiles_merged
-      && flag_branch_probabilities)
-    return ((bb->count + profile_info.count_profiles_merged / 2)
-           / profile_info.count_profiles_merged) == 0;
+  if (profile_info && flag_branch_probabilities)
+    return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
   return false;
 }
 
@@ -185,6 +180,8 @@ predict_insn (insn, predictor, probability)
 {
   if (!any_condjump_p (insn))
     abort ();
+  if (!flag_guess_branch_prob)
+    return;
 
   REG_NOTES (insn)
     = gen_rtx_EXPR_LIST (REG_BR_PRED,
@@ -233,6 +230,18 @@ predict_edge (e, predictor, probability)
   predict_insn (last_insn, predictor, probability);
 }
 
+/* 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 (insn)
+       rtx insn;
+{
+  return (GET_CODE (insn) == JUMP_INSN
+         && any_condjump_p (insn)
+         && BLOCK_FOR_INSN (insn)->succ->succ_next);
+}
+
 /* Predict edge E by given predictor if possible.  */
 
 void
@@ -413,7 +422,7 @@ estimate_probability (loops_info)
 {
   dominance_info dominators, post_dominators;
   basic_block bb;
-  int i;
+  unsigned i;
 
   connect_infinite_loops_to_exit ();
   dominators = calculate_dominance_info (CDI_DOMINATORS);
@@ -424,13 +433,33 @@ estimate_probability (loops_info)
   for (i = 1; i < loops_info->num; i++)
     {
       basic_block bb, *bbs;
-      int j;
+      unsigned j;
       int exits;
       struct loop *loop = loops_info->parray[i];
+      struct loop_desc desc;
+      unsigned HOST_WIDE_INT niter;
 
       flow_loop_scan (loops_info, loop, LOOP_EXIT_EDGES);
       exits = loop->num_exits;
 
+      if (simple_loop_p (loops_info, loop, &desc)
+         && desc.const_iter)
+       {
+         int prob;
+         niter = desc.niter + 1;
+         if (niter == 0)        /* We might overflow here.  */
+           niter = desc.niter;
+
+         prob = (REG_BR_PROB_BASE
+                 - (REG_BR_PROB_BASE + niter /2) / niter);
+         /* Branch prediction algorithm gives 0 frequency for everything
+            after the end of loop for loop having 0 probability to finish.  */
+         if (prob == REG_BR_PROB_BASE)
+           prob = REG_BR_PROB_BASE - 1;
+         predict_edge (desc.in_edge, PRED_LOOP_ITERATIONS,
+                       prob);
+       }
+
       bbs = get_loop_body (loop);
       for (j = 0; j < loop->num_nodes; j++)
        {
@@ -443,7 +472,8 @@ estimate_probability (loops_info)
             statements construct loops via "non-loop" constructs
             in the source language and are better to be handled
             separately.  */
-         if (predicted_by_p (bb, PRED_CONTINUE))
+         if (!can_predict_insn_p (bb->end)
+             || predicted_by_p (bb, PRED_CONTINUE))
            continue;
 
          /* Loop branch heuristics - predict an edge back to a
@@ -457,7 +487,7 @@ estimate_probability (loops_info)
              }
 
          /* Loop exit heuristics - predict an edge exiting the loop if the
-            conditinal has no loop header successors as not taken.  */
+            conditional has no loop header successors as not taken.  */
          if (!header_found)
            for (e = bb->succ; e; e = e->succ_next)
              if (e->dest->index < 0
@@ -477,7 +507,7 @@ estimate_probability (loops_info)
       rtx cond, earliest;
       edge e;
 
-      if (GET_CODE (last_insn) != JUMP_INSN || ! any_condjump_p (last_insn))
+      if (! can_predict_insn_p (last_insn))
        continue;
 
       for (e = bb->succ; e; e = e->succ_next)
@@ -552,12 +582,12 @@ estimate_probability (loops_info)
          case EQ:
          case UNEQ:
            /* Floating point comparisons appears to behave in a very
-              inpredictable way because of special role of = tests in
+              unpredictable way because of special role of = tests in
               FP code.  */
            if (FLOAT_MODE_P (GET_MODE (XEXP (cond, 0))))
              ;
            /* Comparisons with 0 are often used for booleans and there is
-              nothing usefull to predict about them.  */
+              nothing useful to predict about them.  */
            else if (XEXP (cond, 1) == const0_rtx
                     || XEXP (cond, 0) == const0_rtx)
              ;
@@ -568,12 +598,12 @@ estimate_probability (loops_info)
          case NE:
          case LTGT:
            /* Floating point comparisons appears to behave in a very
-              inpredictable way because of special role of = tests in
+              unpredictable way because of special role of = tests in
               FP code.  */
            if (FLOAT_MODE_P (GET_MODE (XEXP (cond, 0))))
              ;
            /* Comparisons with 0 are often used for booleans and there is
-              nothing usefull to predict about them.  */
+              nothing useful to predict about them.  */
            else if (XEXP (cond, 1) == const0_rtx
                     || XEXP (cond, 0) == const0_rtx)
              ;
@@ -766,7 +796,7 @@ process_note_prediction (bb, heads, dominators, post_dominators, pred, flags)
 
   /* Now find the edge that leads to our branch and aply the prediction.  */
 
-  if (y == last_basic_block)
+  if (y == last_basic_block || !can_predict_insn_p (BASIC_BLOCK (y)->end))
     return;
   for (e = BASIC_BLOCK (y)->succ; e; e = e->succ_next)
     if (e->dest->index >= 0
@@ -788,7 +818,7 @@ process_note_predictions (bb, heads, dominators, post_dominators)
   rtx insn;
   edge e;
 
-  /* Additionaly, we check here for blocks with no successors.  */
+  /* Additionally, we check here for blocks with no successors.  */
   int contained_noreturn_call = 0;
   int was_bb_head = 0;
   int noreturn_block = 1;
@@ -876,7 +906,7 @@ note_prediction_to_br_prob ()
 typedef struct block_info_def
 {
   /* Estimated frequency of execution of basic_block.  */
-  REAL_VALUE_TYPE frequency;
+  sreal frequency;
 
   /* To keep queue of basic blocks to process.  */
   basic_block next;
@@ -894,7 +924,7 @@ typedef struct edge_info_def
   /* In case edge is an loopback edge, the probability edge will be reached
      in case header is.  Estimated number of iterations of the loop can be
      then computed as 1 / (1 - back_edge_prob).  */
-  REAL_VALUE_TYPE back_edge_prob;
+  sreal back_edge_prob;
   /* True if the edge is an loopback edge in the natural loop.  */
   int back_edge:1;
 } *edge_info;
@@ -939,7 +969,7 @@ propagate_freq (loop)
   last = head;
   for (bb = head; bb; bb = nextbb)
     {
-      REAL_VALUE_TYPE cyclic_probability, frequency;
+      sreal cyclic_probability, frequency;
 
       memcpy (&cyclic_probability, &real_zero, sizeof (real_zero));
       memcpy (&frequency, &real_zero, sizeof (real_zero));
@@ -959,36 +989,43 @@ propagate_freq (loop)
          for (e = bb->pred; e; e = e->pred_next)
            if (EDGE_INFO (e)->back_edge)
              {
-               REAL_ARITHMETIC (cyclic_probability, PLUS_EXPR,
-                                cyclic_probability,
-                                EDGE_INFO (e)->back_edge_prob);
+               sreal_add (&cyclic_probability, &cyclic_probability,
+                          &EDGE_INFO (e)->back_edge_prob);
              }
            else if (!(e->flags & EDGE_DFS_BACK))
              {
-               REAL_VALUE_TYPE tmp;
+               sreal tmp;
 
                /*  frequency += (e->probability
                                  * BLOCK_INFO (e->src)->frequency /
                                  REG_BR_PROB_BASE);  */
 
-               REAL_VALUE_FROM_INT (tmp, e->probability, 0,
-                                    TYPE_MODE (double_type_node));
-               REAL_ARITHMETIC (tmp, MULT_EXPR, tmp,
-                                BLOCK_INFO (e->src)->frequency);
-               REAL_ARITHMETIC (tmp, RDIV_EXPR, tmp, real_br_prob_base);
-               REAL_ARITHMETIC (frequency, PLUS_EXPR, frequency, tmp);
+               sreal_init (&tmp, e->probability, 0);
+               sreal_mul (&tmp, &tmp, &BLOCK_INFO (e->src)->frequency);
+               sreal_mul (&tmp, &tmp, &real_inv_br_prob_base);
+               sreal_add (&frequency, &frequency, &tmp);
              }
 
-         if (REAL_VALUES_LESS (real_almost_one, cyclic_probability))
-           memcpy (&cyclic_probability, &real_almost_one, sizeof (real_zero));
+         if (sreal_compare (&cyclic_probability, &real_zero) == 0)
+           {
+             memcpy (&BLOCK_INFO (bb)->frequency, &frequency,
+                     sizeof (frequency));
+           }
+         else
+           {
+             if (sreal_compare (&cyclic_probability, &real_almost_one) > 0)
+               {
+                 memcpy (&cyclic_probability, &real_almost_one,
+                         sizeof (real_almost_one));
+               }
 
-         /* BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability)
-          */
+             /* BLOCK_INFO (bb)->frequency = frequency 
+                                             / (1 - cyclic_probability) */
 
-         REAL_ARITHMETIC (cyclic_probability, MINUS_EXPR, real_one,
-                          cyclic_probability);
-         REAL_ARITHMETIC (BLOCK_INFO (bb)->frequency,
-                          RDIV_EXPR, frequency, cyclic_probability);
+             sreal_sub (&cyclic_probability, &real_one, &cyclic_probability);
+             sreal_div (&BLOCK_INFO (bb)->frequency,
+                        &frequency, &cyclic_probability);
+           }
        }
 
       BLOCK_INFO (bb)->tovisit = 0;
@@ -997,18 +1034,16 @@ propagate_freq (loop)
       for (e = bb->succ; e; e = e->succ_next)
        if (e->dest == head)
          {
-           REAL_VALUE_TYPE tmp;
+           sreal tmp;
 
            /* EDGE_INFO (e)->back_edge_prob
                  = ((e->probability * BLOCK_INFO (bb)->frequency)
                     / REG_BR_PROB_BASE); */
-           REAL_VALUE_FROM_INT (tmp, e->probability, 0,
-                                TYPE_MODE (double_type_node));
-           REAL_ARITHMETIC (tmp, MULT_EXPR, tmp,
-                            BLOCK_INFO (bb)->frequency);
-           REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob,
-                            RDIV_EXPR, tmp, real_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.  */
@@ -1042,7 +1077,7 @@ estimate_loops_at_level (first_loop)
     {
       edge e;
       basic_block *bbs;
-      int i;
+      unsigned i;
 
       estimate_loops_at_level (loop->inner);
       
@@ -1066,7 +1101,7 @@ estimate_loops_at_level (first_loop)
 static void
 counts_to_freqs ()
 {
-  HOST_WIDEST_INT count_max = 1;
+  gcov_type count_max = 1;
   basic_block bb;
 
   FOR_EACH_BB (bb)
@@ -1078,7 +1113,7 @@ counts_to_freqs ()
 
 /* Return true if function is likely to be expensive, so there is no point to
    optimize performance of prologue, epilogue or do inlining at the expense
-   of code size growth.  THRESHOLD is the limit of number of isntructions
+   of code size growth.  THRESHOLD is the limit of number of instructions
    function can execute at average to be still considered not expensive.  */
 
 bool
@@ -1126,23 +1161,25 @@ estimate_bb_frequencies (loops)
      struct loops *loops;
 {
   basic_block bb;
-  REAL_VALUE_TYPE freq_max;
-  enum machine_mode double_mode = TYPE_MODE (double_type_node);
+  sreal freq_max;
 
   if (flag_branch_probabilities)
     counts_to_freqs ();
   else
     {
-      REAL_VALUE_FROM_INT (real_zero, 0, 0, double_mode);
-      REAL_VALUE_FROM_INT (real_one, 1, 0, double_mode);
-      REAL_VALUE_FROM_INT (real_br_prob_base, REG_BR_PROB_BASE, 0, double_mode);
-      REAL_VALUE_FROM_INT (real_bb_freq_max, BB_FREQ_MAX, 0, double_mode);
-      REAL_VALUE_FROM_INT (real_one_half, 2, 0, double_mode);
-
-      REAL_ARITHMETIC (real_one_half, RDIV_EXPR, real_one, real_one_half);
-
-      REAL_ARITHMETIC (real_almost_one, RDIV_EXPR, real_one, real_br_prob_base);
-      REAL_ARITHMETIC (real_almost_one, MINUS_EXPR, real_one, real_almost_one);
+      static int real_values_initialized = 0;
+
+      if (!real_values_initialized)
+        {
+         real_values_initialized = 1;
+         sreal_init (&real_zero, 0, 0);
+         sreal_init (&real_one, 1, 0);
+         sreal_init (&real_br_prob_base, REG_BR_PROB_BASE, 0);
+         sreal_init (&real_bb_freq_max, BB_FREQ_MAX, 0);
+         sreal_init (&real_one_half, 1, -1);
+         sreal_div (&real_inv_br_prob_base, &real_one, &real_br_prob_base);
+         sreal_sub (&real_almost_one, &real_one, &real_inv_br_prob_base);
+       }
 
       mark_dfs_back_edges ();
       /* Fill in the probability values in flowgraph based on the REG_BR_PROB
@@ -1151,9 +1188,7 @@ estimate_bb_frequencies (loops)
        {
          rtx last_insn = bb->end;
 
-         if (GET_CODE (last_insn) != JUMP_INSN || !any_condjump_p (last_insn)
-             /* Avoid handling of conditional jumps jumping to fallthru edge.  */
-             || bb->succ->succ_next == NULL)
+         if (!can_predict_insn_p (last_insn))
            {
              /* We can predict only conditional jumps at the moment.
                 Expect each edge to be equally probable.
@@ -1185,11 +1220,10 @@ estimate_bb_frequencies (loops)
          BLOCK_INFO (bb)->tovisit = 0;
          for (e = bb->succ; e; e = e->succ_next)
            {
-             REAL_VALUE_FROM_INT (EDGE_INFO (e)->back_edge_prob,
-                                  e->probability, 0, double_mode);
-             REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob,
-                              RDIV_EXPR, EDGE_INFO (e)->back_edge_prob,
-                              real_br_prob_base);
+             sreal_init (&EDGE_INFO (e)->back_edge_prob, e->probability, 0);
+             sreal_mul (&EDGE_INFO (e)->back_edge_prob,
+                        &EDGE_INFO (e)->back_edge_prob,
+                        &real_inv_br_prob_base);
            }
        }
 
@@ -1199,20 +1233,17 @@ estimate_bb_frequencies (loops)
 
       memcpy (&freq_max, &real_zero, sizeof (real_zero));
       FOR_EACH_BB (bb)
-       if (REAL_VALUES_LESS
-           (freq_max, BLOCK_INFO (bb)->frequency))
-         memcpy (&freq_max, &BLOCK_INFO (bb)->frequency,
-                 sizeof (freq_max));
+       if (sreal_compare (&freq_max, &BLOCK_INFO (bb)->frequency) < 0)
+         memcpy (&freq_max, &BLOCK_INFO (bb)->frequency, sizeof (freq_max));
 
+      sreal_div (&freq_max, &real_bb_freq_max, &freq_max);
       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
        {
-         REAL_VALUE_TYPE tmp;
+         sreal tmp;
 
-         REAL_ARITHMETIC (tmp, MULT_EXPR, BLOCK_INFO (bb)->frequency,
-                          real_bb_freq_max);
-         REAL_ARITHMETIC (tmp, RDIV_EXPR, tmp, freq_max);
-         REAL_ARITHMETIC (tmp, PLUS_EXPR, tmp, real_one_half);
-         bb->frequency = REAL_VALUE_UNSIGNED_FIX (tmp);
+         sreal_mul (&tmp, &BLOCK_INFO (bb)->frequency, &freq_max);
+         sreal_add (&tmp, &tmp, &real_one_half);
+         bb->frequency = sreal_to_int (&tmp);
        }
 
       free_aux_for_blocks ();
@@ -1229,8 +1260,7 @@ compute_function_frequency ()
 {
   basic_block bb;
 
-  if (!profile_info.count_profiles_merged
-      || !flag_branch_probabilities)
+  if (!profile_info || !flag_branch_probabilities)
     return;
   cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
@@ -1250,7 +1280,12 @@ static void
 choose_function_section ()
 {
   if (DECL_SECTION_NAME (current_function_decl)
-      || !targetm.have_named_sections)
+      || !targetm.have_named_sections
+      /* Theoretically we can split the gnu.linkonce text section too,
+        but this requires more work as the frequency needs to match
+        for all generated objects so we need to merge the frequency
+        of all instances.  For now just never set frequency for these.  */
+      || DECL_ONE_ONLY (current_function_decl))
     return;
   if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
     DECL_SECTION_NAME (current_function_decl) =