OSDN Git Service

2010-01-22 Steve Ellcey <sje@cup.hp.com>
[pf3gnuchains/gcc-fork.git] / gcc / profile.c
index d260d66..ac46046 100644 (file)
@@ -1,6 +1,7 @@
 /* Calculate branch probabilities, and basic block execution counts.
    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
    based on some ideas from Dain Samples of UC Berkeley.
    Further mangling by Bob Manson, Cygnus Support.
@@ -9,7 +10,7 @@ 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
@@ -18,9 +19,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
-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/>.  */
 
 /* Generate basic block profile instrumentation and auxiliary files.
    Profile generation is optimized, so that not all arcs in the basic
@@ -69,27 +69,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "cfgloop.h"
 #include "tree-pass.h"
 
+#include "profile.h"
+
 /* Hooks for profiling.  */
 static struct profile_hooks* profile_hooks;
 
-/* File for profiling debug output.  */
-static inline FILE*
-profile_dump_file (void) {
-  return profile_hooks->profile_dump_file ();
-}
-
-/* Additional information about the edges we need.  */
-struct edge_info {
-  unsigned int count_valid : 1;
-
-  /* Is on the spanning tree.  */
-  unsigned int on_tree : 1;
-
-  /* Pretend this edge does not exist (it is abnormal and we've
-     inserted a fake to compensate).  */
-  unsigned int ignore : 1;
-};
-
 struct bb_info {
   unsigned int count_valid : 1;
 
@@ -98,9 +82,9 @@ struct bb_info {
   gcov_type pred_count;
 };
 
-#define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
 #define BB_INFO(b)  ((struct bb_info *) (b)->aux)
 
+
 /* Counter summary from the last set of coverage counts read.  */
 
 const struct gcov_ctr_summary *profile_info;
@@ -116,7 +100,6 @@ static int total_num_blocks_created;
 static int total_num_passes;
 static int total_num_times_called;
 static int total_hist_br_prob[20];
-static int total_num_never_executed;
 static int total_num_branches;
 
 /* Forward declarations.  */
@@ -129,7 +112,6 @@ static gcov_type * get_exec_counts (void);
 static basic_block find_group (basic_block);
 static void union_groups (basic_block, basic_block);
 
-\f
 /* Add edge instrumentation code to the entire insn chain.
 
    F is the first insn of the chain.
@@ -198,6 +180,18 @@ instrument_values (histogram_values values)
          t = GCOV_COUNTER_V_DELTA;
          break;
 
+       case HIST_TYPE_INDIR_CALL:
+         t = GCOV_COUNTER_V_INDIR;
+         break;
+
+       case HIST_TYPE_AVERAGE:
+         t = GCOV_COUNTER_AVERAGE;
+         break;
+
+       case HIST_TYPE_IOR:
+         t = GCOV_COUNTER_IOR;
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -222,11 +216,22 @@ instrument_values (histogram_values values)
          (profile_hooks->gen_const_delta_profiler) (hist, t, 0);
          break;
 
+       case HIST_TYPE_INDIR_CALL:
+         (profile_hooks->gen_ic_profiler) (hist, t, 0);
+         break;
+
+       case HIST_TYPE_AVERAGE:
+         (profile_hooks->gen_average_profiler) (hist, t, 0);
+         break;
+
+       case HIST_TYPE_IOR:
+         (profile_hooks->gen_ior_profiler) (hist, t, 0);
+         break;
+
        default:
          gcc_unreachable ();
        }
     }
-  VEC_free (histogram_value, heap, values);
 }
 \f
 
@@ -260,64 +265,135 @@ get_exec_counts (void)
 
   return counts;
 }
-\f
 
-/* Compute the branch probabilities for the various branches.
-   Annotate them accordingly.  */
+
+static bool
+is_edge_inconsistent (VEC(edge,gc) *edges)
+{
+  edge e;
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, edges)
+    {
+      if (!EDGE_INFO (e)->ignore)
+        {
+          if (e->count < 0
+             && (!(e->flags & EDGE_FAKE)
+                 || !block_ends_with_call_p (e->src)))
+           {
+             if (dump_file)
+               {
+                 fprintf (dump_file,
+                          "Edge %i->%i is inconsistent, count"HOST_WIDEST_INT_PRINT_DEC,
+                          e->src->index, e->dest->index, e->count);
+                 dump_bb (e->src, dump_file, 0);
+                 dump_bb (e->dest, dump_file, 0);
+               }
+              return true;
+           }
+        }
+    }
+  return false;
+}
 
 static void
