regs.h (struct reg_info_def): Add freq field.
authorJan Hubicka <jh@suse.cz>
Fri, 22 Jun 2001 17:18:23 +0000 (19:18 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 22 Jun 2001 17:18:23 +0000 (17:18 +0000)
* regs.h (struct reg_info_def): Add freq field.
(REG_N_REFS): Update comment.
(REG_FREQ): New.
* regclass.c (scan_one_insn): Update REG_FREQ.
* flow.c (mark_set_1): Update REG_FREQ, make REG_N_SETS unweighted.
(attempt_auto_inc): Likewise.
(mark_used_reg): Likewise.
(try_pre_increment_1): Likewise.
* local-alloc.c (struct qty): Add freq field.
(alloc_qty): Set freq.
(update_equiv_regs): Set REG_FREQ.
(QTY_CMP_PRI): Use freq.
(combine_regs): Update qty->freq.
* global.c (struct allocno): Update comment for n_refs;
add freq field.
(local_reg_freq): New array.
(global_alloc): Update freq field;
allocate and initialize local_reg_freq.
(allocno_compare): Use freq field.
(find_reg): Likewise.
* reload1.c (count_pseudo): Use freq isntead of n_refs.
(count_spilled_pseudo): Likewise.

* tm.texi (GCOV_TYPE_SIZE): Document.
* basic-block.h (gcov_type): Define.
(struct edge_def): Use gcov_type for count field.
(struct basic_block_def): Likewise.
* defaults.h (GCOV_TYPE_SIZE): Define.
* final.c (end_final): Use GCOV_TYPE_SIZE.
* flow.c (dump_edge_info, dump_flow_info, dump_bb): Print count fields
using HOST_WIDEST_INT_PRINT_DEC.
* gcov-io.h (__fetch_gcov_type, __store_gcov_type, __read_gcov_type,
__write_gcov_type): New.
(store_long): Remove.
* gcov.c (gcov_type): Set default.
(struct adj_list): Use gcov_type for arc_count.
(bb_info): Use gcov_type for succ_count, pred_count and exec_count.
(create_program_flow_graph): Read arc_count properly.
(solve_program_flow_graph): 'total' is gcov_type.
(output_data): Line_counts is gcov_type, print it properly.
* libgcc2.c (struct bb): Counts is gcov_type.
(__bb_exit_func): Use __read_gcov_type and __write_gcov_type.
* profile.c (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set default.
(GCOV_TYPE_SIZE): Define.
(struct bb_info): succ_count and pred_count is gcov_type.
(compute_branch_probabilities): Use __read_gcov_type,
print read edges to the dump file.
(total): Is gcov_type.
(gen_edge_profiler): Use GCOV_TYPE_SIZE.

From-SVN: r43505

14 files changed:
gcc/ChangeLog
gcc/basic-block.h
gcc/defaults.h
gcc/doc/tm.texi
gcc/final.c
gcc/flow.c
gcc/gcov.c
gcc/global.c
gcc/libgcc2.c
gcc/local-alloc.c
gcc/profile.c
gcc/regclass.c
gcc/regs.h
gcc/reload1.c

index 573da053303313cd42801a93183e3f39c4214fa1..a9ef4ef33c616d1cdfc4cc8910efb97598019f3c 100644 (file)
@@ -1,3 +1,55 @@
+Fri Jun 22 19:11:28 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * regs.h (struct reg_info_def): Add freq field.
+       (REG_N_REFS): Update comment.
+       (REG_FREQ): New.
+       * regclass.c (scan_one_insn): Update REG_FREQ.
+       * flow.c (mark_set_1): Update REG_FREQ, make REG_N_SETS unweighted.
+       (attempt_auto_inc): Likewise.
+       (mark_used_reg): Likewise.
+       (try_pre_increment_1): Likewise.
+       * local-alloc.c (struct qty): Add freq field.
+       (alloc_qty): Set freq.
+       (update_equiv_regs): Set REG_FREQ.
+       (QTY_CMP_PRI): Use freq.
+       (combine_regs): Update qty->freq.
+       * global.c (struct allocno): Update comment for n_refs;
+       add freq field.
+       (local_reg_freq): New array.
+       (global_alloc): Update freq field;
+       allocate and initialize local_reg_freq.
+       (allocno_compare): Use freq field.
+       (find_reg): Likewise.
+       * reload1.c (count_pseudo): Use freq isntead of n_refs.
+       (count_spilled_pseudo): Likewise.
+
+       * tm.texi (GCOV_TYPE_SIZE): Document.
+       * basic-block.h (gcov_type): Define.
+       (struct edge_def): Use gcov_type for count field.
+       (struct basic_block_def): Likewise.
+       * defaults.h (GCOV_TYPE_SIZE): Define.
+       * final.c (end_final): Use GCOV_TYPE_SIZE.
+       * flow.c (dump_edge_info, dump_flow_info, dump_bb): Print count fields
+       using HOST_WIDEST_INT_PRINT_DEC.
+       * gcov-io.h (__fetch_gcov_type, __store_gcov_type, __read_gcov_type,
+       __write_gcov_type): New.
+       (store_long): Remove.
+       * gcov.c (gcov_type): Set default.
+       (struct adj_list): Use gcov_type for arc_count.
+       (bb_info): Use gcov_type for succ_count, pred_count and exec_count.
+       (create_program_flow_graph): Read arc_count properly.
+       (solve_program_flow_graph): 'total' is gcov_type.
+       (output_data): Line_counts is gcov_type, print it properly.
+       * libgcc2.c (struct bb): Counts is gcov_type.
+       (__bb_exit_func): Use __read_gcov_type and __write_gcov_type.
+       * profile.c (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set default.
+       (GCOV_TYPE_SIZE): Define.
+       (struct bb_info): succ_count and pred_count is gcov_type.
+       (compute_branch_probabilities): Use __read_gcov_type,
+       print read edges to the dump file.
+       (total): Is gcov_type.
+       (gen_edge_profiler): Use GCOV_TYPE_SIZE.
+
 2001-06-14  Andrew Haley  <aph@cambridge.redhat.com>
 
        * optabs.c (emit_libcall_block): When using non-call exceptions,
index 95f7e48bcfad91709f2b3178e612806c19d4c265..c41ee322a0eba6372a8d0e135a7b8912acf4cc50 100644 (file)
@@ -111,6 +111,9 @@ do {                                                                        \
    be done, other than zero the statistics on the first allocation.  */
 #define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P) 
 
+/* Type we use to hold basic block counters.  Should be at least 64bit.  */
+typedef HOST_WIDEST_INT gcov_type;
+
 /* Control flow edge information.  */
 typedef struct edge_def {
   /* Links through the predecessor and successor lists.  */
@@ -127,7 +130,7 @@ typedef struct edge_def {
 
   int flags;                   /* see EDGE_* below  */
   int probability;             /* biased by REG_BR_PROB_BASE */
-  int count;                   /* Expected number of executions calculated
+  gcov_type count;             /* Expected number of executions calculated
                                   in profile.c  */
 } *edge;
 
@@ -201,7 +204,7 @@ typedef struct basic_block_def {
   int loop_depth;
 
   /* Expected number of executions: calculated in profile.c.  */
-  int count;
+  gcov_type count;
  
   /* Expected frequency.  Normalized to be in range 0 to BB_FREQ_MAX.  */
   int frequency;
index 2989b6674eef3f873d2024953bd417011ca4c28f..cf1042498867e095096b285c271846cdd3b505cb 100644 (file)
@@ -297,6 +297,15 @@ do {                                                               \
 #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
 #endif
 
+/* Type used by GCOV counters.  Use 64bit data type if target supports
+   it.  */
+#if LONG_TYPE_SIZE >= 64
+#define GCOV_TYPE_SIZE LONG_TYPE_SIZE
+#else
+#define GCOV_TYPE_SIZE LONG_LONG_TYPE_SIZE
+#endif
+
+
 /* By default, the preprocessor should be invoked the same way in C++
    as in C.  */
 #ifndef CPLUSPLUS_CPP_SPEC
index a8d8f4189fc563bf15c56ea43fb41d52a932f8a3..5ef909b485a042ec0e372e3c1f2fbb5acb72e2c5 100644 (file)
@@ -1426,6 +1426,14 @@ characters.  If this is undefined, the default is
 largest value that @code{WCHAR_TYPE_SIZE} can have at run-time.  This is
 used in @code{cpp}.
 
+@findex GCOV_TYPE_SIZE
+@item GCOV_TYPE_SIZE
+A C expression for the size in bits of the type used for gcov counters on the
+target machine.  If you don't define this, the default is one
+@code{LONG_TYPE_SIZE} in case it is greater or equal to 64-bit and
+@code{LONG_LONG_TYPE_SIZE} otherwise.  You may want to re-define the type to
+ensure atomicity for counters in multithreaded programs.
+
 @findex WINT_TYPE
 @item WINT_TYPE
 A C expression for a string describing the name of the data type to
index a3fe70d61cbf28d5b0e1143aada970b17b9addf5..b1d2051c1cd247165b97f337dabc0b455ccdf9fa 100644 (file)
@@ -298,12 +298,13 @@ end_final (filename)
       struct bb_list *ptr;
       struct bb_str *sptr;
       int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
+      int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
       int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
 
       if (profile_block_flag)
        size = long_bytes * count_basic_blocks;
       else
-       size = long_bytes * count_instrumented_edges;
+       size = gcov_type_bytes * count_instrumented_edges;
       rounded = size;
 
       rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
index 35c5bd2180c5bef5fa999e83dfcf5c203c189b4c..b3d4327847708b792147408cb401ea4d879ebc8a 100644 (file)
@@ -4856,8 +4856,8 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
                  /* Count (weighted) references, stores, etc.  This counts a
                     register twice if it is modified, but that is correct.  */
                  REG_N_SETS (i) += 1;
-                 REG_N_REFS (i) += (optimize_size ? 1
-                                    : pbi->bb->loop_depth + 1);
+                 REG_N_REFS (i) += 1;
+                 REG_FREQ (i) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
 
                  /* The insns where a reg is live are normally counted
                     elsewhere, but we want the count to include the insn
@@ -5524,7 +5524,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
       /* Count an extra reference to the reg.  When a reg is
         incremented, spilling it is worse, so we want to make
         that less likely.  */
-      REG_N_REFS (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
+      REG_FREQ (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
 
       /* Count the increment as a setting of the register,
         even though it isn't a SET in rtl.  */
@@ -5689,8 +5689,9 @@ mark_used_reg (pbi, reg, cond, insn)
            REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
 
          /* Count (weighted) number of uses of each reg.  */
-         REG_N_REFS (regno_first)
+         REG_FREQ (regno_first)
            += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
+         REG_N_REFS (regno_first)++;
        }
     }
 
@@ -6111,8 +6112,7 @@ try_pre_increment_1 (pbi, insn)
         so we want to make that less likely.  */
       if (regno >= FIRST_PSEUDO_REGISTER)
        {
-         REG_N_REFS (regno) += (optimize_size ? 1
-                                : pbi->bb->loop_depth + 1);
+         REG_FREQ (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
          REG_N_SETS (regno)++;
        }
 
@@ -6359,9 +6359,10 @@ dump_flow_info (file)
       register basic_block bb = BASIC_BLOCK (i);
       register edge e;
 
-      fprintf (file, "\nBasic block %d: first insn %d, last %d, loop_depth %d, count %d, freq %d.\n",
-              i, INSN_UID (bb->head), INSN_UID (bb->end), bb->loop_depth,
-              bb->count, bb->frequency);
+      fprintf (file, "\nBasic block %d: first insn %d, last %d, loop_depth %d, count ",
+              i, INSN_UID (bb->head), INSN_UID (bb->end), bb->loop_depth);
+      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
+      fprintf (file, ", freq %i.\n", bb->frequency);
 
       fprintf (file, "Predecessors: ");
       for (e = bb->pred; e; e = e->pred_next)
@@ -6405,7 +6406,10 @@ dump_edge_info (file, e, do_succ)
     fprintf (file, " %d", side->index);
 
   if (e->count)
-    fprintf (file, " count:%d", e->count);
+    {
+      fprintf (file, " count:");
+      fprintf (file, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) e->count);
+    }
 
   if (e->flags)
     {
@@ -6445,8 +6449,9 @@ dump_bb (bb, outf)
   rtx last;
   edge e;
 
-  fprintf (outf, ";; Basic block %d, loop depth %d, count %d",
+  fprintf (outf, ";; Basic block %d, loop depth %d, count ",
           bb->index, bb->loop_depth, bb->count);
+  fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
   putc ('\n', outf);
 
   fputs (";; Predecessors: ", outf);
index 457c4adec97621409289718ae13a7cf73ef68ef3..91cbbd64109f74442a8a1379cd9c3b1de8a19c94 100644 (file)
@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA.  */
 #include "intl.h"
 #undef abort
 
+typedef HOST_WIDEST_INT gcov_type;
 #include "gcov-io.h"
 
 /* The .bb file format consists of several lists of 4-byte integers
@@ -104,7 +105,7 @@ struct sourcefile *sources;
 struct adj_list {
   int source;
   int target;
-  int arc_count;
+  gcov_type arc_count;
   unsigned int count_valid : 1;
   unsigned int on_tree : 1;
   unsigned int fake : 1;
@@ -123,9 +124,9 @@ struct adj_list {
 struct bb_info {
   struct adj_list *succ;
   struct adj_list *pred;
-  int succ_count;
-  int pred_count;
-  int exec_count;
+  gcov_type succ_count;
+  gcov_type pred_count;
+  gcov_type exec_count;
   unsigned int count_valid : 1;
   unsigned int on_tree : 1;
 #if 0
@@ -579,8 +580,8 @@ create_program_flow_graph (bptr)
     for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
       if (! arcptr->on_tree)
        {
-         long tmp_count = 0;
-         if (da_file && __read_long (&tmp_count, da_file, 8))
+         gcov_type tmp_count = 0;
+         if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
            abort();
 
          arcptr->arc_count = tmp_count;
@@ -594,7 +595,8 @@ static void
 solve_program_flow_graph (bptr)
      struct bb_info_list *bptr;
 {
-  int passes, changes, total;
+  int passes, changes;
+  gcov_type total;
   int i;
   struct adj_list *arcptr;
   struct bb_info *bb_graph;
@@ -975,7 +977,7 @@ output_data ()
   int this_file;
   /* An array indexed by line number which indicates how many times that line
      was executed.  */
-  long *line_counts;
+  gcov_type *line_counts;
   /* An array indexed by line number which indicates whether the line was
      present in the bb file (i.e. whether it had code associate with it).
      Lines never executed are those which both exist, and have zero execution
@@ -1035,7 +1037,7 @@ output_data ()
       else
        source_file_name = s_ptr->name;
 
-      line_counts = (long *) xcalloc (sizeof (long), s_ptr->maxlineno);
+      line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
       line_exists = xcalloc (1, s_ptr->maxlineno);
       if (output_branch_probs)
        branch_probs = (struct arcdata **)
@@ -1324,8 +1326,12 @@ output_data ()
              if (line_exists[count])
                {
                  if (line_counts[count])
-                   fprintf (gcov_file, "%12ld    %s", line_counts[count],
-                            string);
+                   {
+                     char c[20];
+                     sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
+                     fprintf (gcov_file, "%12s    %s", c,
+                              string);
+                   }
                  else
                    fprintf (gcov_file, "      ######    %s", string);
                }
index 4460836c7ed1d9ee0232469a579334397596b607..f03de63c2c7349e9898bbc8c6c8a1753c73e7bde 100644 (file)
@@ -94,9 +94,12 @@ struct allocno
   /* Number of calls crossed by each allocno.  */
   int calls_crossed;
 
-  /* Number of refs (weighted) to each allocno.  */
+  /* Number of refs to each allocno.  */
   int n_refs;
 
+  /* Frequency of uses of each allocno.  */
+  int freq;
+
   /* Guess at live length of each allocno.
      This is actually the max of the live lengths of the regs.  */
   int live_length;
@@ -215,11 +218,14 @@ static HARD_REG_SET no_global_alloc_regs;
 
 static HARD_REG_SET regs_used_so_far;
 
-/* Number of refs (weighted) to each hard reg, as used by local alloc.
+/* Number of refs to each hard reg, as used by local alloc.
    It is zero for a reg that contains global pseudos or is explicitly used.  */
 
 static int local_reg_n_refs[FIRST_PSEUDO_REGISTER];
 
+/* Frequency of uses of given hard reg.  */
+static int local_reg_freq[FIRST_PSEUDO_REGISTER];
+
 /* Guess at live length of each hard reg, as used by local alloc.
    This is actually the sum of the live lengths of the specific regs.  */
 
@@ -447,6 +453,7 @@ global_alloc (file)
        allocno[num].size = PSEUDO_REGNO_SIZE (i);
        allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
        allocno[num].n_refs += REG_N_REFS (i);
+       allocno[num].freq += REG_FREQ (i);
        if (allocno[num].live_length < REG_LIVE_LENGTH (i))
          allocno[num].live_length = REG_LIVE_LENGTH (i);
       }
@@ -456,6 +463,7 @@ global_alloc (file)
      override it.  */
   memset ((char *) local_reg_live_length, 0, sizeof local_reg_live_length);
   memset ((char *) local_reg_n_refs, 0, sizeof local_reg_n_refs);
+  memset ((char *) local_reg_freq, 0, sizeof local_reg_freq);
   for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
     if (reg_renumber[i] >= 0)
       {
@@ -466,6 +474,7 @@ global_alloc (file)
        for (j = regno; j < endregno; j++)
          {
            local_reg_n_refs[j] += REG_N_REFS (i);
+           local_reg_freq[j] += REG_FREQ (i);
            local_reg_live_length[j] += REG_LIVE_LENGTH (i);
          }
       }
@@ -473,7 +482,7 @@ global_alloc (file)
   /* We can't override local-alloc for a reg used not just by local-alloc.  */
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (regs_ever_live[i])
-      local_reg_n_refs[i] = 0;
+      local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
        
   allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
 
@@ -605,11 +614,11 @@ allocno_compare (v1p, v2p)
      times a register can occur in one insn (surely less than 100).
      Multiplying this by 10000 can't overflow.  */
   register int pri1
-    = (((double) (floor_log2 (allocno[v1].n_refs) * allocno[v1].n_refs)
+    = (((double) (floor_log2 (allocno[v1].n_refs) * allocno[v1].freq)
        / allocno[v1].live_length)
        * 10000 * allocno[v1].size);
   register int pri2
-    = (((double) (floor_log2 (allocno[v2].n_refs) * allocno[v2].n_refs)
+    = (((double) (floor_log2 (allocno[v2].n_refs) * allocno[v2].freq)
        / allocno[v2].live_length)
        * 10000 * allocno[v2].size);
   if (pri2 - pri1)
@@ -1204,9 +1213,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
                 variables so as to avoid excess precision problems that occur
                 on a i386-unknown-sysv4.2 (unixware) host.  */
                 
-             double tmp1 = ((double) local_reg_n_refs[regno]
+             double tmp1 = ((double) local_reg_freq[regno]
                            / local_reg_live_length[regno]);
-             double tmp2 = ((double) allocno[num].n_refs
+             double tmp2 = ((double) allocno[num].freq
                             / allocno[num].live_length);
 
              if (tmp1 < tmp2)
@@ -1256,6 +1265,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
          SET_HARD_REG_BIT (regs_used_so_far, j);
          /* This is no longer a reg used just by local regs.  */
          local_reg_n_refs[j] = 0;
+         local_reg_freq[j] = 0;
        }
       /* For each other pseudo-reg conflicting with this one,
         mark it as conflicting with the hard regs this one occupies.  */
index 177931df4c9c8cbf3403dc02c92becc377c7ff78..0c42ac6e2db2563254dd778f3cdc2232958b6c47 100644 (file)
@@ -1263,12 +1263,19 @@ __eprintf (const char *string, const char *expression,
 
 #ifdef L_bb
 
+#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
+typedef long gcov_type;
+#else
+typedef long long gcov_type;
+#endif
+
+
 /* Structure emitted by -a  */
 struct bb
 {
   long zero_word;
   const char *filename;
-  long *counts;
+  gcov_type *counts;
   long ncounts;
   struct bb *next;
   const unsigned long *addresses;
@@ -1415,9 +1422,9 @@ __bb_exit_func (void)
 
                  for (i = 0; i < n_counts; i++)
                    {
-                     long v = 0;
+                     gcov_type v = 0;
 
-                     if (__read_long (&v, da_file, 8) != 0)
+                     if (__read_gcov_type (&v, da_file, 8) != 0)
                        {
                          fprintf (stderr, "arc profiling: Can't read output file %s.\n",
                                   ptr->filename);
@@ -1439,7 +1446,7 @@ __bb_exit_func (void)
             That way we can easily verify that the proper source/executable/
             data file combination is being used from gcov.  */
 
-         if (__write_long (ptr->ncounts, da_file, 8) != 0)
+         if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
            {
              
              fprintf (stderr, "arc profiling: Error writing output file %s.\n",
@@ -1448,11 +1455,11 @@ __bb_exit_func (void)
          else
            {
              int j;
-             long *count_ptr = ptr->counts;
+             gcov_type *count_ptr = ptr->counts;
              int ret = 0;
              for (j = ptr->ncounts; j > 0; j--)
                {
-                 if (__write_long (*count_ptr, da_file, 8) != 0)
+                 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
                    {
                      ret=1;
                      break;
index 13155f3a6b5e494d7427688deed3d38fa584d0c6..4424074b653519c806dee2eed7aac6af319e0a37 100644 (file)
@@ -85,6 +85,10 @@ struct qty
 
   int n_refs;
 
+  /* The frequency of uses of quantity Q.  */
+
+  int freq;
+
   /* Insn number (counting from head of basic block)
      where quantity Q was born.  -1 if birth has not been recorded.  */
 
@@ -321,6 +325,7 @@ alloc_qty (regno, mode, size, birth)
   qty[qtyno].min_class = reg_preferred_class (regno);
   qty[qtyno].alternate_class = reg_alternate_class (regno);
   qty[qtyno].n_refs = REG_N_REFS (regno);
+  qty[qtyno].freq = REG_FREQ (regno);
   qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
 }
 \f
@@ -1127,6 +1132,7 @@ update_equiv_regs ()
 
                  remove_death (regno, insn);
                  REG_N_REFS (regno) = 0;
+                 REG_FREQ (regno) = 0;
                  PUT_CODE (equiv_insn, NOTE);
                  NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
                  NOTE_SOURCE_FILE (equiv_insn) = 0;
@@ -1697,7 +1703,7 @@ block_alloc (b)
    QTY_CMP_PRI is also used by qty_sugg_compare.  */
 
 #define QTY_CMP_PRI(q)         \
-  ((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].n_refs * qty[q].size) \
+  ((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].freq * qty[q].size) \
          / (qty[q].death - qty[q].birth)) * 10000))
 
 static int
@@ -1966,6 +1972,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
       /* Update info about quantity SQTY.  */
       qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
       qty[sqty].n_refs += REG_N_REFS (sreg);
+      qty[sqty].freq += REG_FREQ (sreg);
       if (usize < ssize)
        {
          register int i;
index 52253082aa50113a3a24ce9f183a5f1db8c77970..37fe3c2e707b1970b742f20de33635f94f9f5701 100644 (file)
@@ -43,11 +43,11 @@ Boston, MA 02111-1307, USA.  */
 #include "regs.h"
 #include "expr.h"
 #include "function.h"
-#include "gcov-io.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
+#include "gcov-io.h"
 
 /* Additional information about the edges we need.  */
 struct edge_info
@@ -59,8 +59,8 @@ struct edge_info
 struct bb_info
   {
     unsigned int count_valid : 1;
-    int succ_count;
-    int pred_count;
+    gcov_type succ_count;
+    gcov_type pred_count;
   };
 
 #define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
@@ -256,8 +256,8 @@ compute_branch_probabilities ()
            num_edges++;
            if (da_file)
              {
-               long value;
-               __read_long (&value, da_file, 8);
+               gcov_type value;
+               __read_gcov_type (&value, da_file, 8);
                e->count = value;
              }
            else
@@ -265,11 +265,18 @@ compute_branch_probabilities ()
            EDGE_INFO (e)->count_valid = 1;
            BB_INFO (bb)->succ_count--;
            BB_INFO (e->dest)->pred_count--;
+           if (rtl_dump_file)
+             {
+               fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
+                        bb->index, e->dest->index);
+               fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
+                        (HOST_WIDEST_INT) e->count);
+             }
          }
     }
 
   if (rtl_dump_file)
-    fprintf (rtl_dump_file, "%d edge counts read\n", num_edges);
+    fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
 
   /* For every block in the file,
      - if every exit/entrance edge has a known count, then set the block count
@@ -303,7 +310,7 @@ compute_branch_probabilities ()
              if (bi->succ_count == 0)
                {
                  edge e;
-                 int total = 0;
+                 gcov_type total = 0;
 
                  for (e = bb->succ; e; e = e->succ_next)
                    total += e->count;
@@ -314,7 +321,7 @@ compute_branch_probabilities ()
              else if (bi->pred_count == 0)
                {
                  edge e;
-                 int total = 0;
+                 gcov_type total = 0;
 
                  for (e = bb->pred; e; e = e->pred_next)
                    total += e->count;
@@ -328,7 +335,7 @@ compute_branch_probabilities ()
              if (bi->succ_count == 1)
                {
                  edge e;
-                 int total = 0;
+                 gcov_type total = 0;
 
                  /* One of the counts will be invalid, but it is zero,
                     so adding it in also doesn't hurt.  */
@@ -355,7 +362,7 @@ compute_branch_probabilities ()
              if (bi->pred_count == 1)
                {
                  edge e;
-                 int total = 0;
+                 gcov_type total = 0;
 
                  /* One of the counts will be invalid, but it is zero,
                     so adding it in also doesn't hurt.  */
@@ -411,7 +418,7 @@ compute_branch_probabilities ()
       basic_block bb = BASIC_BLOCK (i);
       edge e;
       rtx insn;
-      int total;
+      gcov_type total;
       rtx note;
 
       total = bb->count;
@@ -1036,14 +1043,14 @@ static rtx
 gen_edge_profiler (edgeno)
      int edgeno;
 {
-  enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0);
+  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
   rtx mem_ref, tmp;
   rtx sequence;
 
   start_sequence ();
 
   tmp = force_reg (Pmode, profiler_label);
-  tmp = plus_constant (tmp, LONG_TYPE_SIZE / BITS_PER_UNIT * edgeno);
+  tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
   mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
 
   tmp = expand_binop (mode, add_optab, mem_ref, const1_rtx,
@@ -1068,7 +1075,7 @@ output_func_start_profiler ()
   char buf[20];
   const char *cfnname;
   rtx table_address;
-  enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0);
+  enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
   int save_flag_inline_functions = flag_inline_functions;
   int save_flag_test_coverage = flag_test_coverage;
   int save_profile_arc_flag = profile_arc_flag;
index 82d90faa525f991d5628235e0d78653d5b4077e5..35f0e09fb02e3a68d0184267bea8d46188580544 100644 (file)
@@ -1059,14 +1059,17 @@ scan_one_insn (insn, pass)
       /* This makes one more setting of new insns's dest.  */
       REG_N_SETS (REGNO (recog_data.operand[0]))++;
       REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
 
       *recog_data.operand_loc[1] = recog_data.operand[0];
       REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
       for (i = recog_data.n_dups - 1; i >= 0; i--)
        if (recog_data.dup_num[i] == 1)
          {
            *recog_data.dup_loc[i] = recog_data.operand[0];
            REG_N_REFS (REGNO (recog_data.operand[0]))++;
+           REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
          }
 
       return PREV_INSN (newinsn);
index 61b9a49ac02d3b1b3cd504ad812865b022dbfb19..3857c829dc1dbc489c6f5d611eeb0f6d528d876d 100644 (file)
@@ -67,6 +67,7 @@ typedef struct reg_info_def
 
                                /* fields set by flow_analysis */
   int refs;                    /* # of times (REG n) is used or set */
+  int freq;                    /* # estimated frequency (REG n) is used or set */
   int deaths;                  /* # of times (REG n) dies */
   int live_length;             /* # of instructions (REG n) is live */
   int calls_crossed;           /* # of calls (REG n) is live across */
@@ -77,11 +78,14 @@ typedef struct reg_info_def
 
 extern varray_type reg_n_info;
 
-/* Indexed by n, gives number of times (REG n) is used or set.
-   References within loops may be counted more times.  */
+/* Indexed by n, gives number of times (REG n) is used or set.  */
 
 #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
 
+/* Estimate frequency of references to register N.  */
+
+#define REG_FREQ(N) (VARRAY_REG (reg_n_info, N)->freq)
+
 /* Indexed by n, gives number of times (REG n) is set.
    ??? both regscan and flow allocate space for this.  We should settle
    on just copy.  */
index 5f08444ec914a76aff3b205a5a1f29c9ff5edc18..7a587a72111552a20448d6452edb37436287f39b 100644 (file)
@@ -1567,7 +1567,7 @@ static void
 count_pseudo (reg)
      int reg;
 {
-  int n_refs = REG_N_REFS (reg);
+  int freq = REG_FREQ (reg);
   int r = reg_renumber[reg];
   int nregs;
 
@@ -1580,11 +1580,11 @@ count_pseudo (reg)
   if (r < 0)
     abort ();
 
-  spill_add_cost[r] += n_refs;
+  spill_add_cost[r] += freq;
 
   nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
   while (nregs-- > 0)
-    spill_cost[r + nregs] += n_refs;
+    spill_cost[r + nregs] += freq;
 }
 
 /* Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the
@@ -1654,9 +1654,9 @@ count_spilled_pseudo (spilled, spilled_nregs, reg)
 
   SET_REGNO_REG_SET (&spilled_pseudos, reg);
 
-  spill_add_cost[r] -= REG_N_REFS (reg);
+  spill_add_cost[r] -= REG_FREQ (reg);
   while (nregs-- > 0)
-    spill_cost[r + nregs] -= REG_N_REFS (reg);
+    spill_cost[r + nregs] -= REG_FREQ (reg);
 }
 
 /* Find reload register to use for reload number ORDER.  */