OSDN Git Service

libcpp/:
[pf3gnuchains/gcc-fork.git] / gcc / profile.c
index 6f89645..c4c7276 100644 (file)
@@ -277,8 +277,20 @@ is_edge_inconsistent (VEC(edge,gc) *edges)
     {
       if (!EDGE_INFO (e)->ignore)
         {
-          if (e->count < 0)
-            return true;
+          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;
@@ -307,20 +319,59 @@ static bool
 is_inconsistent (void)
 {
   basic_block bb;
+  bool inconsistent = false;
   FOR_EACH_BB (bb)
     {
-      if (is_edge_inconsistent (bb->preds))
-        return true;
-      if (is_edge_inconsistent (bb->succs))
-        return true;
-      if ( bb->count != sum_edge_counts (bb->preds)
-         || (bb->count != sum_edge_counts (bb->succs) &&
-             !(find_edge (bb, EXIT_BLOCK_PTR) != NULL &&
-               block_ends_with_call_p (bb))))
-        return true;
+      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 incomming 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)))
+       {
+         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;
     }
 
-  return false;
+  return inconsistent;
 }
 
 /* Set each basic block count to the sum of its outgoing edge counts */
@@ -402,19 +453,18 @@ compute_branch_probabilities (void)
   int inconsistent = 0;
 
   /* Very simple sanity checks so we catch bugs in our profiling code.  */
-  if (profile_info)
+  if (!profile_info)
+    return;
+  if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
     {
-      if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
-        {
-          error ("corrupted profile info: run_max * runs < sum_max");
-          exec_counts = NULL;
-        }
+      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;
-        }
+  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.  */
@@ -695,6 +745,7 @@ compute_branch_probabilities (void)
        }
     }
   counts_to_freqs ();
+  profile_status = PROFILE_READ;
 
   if (dump_file)
     {
@@ -909,10 +960,12 @@ branch_prob (void)
              && (LOCATION_FILE (e->goto_locus)
                  != LOCATION_FILE (gimple_location (last))
                  || (LOCATION_LINE (e->goto_locus)
-                     != LOCATION_LINE (gimple_location  (last)))))
+                     != LOCATION_LINE (gimple_location (last)))))
            {
              basic_block new_bb = split_edge (e);
-             single_succ_edge (new_bb)->goto_locus = e->goto_locus;
+             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)
@@ -1154,8 +1207,6 @@ branch_prob (void)
 
   VEC_free (histogram_value, heap, values);
   free_edge_list (el);
-  if (flag_branch_probabilities && profile_info)
-    profile_status = PROFILE_READ;
   coverage_end_function ();
 }
 \f