re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / profile.c
index e549453bfad6950e9a16ceab193f806cb40f5b8d..754326b3a362eec8b2d0ee1b57a39aa8994b3b77 100644 (file)
@@ -1,5 +1,5 @@
 /* Calculate branch probabilities, and basic block execution counts.
-   Copyright (C) 1990-2014 Free Software Foundation, Inc.
+   Copyright (C) 1990-2015 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.
@@ -54,17 +54,32 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtl.h"
 #include "flags.h"
 #include "regs.h"
-#include "expr.h"
+#include "symtab.h"
+#include "hard-reg-set.h"
 #include "function.h"
+#include "alias.h"
+#include "tree.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
 #include "basic-block.h"
 #include "diagnostic-core.h"
 #include "coverage.h"
 #include "value-prof.h"
-#include "tree.h"
+#include "fold-const.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
@@ -74,7 +89,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "profile.h"
 
-struct bb_info {
+struct bb_profile_info {
   unsigned int count_valid : 1;
 
   /* Number of successor and predecessor edges.  */
@@ -82,7 +97,7 @@ struct bb_info {
   gcov_type pred_count;
 };
 
-#define BB_INFO(b)  ((struct bb_info *) (b)->aux)
+#define BB_INFO(b)  ((struct bb_profile_info *) (b)->aux)
 
 
 /* Counter summary from the last set of coverage counts read.  */
@@ -106,6 +121,14 @@ static int total_num_times_called;
 static int total_hist_br_prob[20];
 static int total_num_branches;
 
+/* Helper function to update gcov_working_sets.  */
+
+void add_working_set (gcov_working_set_t *set) {
+  int i = 0;
+  for (; i < NUM_GCOV_WORKING_SETS; i++)
+    gcov_working_sets[i] = set[i];
+}
+
 /* Forward declarations.  */
 static void find_spanning_tree (struct edge_list *);
 
@@ -128,7 +151,7 @@ instrument_edges (struct edge_list *el)
 
       FOR_EACH_EDGE (e, ei, bb->succs)
        {
-         struct edge_info *inf = EDGE_INFO (e);
+         struct edge_profile_info *inf = EDGE_INFO (e);
 
          if (!inf->ignore && !inf->on_tree)
            {
@@ -183,6 +206,7 @@ instrument_values (histogram_values values)
          break;
 
        case HIST_TYPE_INDIR_CALL:
+       case HIST_TYPE_INDIR_CALL_TOPN:
          gimple_gen_ic_profiler (hist, t, 0);
          break;
 
@@ -237,10 +261,10 @@ get_working_sets (void)
           ws_info = &gcov_working_sets[ws_ix];
           /* Print out the percentage using int arithmatic to avoid float.  */
           fprintf (dump_file, "\t\t%u.%02u%%: num counts=%u, min counter="
-                   HOST_WIDEST_INT_PRINT_DEC "\n",
+                   "%" PRId64 "\n",
                    pct / 100, pct - (pct / 100 * 100),
                    ws_info->num_counters,
-                   (HOST_WIDEST_INT)ws_info->min_counter);
+                   (int64_t)ws_info->min_counter);
         }
     }
 }
@@ -318,7 +342,7 @@ is_edge_inconsistent (vec<edge, va_gc> *edges)
              if (dump_file)
                {
                  fprintf (dump_file,
-                          "Edge %i->%i is inconsistent, count"HOST_WIDEST_INT_PRINT_DEC,
+                          "Edge %i->%i is inconsistent, count%" PRId64,
                           e->src->index, e->dest->index, e->count);
                  dump_bb (dump_file, e->src, 0, TDF_DETAILS);
                  dump_bb (dump_file, e->dest, 0, TDF_DETAILS);
@@ -367,7 +391,7 @@ is_inconsistent (void)
          if (dump_file)
            {
              fprintf (dump_file, "BB %i count is negative "
-                      HOST_WIDEST_INT_PRINT_DEC,
+                      "%" PRId64,
                       bb->index,
                       bb->count);
              dump_bb (dump_file, bb, 0, TDF_DETAILS);
@@ -379,7 +403,7 @@ is_inconsistent (void)
          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,
+                      "%" PRId64" should be %" PRId64,
                       bb->index,
                       bb->count,
                       sum_edge_counts (bb->preds));
@@ -394,7 +418,7 @@ is_inconsistent (void)
          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,
+                      "%" PRId64" should be %" PRId64,
                       bb->index,
                       bb->count,
                       sum_edge_counts (bb->succs));