-compute_branch_probabilities (void)
+correct_negative_edge_counts (void)
 {
   basic_block bb;
-  int i;
-  int num_edges = 0;
-  int changes;
-  int passes;
-  int hist_br_prob[20];
-  int num_never_executed;
-  int num_branches;
-  gcov_type *exec_counts = get_exec_counts ();
-  int exec_counts_pos = 0;
+  edge e;
+  edge_iterator ei;
 
-  /* Very simple sanity checks so we catch bugs in our profiling code.  */
-  if (profile_info)
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
-      if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
-       {
-         error ("corrupted profile info: run_max * runs < sum_max");
-         exec_counts = NULL;
-       }
+      FOR_EACH_EDGE (e, ei, bb->succs)
+        {
+           if (e->count < 0)
+             e->count = 0;
+        }
+    }
+}
 
-      if (profile_info->sum_all < profile_info->sum_max)
+/* Check consistency.
+   Return true if inconsistency is found.  */
+static bool
+is_inconsistent (void)
+{
+  basic_block bb;
+  bool inconsistent = false;
+  FOR_EACH_BB (bb)
+    {
+      inconsistent |= is_edge_inconsistent (bb->preds);
+      if (!dump_file && inconsistent)
+       return true;
+      inconsistent |= is_edge_inconsistent (bb->succs);
+      if (!dump_file && inconsistent)
+       return true;
+      if (bb->count < 0)
+        {
+         if (dump_file)
+           {
+             fprintf (dump_file, "BB %i count is negative "
+                      HOST_WIDEST_INT_PRINT_DEC,
+                      bb->index,
+                      bb->count);
+             dump_bb (bb, dump_file, 0);
+           }
+         inconsistent = true;
+       }
+      if (bb->count != sum_edge_counts (bb->preds))
+        {
+         if (dump_file)
+           {
+             fprintf (dump_file, "BB %i count does not match sum of incoming edges "
+                      HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC,
+                      bb->index,
+                      bb->count,
+                      sum_edge_counts (bb->preds));
+             dump_bb (bb, dump_file, 0);
+           }
+         inconsistent = true;
+       }
+      if (bb->count != sum_edge_counts (bb->succs) &&
+          ! (find_edge (bb, EXIT_BLOCK_PTR) != NULL && block_ends_with_call_p (bb)))
        {
-         error ("corrupted profile info: sum_all is smaller than sum_max");
-         exec_counts = NULL;
+         if (dump_file)
+           {
+             fprintf (dump_file, "BB %i count does not match sum of outgoing edges "
+                      HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC,
+                      bb->index,
+                      bb->count,
+                      sum_edge_counts (bb->succs));
+             dump_bb (bb, dump_file, 0);
+           }
+         inconsistent = true;
        }
+      if (!dump_file && inconsistent)
+       return true;
     }
 
-  /* Attach extra info block to each bb.  */
+  return inconsistent;
+}
 
-  alloc_aux_for_blocks (sizeof (struct bb_info));
+/* Set each basic block count to the sum of its outgoing edge counts */
+static void
+set_bb_counts (void)
+{
+  basic_block bb;
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
-      edge e;
-      edge_iterator ei;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       if (!EDGE_INFO (e)->ignore)
-         BB_INFO (bb)->succ_count++;
-      FOR_EACH_EDGE (e, ei, bb->preds)
-       if (!EDGE_INFO (e)->ignore)
-         BB_INFO (bb)->pred_count++;
+      bb->count = sum_edge_counts (bb->succs);
+      gcc_assert (bb->count >= 0);
     }
+}
 
