OSDN Git Service

PR c++/29175
[pf3gnuchains/gcc-fork.git] / gcc / value-prof.c
index b9594f1..6c64e3c 100644 (file)
@@ -42,15 +42,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "gcov-io.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "toplev.h"
 
 static struct value_prof_hooks *value_prof_hooks;
 
-/* This is the vector of histograms.  Created in find_values_to_profile.
-   During profile generation, freed by instrument_values.
-   During profile use, freed by value_profile_transformations.  */
-
-static histogram_values static_values = NULL;
-
 /* In this file value profile based optimizations are placed.  Currently the
    following optimizations are implemented (for more detailed descriptions
    see comments at value_profile_transformations):
@@ -85,6 +80,25 @@ static bool tree_divmod_fixed_value_transform (tree);
 static bool tree_mod_pow2_value_transform (tree);
 static bool tree_mod_subtract_transform (tree);
 
+/* The overall number of invocations of the counter should match execution count
+   of basic block.  Report it as error rather than internal error as it might
+   mean that user has misused the profile somehow.  */
+static bool
+check_counter (tree stmt, const char * name, gcov_type all, gcov_type bb_count)
+{
+  if (all != bb_count)
+    {
+      location_t * locus;
+      locus = (stmt != NULL && EXPR_HAS_LOCATION (stmt)
+              ? EXPR_LOCUS (stmt)
+              : &DECL_SOURCE_LOCATION (current_function_decl));
+      error ("%HCorrupted value profile: %s profiler overall count (%d) does not match BB count (%d)",
+            locus, name, (int)all, (int)bb_count);
+      return true;
+    }
+  return false;
+}
+
 /* Tree based transformations. */
 static bool
 tree_value_profile_transformations (void)
@@ -127,7 +141,11 @@ tree_value_profile_transformations (void)
            {
              changed = true;
              /* Original statement may no longer be in the same block. */
-             bb = bb_for_stmt (stmt);
+             if (bb != bb_for_stmt (stmt))
+               {
+                 bb = bb_for_stmt (stmt);
+                 bsi = bsi_for_stmt (stmt);
+               }
            }
 
          /* Free extra storage from compute_value_histograms.  */
@@ -286,6 +304,9 @@ tree_divmod_fixed_value_transform (tree stmt)
   if (simple_cst_equal (op2, value) != 1 || 2 * count < all)
     return false;
 
+  if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
+    return false;
+
   /* Compute probability of taking the optimal path.  */
   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
 
@@ -319,7 +340,7 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
               gcov_type count, gcov_type all)
 {
   tree stmt1, stmt2, stmt3, stmt4;
-  tree tmp1, tmp2, tmp3;
+  tree tmp2, tmp3;
   tree label_decl1 = create_artificial_label ();
   tree label_decl2 = create_artificial_label ();
   tree label_decl3 = create_artificial_label ();
@@ -334,19 +355,17 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
   bb = bb_for_stmt (stmt);
   bsi = bsi_for_stmt (stmt);
 
-  tmp1 = create_tmp_var (optype, "PROF");
   tmp2 = create_tmp_var (optype, "PROF");
   tmp3 = create_tmp_var (optype, "PROF");
-  stmt1 = build2 (MODIFY_EXPR, optype, tmp1, fold_convert (optype, op2));
   stmt2 = build2 (MODIFY_EXPR, optype, tmp2, 
-                   build2 (PLUS_EXPR, optype, op2, integer_minus_one_node));
+                 build2 (PLUS_EXPR, optype, op2, build_int_cst (optype, -1)));
   stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
-                   build2 (BIT_AND_EXPR, optype, tmp2, tmp1));
+                 build2 (BIT_AND_EXPR, optype, tmp2, op2));
   stmt4 = build3 (COND_EXPR, void_type_node,
-           build2 (NE_EXPR, boolean_type_node, tmp3, integer_zero_node),
-           build1 (GOTO_EXPR, void_type_node, label_decl2),
-           build1 (GOTO_EXPR, void_type_node, label_decl1));
-  bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
+                 build2 (NE_EXPR, boolean_type_node,
+                         tmp3, build_int_cst (optype, 0)),
+                 build1 (GOTO_EXPR, void_type_node, label_decl2),
+                 build1 (GOTO_EXPR, void_type_node, label_decl1));
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
@@ -457,6 +476,9 @@ tree_mod_pow2_value_transform (tree stmt)
 
   /* Compute probability of taking the optimal path.  */
   all = count + wrong_values;
+  if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
+    return false;
+
   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
 
   result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
@@ -631,6 +653,10 @@ tree_mod_subtract_transform (tree stmt)
   wrong_values += histogram->hvalue.counters[i+1];
   all += wrong_values;
 
+  /* Compute probability of taking the optimal path.  */
+  if (check_counter (stmt, "interval", all, bb_for_stmt (stmt)->count))
+    return false;
+
   /* We require that we use just subtractions in at least 50% of all
      evaluations.  */
   count = 0;
@@ -765,7 +791,6 @@ tree_find_values_to_profile (histogram_values *values)
   FOR_EACH_BB (bb)
     for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
       tree_values_to_profile (bsi_stmt (bsi), values);
-  static_values = *values;
   
   for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
     {
@@ -843,9 +868,7 @@ find_values_to_profile (histogram_values *values)
 bool
 value_profile_transformations (void)
 {
-  bool retval = (value_prof_hooks->value_profile_transformations) ();
-  VEC_free (histogram_value, heap, static_values);
-  return retval;
+  return (value_prof_hooks->value_profile_transformations) ();
 }
 \f