@@ -471,8 +495,8 @@ read_profile_edge_counts (gcov_type *exec_counts)
              {
                fprintf (dump_file, "\nRead edge from %i to %i, count:",
                         bb->index, e->dest->index);
-               fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
-                        (HOST_WIDEST_INT) e->count);
+               fprintf (dump_file, "%" PRId64,
+                        (int64_t) e->count);
              }
          }
     }
@@ -542,7 +566,7 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
     }
 
   /* Attach extra info block to each bb.  */
-  alloc_aux_for_blocks (sizeof (struct bb_info));
+  alloc_aux_for_blocks (sizeof (struct bb_profile_info));
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
     {
       edge e;
@@ -590,7 +614,7 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
       changes = 0;
       FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), NULL, prev_bb)
        {
-         struct bb_info *bi = BB_INFO (bb);
+         struct bb_profile_info *bi = BB_INFO (bb);
          if (! bi->count_valid)
            {
              if (bi->succ_count == 0)
@@ -918,9 +942,8 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
          the corresponding call graph node.  */
       if (hist->type == HIST_TYPE_TIME_PROFILE)
         {
-          node = cgraph_get_node (hist->fun->decl);
-
-          node->tp_first_run = hist->hvalue.counters[0];
+         node = cgraph_node::get (hist->fun->decl);
+         node->tp_first_run = hist->hvalue.counters[0];
 
           if (dump_file)
             fprintf (dump_file, "Read tp_first_run: %d\n", node->tp_first_run);
@@ -1104,29 +1127,20 @@ branch_prob (void)
            {
              gimple_stmt_iterator gsi;
              gimple first;
-             tree fndecl;
 
-             gsi = gsi_after_labels (bb);
+             gsi = gsi_start_nondebug_after_labels_bb (bb);
              gcc_checking_assert (!gsi_end_p (gsi));
              first = gsi_stmt (gsi);
-             if (is_gimple_debug (first))
-               {
-                 gsi_next_nondebug (&gsi);
-                 gcc_checking_assert (!gsi_end_p (gsi));
-                 first = gsi_stmt (gsi);
-               }
              /* Don't split the bbs containing __builtin_setjmp_receiver
-                or __builtin_setjmp_dispatcher calls.  These are very
+                or ABNORMAL_DISPATCHER calls.  These are very
                 special and don't expect anything to be inserted before
                 them.  */
              if (is_gimple_call (first)
-                 && (((fndecl = gimple_call_fndecl (first)) != NULL
-                      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-                      && (DECL_FUNCTION_CODE (fndecl)
-                          == BUILT_IN_SETJMP_RECEIVER
-                          || (DECL_FUNCTION_CODE (fndecl)
-                              == BUILT_IN_SETJMP_DISPATCHER)))
-                     || gimple_call_flags (first) & ECF_RETURNS_TWICE))
+                 && (gimple_call_builtin_p (first, BUILT_IN_SETJMP_RECEIVER)
+                     || (gimple_call_flags (first) & ECF_RETURNS_TWICE)
+                     || (gimple_call_internal_p (first)
+                         && (gimple_call_internal_fn (first)
+                             == IFN_ABNORMAL_DISPATCHER))))
                continue;
 
              if (dump_file)
@@ -1139,7 +1153,7 @@ branch_prob (void)
 
   el = create_edge_list ();
   num_edges = NUM_EDGES (el);
-  alloc_aux_for_edges (sizeof (struct edge_info));
+  alloc_aux_for_edges (sizeof (struct edge_profile_info));
 
   /* The basic blocks are expected to be numbered sequentially.  */
   compact_blocks ();
@@ -1171,7 +1185,7 @@ branch_prob (void)
   for (num_instrumented = i = 0; i < num_edges; i++)
     {
       edge e = INDEX_EDGE (el, i);
-      struct edge_info *inf = EDGE_INFO (e);
+      struct edge_profile_info *inf = EDGE_INFO (e);
 
       if (inf->ignore || inf->on_tree)
        /*NOP*/;
@@ -1204,7 +1218,7 @@ branch_prob (void)
      the checksum in only once place, since it depends on the shape
      of the control flow which can change during 
      various transformations.  */
-  cfg_checksum = coverage_compute_cfg_checksum ();
+  cfg_checksum = coverage_compute_cfg_checksum (cfun);
   lineno_checksum = coverage_compute_lineno_checksum ();
 
   /* Write the data from which gcov can reconstruct the basic block
@@ -1231,7 +1245,7 @@ branch_prob (void)
 
          FOR_EACH_EDGE (e, ei, bb->succs)
            {
-             struct edge_info *i = EDGE_INFO (e);
+             struct edge_profile_info *i = EDGE_INFO (e);
              if (!i->ignore)
                {
                  unsigned flag_bits = 0;