-  /* Avoid predicting entry on exit nodes.  */
-  BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
-  BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
-
+/* Reads profile data and returns total number of edge counts read */
+static int
+read_profile_edge_counts (gcov_type *exec_counts)
+{
+  basic_block bb;
+  int num_edges = 0;
+  int exec_counts_pos = 0;
   /* For each edge not on the spanning tree, set its execution count from
      the .da file.  */
-
   /* The first count in the .da file is the number of times that the function
      was entered.  This is the exec_count for block zero.  */
 
@@ -355,6 +431,61 @@ compute_branch_probabilities (void)
          }
     }
 
+    return num_edges;
+}
+
+/* Compute the branch probabilities for the various branches.
+   Annotate them accordingly.  */
+
+static void
+compute_branch_probabilities (void)
+{
+  basic_block bb;
+  int i;
+  int num_edges = 0;
+  int changes;
+  int passes;
+  int hist_br_prob[20];
+  int num_branches;
+  gcov_type *exec_counts = get_exec_counts ();
+  int inconsistent = 0;
+
+  /* Very simple sanity checks so we catch bugs in our profiling code.  */
+  if (!profile_info)
+    return;
+  if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
+    {
+      error ("corrupted profile info: run_max * runs < sum_max");
+      exec_counts = NULL;
+    }
+
+  if (profile_info->sum_all < profile_info->sum_max)
+    {
+      error ("corrupted profile info: sum_all is smaller than sum_max");
+      exec_counts = NULL;
+    }
+
+  /* Attach extra info block to each bb.  */
+  alloc_aux_for_blocks (sizeof (struct bb_info));
+  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+    {
+      edge e;
+      edge_iterator ei;
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       if (!EDGE_INFO (e)->ignore)
+         BB_INFO (bb)->succ_count++;
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (!EDGE_INFO (e)->ignore)
+         BB_INFO (bb)->pred_count++;
+    }
+
+  /* Avoid predicting entry on exit nodes.  */
+  BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
+  BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
+
+  num_edges = read_profile_edge_counts (exec_counts);
+
   if (dump_file)
     fprintf (dump_file, "\n%d edge counts read\n", num_edges);
 
@@ -424,7 +555,7 @@ compute_branch_probabilities (void)
                  FOR_EACH_EDGE (e, ei, bb->succs)
                    total += e->count;
 
-                 /* Seedgeh for the invalid edge, and set its count.  */
+                 /* Search for the invalid edge, and set its count.  */
                  FOR_EACH_EDGE (e, ei, bb->succs)
                    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
                      break;
@@ -471,7 +602,7 @@ compute_branch_probabilities (void)
        }
     }
   if (dump_file)
-    dump_flow_info (dump_file);
+    dump_flow_info (dump_file, dump_flags);
 
   total_num_passes += passes;
   if (dump_file)
@@ -484,19 +615,42 @@ compute_branch_probabilities (void)
       gcc_assert (!BB_INFO (bb)->succ_count && !BB_INFO (bb)->pred_count);
     }
 
+  /* Check for inconsistent basic block counts */
+  inconsistent = is_inconsistent ();
+
+  if (inconsistent)
+   {
+     if (flag_profile_correction)
+       {
+         /* Inconsistency detected. Make it flow-consistent. */
+         static int informed = 0;
+         if (informed == 0)
+           {
+             informed = 1;
+             inform (input_location, "correcting inconsistent profile data");
+           }
+         correct_negative_edge_counts ();
+         /* Set bb counts to the sum of the outgoing edge counts */
+         set_bb_counts ();
+         if (dump_file)
+           fprintf (dump_file, "\nCalling mcf_smooth_cfg\n");
+         mcf_smooth_cfg ();
+       }
+     else
+       error ("corrupted profile info: profile data is not flow-consistent");
+   }
+
   /* For every edge, calculate its branch probability and add a reg_note
      to the branch insn to indicate this.  */
 
   for (i = 0; i < 20; i++)
     hist_br_prob[i] = 0;
-  num_never_executed = 0;
   num_branches = 0;
 
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
     {
       edge e;
       edge_iterator ei;
-      rtx note;
 
       if (bb->count < 0)
        {
@@ -531,7 +685,7 @@ compute_branch_probabilities (void)
        {
          FOR_EACH_EDGE (e, ei, bb->succs)
            e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
-         if (bb->index >= 0
+         if (bb->index >= NUM_FIXED_BLOCKS
              && block_ends_with_condjump_p (bb)
              && EDGE_COUNT (bb->succs) >= 2)
            {
@@ -552,37 +706,9 @@ compute_branch_probabilities (void)
                index = 19;
              hist_br_prob[index]++;
 
-             /* Do this for RTL only.  */
-             if (!ir_type ())
-               {
-                 note = find_reg_note (BB_END (bb), REG_BR_PROB, 0);
-                 /* There may be already note put by some other pass, such
-                    as builtin_expect expander.  */
-                 if (note)
-                   XEXP (note, 0) = GEN_INT (prob);
-                 else
-                   REG_NOTES (BB_END (bb))
-                     = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
-                                          REG_NOTES (BB_END (bb)));
-               }
              num_branches++;
            }
        }
-      /* Otherwise try to preserve the existing REG_BR_PROB probabilities
-         tree based profile guessing put into code.  BB can be the
-        ENTRY_BLOCK, and it can have multiple (fake) successors in
-        EH cases, but it still has no code; don't crash in this case.  */
-      else if (profile_status == PROFILE_ABSENT
-              && !ir_type ()
-              && EDGE_COUNT (bb->succs) > 1
-              && BB_END (bb)
-              && (note = find_reg_note (BB_END (bb), REG_BR_PROB, 0)))
-       {
-         int prob = INTVAL (XEXP (note, 0));
-
-         BRANCH_EDGE (bb)->probability = prob;
-         FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
-       }
       /* As a last resort, distribute the probabilities evenly.
         Use simple heuristics that if there are normal edges,
         give all abnormals frequency of 0, otherwise distribute the
@@ -609,19 +735,18 @@ compute_branch_probabilities (void)
              FOR_EACH_EDGE (e, ei, bb->succs)
                e->probability = REG_BR_PROB_BASE / total;
            }
-         if (bb->index >= 0
+         if (bb->index >= NUM_FIXED_BLOCKS
              && block_ends_with_condjump_p (bb)
              && EDGE_COUNT (bb->succs) >= 2)
-           num_branches++, num_never_executed;
+           num_branches++;
        }
     }
   counts_to_freqs ();
+  profile_status = PROFILE_READ;
 
   if (dump_file)
     {
       fprintf (dump_file, "%d branches\n", num_branches);
-      fprintf (dump_file, "%d branches never executed\n",
-              num_never_executed);
       if (num_branches)
        for (i = 0; i < 10; i++)
          fprintf (dump_file, "%d%% branches in range %d-%d%%\n",
@@ -629,7 +754,6 @@ compute_branch_probabilities (void)
                   5 * i, 5 * i + 5);
 
       total_num_branches += num_branches;
-      total_num_never_executed += num_never_executed;
       for (i = 0; i < 20; i++)
        total_hist_br_prob[i] += hist_br_prob[i];
 
@@ -651,7 +775,7 @@ compute_value_histograms (histogram_values values)
   gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS];
   gcov_type *act_count[GCOV_N_VALUE_COUNTERS];
   gcov_type *aact_count;
+
   for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
     n_histogram_counters[t] = 0;
 
@@ -683,18 +807,15 @@ compute_value_histograms (histogram_values values)
   for (i = 0; i < VEC_length (histogram_value, values); i++)
     {
       histogram_value hist = VEC_index (histogram_value, values, i);
-      tree stmt = hist->hvalue.stmt;
-      stmt_ann_t ann = get_stmt_ann (stmt);
+      gimple stmt = hist->hvalue.stmt;
 
       t = (int) hist->type;
 
       aact_count = act_count[t];
       act_count[t] += hist->n_counters;
 
-      hist->hvalue.next = ann->histograms;
-      ann->histograms = hist;
-      hist->hvalue.counters = 
-           xmalloc (sizeof (gcov_type) * hist->n_counters);
+      gimple_add_histogram_value (cfun, stmt, hist);
+      hist->hvalue.counters =  XNEWVEC (gcov_type, hist->n_counters);
       for (j = 0; j < hist->n_counters; j++)
        hist->hvalue.counters[j] = aact_count[j];
     }
@@ -704,7 +825,9 @@ compute_value_histograms (histogram_values values)
       free (histogram_counts[t]);
 }
 
-#define BB_TO_GCOV_INDEX(bb)  ((bb)->index + 1)
+/* The entry basic block will be moved around so that it has index=1,
+   there is nothing at index 0 and the exit is at n_basic_block.  */
+#define BB_TO_GCOV_INDEX(bb)  ((bb)->index - 1)
 /* When passed NULL as file_name, initialize.
    When passed something else, output the necessary commands to change
    line to LINE and offset to FILE_NAME.  */
@@ -806,39 +929,37 @@ branch_prob (void)
 
       FOR_EACH_EDGE (e, ei, bb->succs)
        {
-         block_stmt_iterator bsi;
-         tree last = NULL;
+         gimple_stmt_iterator gsi;
+         gimple last = NULL;
 
          /* It may happen that there are compiler generated statements
             without a locus at all.  Go through the basic block from the
             last to the first statement looking for a locus.  */
-         for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
+         for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
            {
-             last = bsi_stmt (bsi);
-             if (EXPR_LOCUS (last))
+             last = gsi_stmt (gsi);
+             if (gimple_has_location (last))
                break;
            }
 
          /* Edge with goto locus might get wrong coverage info unless
-            it is the only edge out of BB.   
-            Don't do that when the locuses match, so 
+            it is the only edge out of BB.
+            Don't do that when the locuses match, so
             if (blah) goto something;
             is not computed twice.  */
-         if (last && EXPR_LOCUS (last)
-             && e->goto_locus
+         if (last
+             && gimple_has_location (last)
+             && e->goto_locus != UNKNOWN_LOCATION
              && !single_succ_p (bb)
-#ifdef USE_MAPPED_LOCATION
              && (LOCATION_FILE (e->goto_locus)
-                 != LOCATION_FILE (EXPR_LOCATION  (last))
+                 != LOCATION_FILE (gimple_location (last))
                  || (LOCATION_LINE (e->goto_locus)
-                     != LOCATION_LINE (EXPR_LOCATION  (last)))))
-#else
-             && (e->goto_locus->file != EXPR_LOCUS (last)->file
-                 || (e->goto_locus->line != EXPR_LOCUS (last)->line)))
-#endif
+                     != LOCATION_LINE (gimple_location (last)))))
            {
-             basic_block new = split_edge (e);
-             single_succ_edge (new)->goto_locus = e->goto_locus;
+             basic_block new_bb = split_edge (e);
+             edge ne = single_succ_edge (new_bb);
+             ne->goto_locus = e->goto_locus;
+             ne->goto_block = e->goto_block;
            }
          if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
               && e->dest != EXIT_BLOCK_PTR)
@@ -917,7 +1038,7 @@ branch_prob (void)
        num_instrumented++;
     }
 
-  total_num_blocks += n_basic_blocks + 2;
+  total_num_blocks += n_basic_blocks;
   if (dump_file)
     fprintf (dump_file, "%d basic blocks\n", n_basic_blocks);
 
@@ -938,7 +1059,7 @@ branch_prob (void)
       gcov_position_t offset;
 
       offset = gcov_write_tag (GCOV_TAG_BLOCKS);
-      for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
+      for (i = 0; i != (unsigned) (n_basic_blocks); i++)
        gcov_write_unsigned (0);
       gcov_write_length (offset);
     }
@@ -946,7 +1067,7 @@ branch_prob (void)
    /* Keep all basic block indexes nonnegative in the gcov output.
       Index 0 is used for entry block, last index is for exit block.
       */
-  ENTRY_BLOCK_PTR->index = -1;
+  ENTRY_BLOCK_PTR->index = 1;
   EXIT_BLOCK_PTR->index = last_basic_block;
 
   /* Arcs */
@@ -977,8 +1098,7 @@ branch_prob (void)
                    flag_bits |= GCOV_ARC_FALLTHROUGH;
                  /* On trees we don't have fallthru flags, but we can
                     recompute them from CFG shape.  */
-                 if (ir_type ()
-                     && e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)
+                 if (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)
                      && e->src->next_bb == e->dest)
                    flag_bits |= GCOV_ARC_FALLTHROUGH;
 
@@ -994,116 +1114,52 @@ branch_prob (void)
   /* Line numbers.  */
   if (coverage_begin_output ())
     {
+      gcov_position_t offset;
+
       /* Initialize the output.  */
       output_location (NULL, 0, NULL, NULL);
 
-      if (!ir_type ())
+      FOR_EACH_BB (bb)
        {
-         gcov_position_t offset;
-
-         FOR_EACH_BB (bb)
-           {
-             rtx insn = BB_HEAD (bb);
-             int ignore_next_note = 0;
-
-             offset = 0;
+         gimple_stmt_iterator gsi;
 
-             /* We are looking for line number notes.  Search backward
-                before basic block to find correct ones.  */
-             insn = prev_nonnote_insn (insn);
-             if (!insn)
-               insn = get_insns ();
-             else
-               insn = NEXT_INSN (insn);
+         offset = 0;
 
-             while (insn != BB_END (bb))
-               {
-                 if (NOTE_P (insn))
-                   {
-                     /* Must ignore the line number notes that
-                        immediately follow the end of an inline function
-                        to avoid counting it twice.  There is a note
-                        before the call, and one after the call.  */
-                     if (NOTE_LINE_NUMBER (insn)
-                         == NOTE_INSN_REPEATED_LINE_NUMBER)
-                       ignore_next_note = 1;
-                     else if (NOTE_LINE_NUMBER (insn) <= 0)
-                       /*NOP*/;
-                     else if (ignore_next_note)
-                       ignore_next_note = 0;
-                     else
-                       {
-                         expanded_location s;
-                         NOTE_EXPANDED_LOCATION (s, insn);
-                         output_location (s.file, s.line, &offset, bb);
-                       }
-                   }
-                 insn = NEXT_INSN (insn);
-               }
-
-             if (offset)
-               {
-                 /* A file of NULL indicates the end of run.  */
-                 gcov_write_unsigned (0);
-                 gcov_write_string (NULL);
-                 gcov_write_length (offset);
-               }
+         if (bb == ENTRY_BLOCK_PTR->next_bb)
+           {
+             expanded_location curr_location =
+               expand_location (DECL_SOURCE_LOCATION (current_function_decl));
+             output_location (curr_location.file, curr_location.line,
+                              &offset, bb);
            }
-       }
-      else
-       {
-         gcov_position_t offset;
 
-         FOR_EACH_BB (bb)
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
            {
-             block_stmt_iterator bsi;
-
-             offset = 0;
-
-             if (bb == ENTRY_BLOCK_PTR->next_bb)
-               {
-                 expanded_location curr_location = 
-                   expand_location (DECL_SOURCE_LOCATION
-                                    (current_function_decl));
-                 output_location (curr_location.file, curr_location.line,
-                                  &offset, bb);
-               }
-
-             for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-               {
-                 tree stmt = bsi_stmt (bsi);
-                 if (EXPR_HAS_LOCATION (stmt))
-                   output_location (EXPR_FILENAME (stmt), 
-                                    EXPR_LINENO (stmt),
-                                    &offset, bb);
-               }
+             gimple stmt = gsi_stmt (gsi);
+             if (gimple_has_location (stmt))
+               output_location (gimple_filename (stmt), gimple_lineno (stmt),
+                                &offset, bb);
+           }
 
-             /* Notice GOTO expressions we eliminated while constructing the
-                CFG.  */
-             if (single_succ_p (bb) && single_succ_edge (bb)->goto_locus)
-               {
-                 /* ??? source_locus type is marked deprecated in input.h.  */
-                 source_locus curr_location = single_succ_edge (bb)->goto_locus;
-                 /* ??? The FILE/LINE API is inconsistent for these cases.  */
-#ifdef USE_MAPPED_LOCATION 
-                 output_location (LOCATION_FILE (curr_location),
-                                  LOCATION_LINE (curr_location),
-                                  &offset, bb);
-#else
-                 output_location (curr_location->file, curr_location->line,
-                                  &offset, bb);
-#endif
-               }
+         /* Notice GOTO expressions we eliminated while constructing the
+            CFG.  */
+         if (single_succ_p (bb)
+             && single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
+           {
+             location_t curr_location = single_succ_edge (bb)->goto_locus;
+             /* ??? The FILE/LINE API is inconsistent for these cases.  */
+             output_location (LOCATION_FILE (curr_location),
+                              LOCATION_LINE (curr_location), &offset, bb);
+           }
 
-             if (offset)
-               {
-                 /* A file of NULL indicates the end of run.  */
-                 gcov_write_unsigned (0);
-                 gcov_write_string (NULL);
-                 gcov_write_length (offset);
-               }
+         if (offset)
+           {
+             /* A file of NULL indicates the end of run.  */
+             gcov_write_unsigned (0);
+             gcov_write_string (NULL);
+             gcov_write_length (offset);
            }
-        }
+       }
     }
 
   ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
@@ -1138,29 +1194,13 @@ branch_prob (void)
        instrument_values (values);
 
       /* Commit changes done by instrumentation.  */
-      if (ir_type ())
-       bsi_commit_edge_inserts ();
-      else
-       {
-          commit_edge_insertions_watch_calls ();
-         allocate_reg_info (max_reg_num (), FALSE, FALSE);
-       }
+      gsi_commit_edge_inserts ();
     }
 
   free_aux_for_edges ();
 
-  if (!ir_type ())
-    {
-      /* Re-merge split basic blocks and the mess introduced by
-        insert_insn_on_edge.  */
-      cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
-      if (profile_dump_file())
-       dump_flow_info (profile_dump_file());
-    }
-
+  VEC_free (histogram_value, heap, values);
   free_edge_list (el);
-  if (flag_branch_probabilities)
-    profile_status = PROFILE_READ;
   coverage_end_function ();
 }
 \f
@@ -1287,7 +1327,6 @@ init_branch_prob (void)
   total_num_passes = 0;
   total_num_times_called = 0;
   total_num_branches = 0;
-  total_num_never_executed = 0;
   for (i = 0; i < 20; i++)
     total_hist_br_prob[i] = 0;
 }
@@ -1318,8 +1357,6 @@ end_branch_prob (void)
                 / total_num_times_called);
       fprintf (dump_file, "Total number of branches: %d\n",
               total_num_branches);
-      fprintf (dump_file, "Total number of branches never executed: %d\n",
-              total_num_never_executed);
       if (total_num_branches)
        {
          int i;
@@ -1337,49 +1374,6 @@ end_branch_prob (void)
 void
 tree_register_profile_hooks (void)
 {
-  gcc_assert (ir_type ());
+  gcc_assert (current_ir_type () == IR_GIMPLE);
   profile_hooks = &tree_profile_hooks;
 }
-
-\f
-/* Do branch profiling and static profile estimation passes.  */
-static void
-rest_of_handle_branch_prob (void)
-{
-  struct loops loops;
-
-  /* Discover and record the loop depth at the head of each basic
-     block.  The loop infrastructure does the real job for us.  */
-  flow_loops_find (&loops);
-
-  if (dump_file)
-    flow_loops_dump (&loops, dump_file, NULL, 0);
-
-  /* Estimate using heuristics if no profiling info is available.  */
-  if (flag_guess_branch_prob
-      && profile_status == PROFILE_ABSENT)
-    estimate_probability (&loops);
-
-  flow_loops_free (&loops);
-  free_dominance_info (CDI_DOMINATORS);
-}
-
-struct tree_opt_pass pass_branch_prob =
-{
-  "bp",                                 /* name */
-  NULL,                                 /* gate */   
-  rest_of_handle_branch_prob,           /* execute */       
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_BRANCH_PROB,                       /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'b'                                   /* letter */
-};
-
-
-