]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
opts.c (common_handle_option): Do not set flag_value_profile_transformations for...
authorSteven Bosscher <steven@gcc.gnu.org>
Mon, 23 Jul 2012 09:24:21 +0000 (09:24 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Mon, 23 Jul 2012 09:24:21 +0000 (09:24 +0000)
* opts.c (common_handle_option): Do not set
flag_value_profile_transformations for -fprofile-generate.
* profile.c (instrument_values): Use COUNTER_FOR_HIST_TYPE.
(BB_TO_GCOV_INDEX): Remove.
(output_location): Don't use it.
(branch_prob): Likewise.  Don't fiddle with the index of
ENTRY_BLOCK_PTR and EXIT_BLOCK_PTR.  Use clear_aux_for_blocks.
(find_spanning_tree):
* gcov.c (struct function_info): Document that blocks 0 and 1
are the entry resp. exit blocks in gcov, too, like in GCC itself.
(solve_flow_graph): Use ENTRY_BLOCK and EXIT_BLOCK for special
blocks identification.
(output_lines): Likewise.
* value-prof.c (gimple_value_profile_transformations): Do not
test flag_value_profile_transformations again.
(gimple_ic_transform): Take a gimple_stmt_iterator like all other
transformation functions.
(gimple_values_to_profile):
Don't test flag_value_profile_transformations
* tree-profile.c (tree_profiling): Assert that the cgraph is in
the CGRAPH_STATE_IPA_SSA state.
Do not set, or look at, after_tree_profile.
* function.h (struct function): Remove after_tree_profile bit.
* omp-low.c (expand_omp_taskreg): Don't set after_tree_profile.
* tree-inline.c (initialize_cfun): Don't copy it.
* lto-streamer-out.c (output_struct_function_base): Don't stream it.
* lto-streamer-in.c (input_struct_function_base): Likewise.

From-SVN: r189778

gcc/ChangeLog
gcc/function.h
gcc/gcov.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/omp-low.c
gcc/opts.c
gcc/profile.c
gcc/tree-inline.c
gcc/tree-profile.c
gcc/value-prof.c

index 2b04ab700c4648346d3545d3e9ecb546e0fae559..68800a6640068927f89a720f475f1c3acb9c77d9 100644 (file)
@@ -1,3 +1,33 @@
+2012-07-22  Steven Bosscher <steven@gcc.gnu.org>
+
+       * opts.c (common_handle_option): Do not set 
+       flag_value_profile_transformations for -fprofile-generate.
+       * profile.c (instrument_values): Use COUNTER_FOR_HIST_TYPE.
+       (BB_TO_GCOV_INDEX): Remove.
+       (output_location): Don't use it.
+       (branch_prob): Likewise.  Don't fiddle with the index of
+       ENTRY_BLOCK_PTR and EXIT_BLOCK_PTR.  Use clear_aux_for_blocks.
+       (find_spanning_tree):
+       * gcov.c (struct function_info): Document that blocks 0 and 1
+       are the entry resp. exit blocks in gcov, too, like in GCC itself.
+       (solve_flow_graph): Use ENTRY_BLOCK and EXIT_BLOCK for special
+       blocks identification.
+       (output_lines): Likewise.
+       * value-prof.c (gimple_value_profile_transformations): Do not
+       test flag_value_profile_transformations again.
+       (gimple_ic_transform): Take a gimple_stmt_iterator like all other
+       transformation functions.
+       (gimple_values_to_profile):
+       Don't test flag_value_profile_transformations
+       * tree-profile.c (tree_profiling): Assert that the cgraph is in
+       the CGRAPH_STATE_IPA_SSA state.
+       Do not set, or look at, after_tree_profile.
+       * function.h (struct function): Remove after_tree_profile bit.
+       * omp-low.c (expand_omp_taskreg): Don't set after_tree_profile.
+       * tree-inline.c (initialize_cfun): Don't copy it.
+       * lto-streamer-out.c (output_struct_function_base): Don't stream it.
+       * lto-streamer-in.c (input_struct_function_base): Likewise.
+
 2012-07-22  Oleg Endo  <olegendo@gcc.gnu.org>
 
        * config/sh/sh.h (TARGET_DYNSHIFT): New macro.
index a7d8b44a5d0a1d6576c126fa4d20044004f5077e..3d3313fc9b3286d8b6e14f5b0bd9bb850bff0150 100644 (file)
@@ -645,9 +645,6 @@ struct GTY(()) function {
      return the address of where it has put a structure value.  */
   unsigned int returns_pcc_struct : 1;
 
-  /* Nonzero if pass_tree_profile was run on this function.  */
-  unsigned int after_tree_profile : 1;
-
   /* Nonzero if this function has local DECL_HARD_REGISTER variables.
      In this case code motion has to be done more carefully.  */
   unsigned int has_local_explicit_reg_vars : 1;
index d4823991d14e7ef4c91ad9c3e2359e6ebf54bce0..318ce6046baefaea0e7f6ead5d6213e19a21da2f 100644 (file)
@@ -57,10 +57,10 @@ along with Gcov; see the file COPYING3.  If not see
 
 /* The code validates that the profile information read in corresponds
    to the code currently being compiled.  Rather than checking for
-   identical files, the code below computes a checksum on the CFG
+   identical files, the code below compares a checksum on the CFG
    (based on the order of basic blocks and the arcs in the CFG).  If
-   the CFG checksum in the gcda file match the CFG checksum for the
-   code currently being compiled, the profile data will be used.  */
+   the CFG checksum in the gcda file match the CFG checksum in the
+   gcno file, the profile data will be used.  */
 
 /* This is the size of the buffer used to read in source file lines.  */
 
@@ -177,7 +177,10 @@ typedef struct function_info
   /* The graph contains at least one fake incoming edge.  */
   unsigned has_catch : 1;
 
-  /* Array of basic blocks.  */
+  /* Array of basic blocks.  Like in GCC, the entry block is
+     at blocks[0] and the exit block is at blocks[1].  */
+#define ENTRY_BLOCK (0)
+#define EXIT_BLOCK (1)
   block_t *blocks;
   unsigned num_blocks;
   unsigned blocks_executed;
@@ -1363,21 +1366,21 @@ solve_flow_graph (function_t *fn)
             bbg_file_name, fn->name);
   else
     {
-      if (fn->blocks[0].num_pred)
+      if (fn->blocks[ENTRY_BLOCK].num_pred)
        fnotice (stderr, "%s:'%s' has arcs to entry block\n",
                 bbg_file_name, fn->name);
       else
        /* We can't deduce the entry block counts from the lack of
           predecessors.  */
-       fn->blocks[0].num_pred = ~(unsigned)0;
+       fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
 
-      if (fn->blocks[fn->num_blocks - 1].num_succ)
+      if (fn->blocks[EXIT_BLOCK].num_succ)
        fnotice (stderr, "%s:'%s' has arcs from exit block\n",
                 bbg_file_name, fn->name);
       else
        /* Likewise, we can't deduce exit block counts from the lack
           of its successors.  */
-       fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
+       fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
     }
 
   /* Propagate the measured counts, this must be done in the same
@@ -1637,7 +1640,7 @@ add_branch_counts (coverage_t *coverage, const arc_t *arc)
     }
 }
 
-/* Format a HOST_WIDE_INT as either a percent ratio, or absolute
+/* Format a GCOV_TYPE integer as either a percent ratio, or absolute
    count.  If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
    If DP is zero, no decimal point is printed. Only print 100% when
    TOP==BOTTOM and only print 0% when TOP=0.  If dp < 0, then simply
@@ -2266,8 +2269,9 @@ output_lines (FILE *gcov_file, const source_t *src)
     {
       for (; fn && fn->line == line_num; fn = fn->line_next)
        {
-         arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
-         gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
+         arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
+         gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
+         gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
 
          for (; arc; arc = arc->pred_next)
            if (arc->fake)
@@ -2275,9 +2279,9 @@ output_lines (FILE *gcov_file, const source_t *src)
 
          fprintf (gcov_file, "function %s", fn->name);
          fprintf (gcov_file, " called %s",
-                  format_gcov (fn->blocks[0].count, 0, -1));
+                  format_gcov (called_count, 0, -1));
          fprintf (gcov_file, " returned %s",
-                  format_gcov (return_count, fn->blocks[0].count, 0));
+                  format_gcov (return_count, called_count, 0));
          fprintf (gcov_file, " blocks executed %s",
                   format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
          fprintf (gcov_file, "\n");
index 07ae2b38609eb525c13bc8121f154520f6fd7652..c7257d9be16a769337b7d53743304fddb1661443 100644 (file)
@@ -798,7 +798,6 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
   bp = streamer_read_bitpack (ib);
   fn->is_thunk = bp_unpack_value (&bp, 1);
   fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1);
-  fn->after_tree_profile = bp_unpack_value (&bp, 1);
   fn->returns_pcc_struct = bp_unpack_value (&bp, 1);
   fn->returns_struct = bp_unpack_value (&bp, 1);
   fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1);
index 370bf0a7ae80c40683a9b45dea48d12ceed1be15..cfcd3d0a570dbb11337f412ce6400cdcfe5d0b3f 100644 (file)
@@ -757,7 +757,6 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
   bp = bitpack_create (ob->main_stream);
   bp_pack_value (&bp, fn->is_thunk, 1);
   bp_pack_value (&bp, fn->has_local_explicit_reg_vars, 1);
-  bp_pack_value (&bp, fn->after_tree_profile, 1);
   bp_pack_value (&bp, fn->returns_pcc_struct, 1);
   bp_pack_value (&bp, fn->returns_struct, 1);
   bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1);
index 03eb399c45831788492ec128a1962fc1aad62387..4d3b03239d4e03cae7a1698ba6cac2582a019c0f 100644 (file)
@@ -3398,9 +3398,6 @@ expand_omp_taskreg (struct omp_region *region)
   entry_stmt = last_stmt (region->entry);
   child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
-  /* If this function has been already instrumented, make sure
-     the child function isn't instrumented again.  */
-  child_cfun->after_tree_profile = cfun->after_tree_profile;
 
   entry_bb = region->entry;
   exit_bb = region->exit;
index d9287845c968f02220d82fd9cd2a15d9da2ed12c..0ddb1a0e582378542777b36cbb72de19b203e4bf 100644 (file)
@@ -1593,8 +1593,6 @@ common_handle_option (struct gcc_options *opts,
        opts->x_profile_arc_flag = value;
       if (!opts_set->x_flag_profile_values)
        opts->x_flag_profile_values = value;
-      if (!opts_set->x_flag_value_profile_transformations)
-       opts->x_flag_value_profile_transformations = value;
       if (!opts_set->x_flag_inline_functions)
        opts->x_flag_inline_functions = value;
       /* FIXME: Instrumentation we insert makes ipa-reference bitmaps
index f8debfc38d4d3af2e03be1759fbfd14adab24123..3d0689afac31dca3d9d534d053a0e4ab9e13565c 100644 (file)
@@ -143,46 +143,15 @@ instrument_edges (struct edge_list *el)
 static void
 instrument_values (histogram_values values)
 {
-  unsigned i, t;
+  unsigned i;
 
   /* Emit code to generate the histograms before the insns.  */
 
   for (i = 0; i < VEC_length (histogram_value, values); i++)
     {
       histogram_value hist = VEC_index (histogram_value, values, i);
-      switch (hist->type)
-       {
-       case HIST_TYPE_INTERVAL:
-         t = GCOV_COUNTER_V_INTERVAL;
-         break;
-
-       case HIST_TYPE_POW2:
-         t = GCOV_COUNTER_V_POW2;
-         break;
-
-       case HIST_TYPE_SINGLE_VALUE:
-         t = GCOV_COUNTER_V_SINGLE;
-         break;
-
-       case HIST_TYPE_CONST_DELTA:
-         t = GCOV_COUNTER_V_DELTA;
-         break;
+      unsigned t = COUNTER_FOR_HIST_TYPE (hist->type);
 
-       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 ();
-       }
       if (!coverage_counter_alloc (t, hist->n_counters))
        continue;
 
@@ -870,9 +839,6 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
     free (histogram_counts[t]);
 }
 
-/* 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.  */
@@ -899,7 +865,7 @@ output_location (char const *file_name, int line,
       if (!*offset)
        {
          *offset = gcov_write_tag (GCOV_TAG_LINES);
-         gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
+         gcov_write_unsigned (bb->index);
          name_differs = line_differs=true;
        }
 
@@ -919,19 +885,22 @@ output_location (char const *file_name, int line,
      }
 }
 
-/* Instrument and/or analyze program behavior based on program flow graph.
-   In either case, this function builds a flow graph for the function being
-   compiled.  The flow graph is stored in BB_GRAPH.
+/* Instrument and/or analyze program behavior based on program the CFG.
+
+   This function creates a representation of the control flow graph (of
+   the function being compiled) that is suitable for the instrumentation
+   of edges and/or converting measured edge counts to counts on the
+   complete CFG.
 
    When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
    the flow graph that are needed to reconstruct the dynamic behavior of the
-   flow graph.
+   flow graph.  This data is written to the gcno file for gcov.
 
    When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
-   information from a data file containing edge count information from previous
-   executions of the function being compiled.  In this case, the flow graph is
-   annotated with actual execution counts, which are later propagated into the
-   rtl for optimization purposes.
+   information from the gcda file containing edge count information from
+   previous executions of the function being compiled.  In this case, the
+   control flow graph is annotated with actual execution counts by
+   compute_branch_probabilities().
 
    Main entry point of this file.  */
 
@@ -1145,8 +1114,7 @@ branch_prob (void)
   lineno_checksum = coverage_compute_lineno_checksum ();
 
   /* Write the data from which gcov can reconstruct the basic block
-     graph and function line numbers  */
-
+     graph and function line numbers (the gcno file).  */
   if (coverage_begin_function (lineno_checksum, cfg_checksum))
     {
       gcov_position_t offset;
@@ -1157,12 +1125,6 @@ branch_prob (void)
        gcov_write_unsigned (0);
       gcov_write_length (offset);
 
-      /* 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;
-      EXIT_BLOCK_PTR->index = last_basic_block;
-
       /* Arcs */
       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
        {
@@ -1170,7 +1132,7 @@ branch_prob (void)
          edge_iterator ei;
 
          offset = gcov_write_tag (GCOV_TAG_ARCS);
-         gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
+         gcov_write_unsigned (bb->index);
 
          FOR_EACH_EDGE (e, ei, bb->succs)
            {
@@ -1191,7 +1153,7 @@ branch_prob (void)
                      && e->src->next_bb == e->dest)
                    flag_bits |= GCOV_ARC_FALLTHROUGH;
 
-                 gcov_write_unsigned (BB_TO_GCOV_INDEX (e->dest));
+                 gcov_write_unsigned (e->dest->index);
                  gcov_write_unsigned (flag_bits);
                }
            }
@@ -1199,9 +1161,6 @@ branch_prob (void)
          gcov_write_length (offset);
        }
 
-      ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
-      EXIT_BLOCK_PTR->index = EXIT_BLOCK;
-
       /* Line numbers.  */
       /* Initialize the output.  */
       output_location (NULL, 0, NULL, NULL);
@@ -1247,8 +1206,6 @@ branch_prob (void)
        }
     }
 
-#undef BB_TO_GCOV_INDEX
-
   if (flag_profile_values)
     gimple_find_values_to_profile (&values);
 
@@ -1391,8 +1348,7 @@ find_spanning_tree (struct edge_list *el)
        }
     }
 
-  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
-    bb->aux = NULL;
+  clear_aux_for_blocks ();
 }
 \f
 /* Perform file-level initialization for branch-prob processing.  */
index 3131525fb8b375bbff16286143b2ebe5d26fb240..78b4d94573d53de27fdb56eaba60b5047020ae46 100644 (file)
@@ -2110,7 +2110,6 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
   cfun->can_delete_dead_exceptions = src_cfun->can_delete_dead_exceptions;
   cfun->returns_struct = src_cfun->returns_struct;
   cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
-  cfun->after_tree_profile = src_cfun->after_tree_profile;
 
   init_empty_tree_cfg ();
 
index ba6c6ed4cf7ac26efcbe08c595206ecc31b5ac76..41879530303dee631d02c8c2355c3ead2368e9c4 100644 (file)
@@ -100,6 +100,8 @@ init_ic_make_global_vars (void)
   varpool_finalize_decl (ic_gcov_type_ptr_var);
 }
 
+/* Create the type and function decls for the interface with gcov.  */
+
 void
 gimple_init_edge_profiler (void)
 {
@@ -332,8 +334,9 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
 
   /* Insert code:
 
-    __gcov_indirect_call_counters = get_relevant_counter_ptr ();
-    __gcov_indirect_call_callee = (void *) indirect call argument;
+    stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
+    stmt2: tmp1 = (void *) (indirect call argument value)
+    stmt3: __gcov_indirect_call_callee = tmp1;
    */
 
   tmp1 = create_tmp_reg (ptr_void, "PROF");
@@ -368,6 +371,13 @@ gimple_gen_ic_func_profiler (void)
 
   gimple_init_edge_profiler ();
 
+  /* Insert code:
+
+    stmt1: __gcov_indirect_call_profiler (__gcov_indirect_call_counters,
+                                         current_function_funcdef_no,
+                                         &current_function_decl,
+                                         __gcov_indirect_call_callee);
+   */
   gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
 
   cur_func = force_gimple_operand_gsi (&gsi,
@@ -461,12 +471,9 @@ tree_profiling (void)
 {
   struct cgraph_node *node;
 
-  /* Don't profile functions produced at destruction time, particularly
-     the gcov datastructure initializer.  Don't profile if it has been
-     already instrumented either (when OpenMP expansion creates
-     child function from already instrumented body).  */
-  if (cgraph_state == CGRAPH_STATE_FINISHED)
-    return 0;
+  /* This is a small-ipa pass that gets called only once, from
+     cgraphunit.c:ipa_passes().  */
+  gcc_assert (cgraph_state == CGRAPH_STATE_IPA_SSA);
 
   init_node_map();
 
@@ -476,8 +483,7 @@ tree_profiling (void)
        continue;
 
       /* Don't profile functions produced for builtin stuff.  */
-      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
-         || DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
+      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
        continue;
 
       push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
@@ -489,6 +495,7 @@ tree_profiling (void)
       /* Local pure-const may imply need to fixup the cfg.  */
       if (execute_fixup_cfg () & TODO_cleanup_cfg)
        cleanup_tree_cfg ();
+
       branch_prob ();
 
       if (! flag_branch_probabilities
@@ -519,8 +526,7 @@ tree_profiling (void)
        continue;
 
       /* Don't profile functions produced for builtin stuff.  */
-      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
-         || DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
+      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
        continue;
 
       cgraph_set_const_flag (node, false, false);
@@ -538,8 +544,7 @@ tree_profiling (void)
        continue;
 
       /* Don't profile functions produced for builtin stuff.  */
-      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
-         || DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
+      if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
        continue;
 
       push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
@@ -556,7 +561,6 @@ tree_profiling (void)
            }
        }
 
-      cfun->after_tree_profile = 1;
       update_ssa (TODO_update_ssa);
 
       rebuild_cgraph_edges ();
index 29c3e92b28928c8f926311dd63ae5beed453743f..b75c36f87f7eeb6435babd8d946f2eccf34c80d5 100644 (file)
@@ -53,28 +53,63 @@ along with GCC; see the file COPYING3.  If not see
    1) Division/modulo specialization.  Provided that we can determine that the
       operands of the division have some special properties, we may use it to
       produce more effective code.
-   2) Speculative prefetching.  If we are able to determine that the difference
-      between addresses accessed by a memory reference is usually constant, we
-      may add the prefetch instructions.
-      FIXME: This transformation was removed together with RTL based value
-      profiling.
 
-   3) Indirect/virtual call specialization. If we can determine most
+   2) Indirect/virtual call specialization. If we can determine most
       common function callee in indirect/virtual call. We can use this
       information to improve code effectiveness (especially info for
-      inliner).
+      the inliner).
 
-   Every such optimization should add its requirements for profiled values to
-   insn_values_to_profile function.  This function is called from branch_prob
-   in profile.c and the requested values are instrumented by it in the first
-   compilation with -fprofile-arcs.  The optimization may then read the
-   gathered data in the second compilation with -fbranch-probabilities.
+   3) Speculative prefetching.  If we are able to determine that the difference
+      between addresses accessed by a memory reference is usually constant, we
+      may add the prefetch instructions.
+      FIXME: This transformation was removed together with RTL based value
+      profiling.
 
-   The measured data is pointed to from the histograms
-   field of the statement annotation of the instrumented insns.  It is
-   kept as a linked list of struct histogram_value_t's, which contain the
-   same information as above.  */
 
+   Value profiling internals
+   ==========================
+
+   Every value profiling transformation starts with defining what values
+   to profile.  There are different histogram types (see HIST_TYPE_* in
+   value-prof.h) and each transformation can request one or more histogram
+   types per GIMPLE statement.  The function gimple_find_values_to_profile()
+   collects the values to profile in a VEC, and adds the number of counters
+   required for the different histogram types.
+
+   For a -fprofile-generate run, the statements for which values should be
+   recorded, are instrumented in instrument_values().  The instrumentation
+   is done by helper functions that can be found in tree-profile.c, where
+   new types of histograms can be added if necessary.
+
+   After a -fprofile-use, the value profiling data is read back in by
+   compute_value_histograms() that translates the collected data to
+   histograms and attaches them to the profiled statements via
+   gimple_add_histogram_value().  Histograms are stored in a hash table
+   that is attached to every intrumented function, see VALUE_HISTOGRAMS
+   in function.h.
+   
+   The value-profile transformations driver is the function
+   gimple_value_profile_transformations().  It traverses all statements in
+   the to-be-transformed function, and looks for statements with one or
+   more histograms attached to it.  If a statement has histograms, the
+   transformation functions are called on the statement.
+
+   Limitations / FIXME / TODO:
+   * Only one histogram of each type can be associated with a statement.
+   * Currently, HIST_TYPE_CONST_DELTA is not implemented.
+     (This type of histogram was originally used to implement a form of
+     stride profiling based speculative prefetching to improve SPEC2000
+     scores for memory-bound benchmarks, mcf and equake.  However, this
+     was an RTL value-profiling transformation, and those have all been
+     removed.)
+   * Some value profile transformations are done in builtins.c (?!)
+   * Updating of histograms needs some TLC.
+   * The value profiling code could be used to record analysis results
+     from non-profiling (e.g. VRP).
+   * Adding new profilers should be simplified, starting with a cleanup
+     of what-happens-where andwith making gimple_find_values_to_profile
+     and gimple_value_profile_transformations table-driven, perhaps...
+*/
 
 static tree gimple_divmod_fixed_value (gimple, tree, int, gcov_type, gcov_type);
 static tree gimple_mod_pow2 (gimple, int, gcov_type, gcov_type);
@@ -84,7 +119,7 @@ static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
 static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
 static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
 static bool gimple_stringops_transform (gimple_stmt_iterator *);
-static bool gimple_ic_transform (gimple);
+static bool gimple_ic_transform (gimple_stmt_iterator *);
 
 /* Allocate histogram value.  */
 
@@ -309,7 +344,7 @@ dump_histograms_for_stmt (struct function *fun, FILE *dump_file, gimple stmt)
 {
   histogram_value hist;
   for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
-   dump_histogram_value (dump_file, hist);
+    dump_histogram_value (dump_file, hist);
 }
 
 /* Remove all histograms associated with STMT.  */
@@ -519,12 +554,11 @@ gimple_value_profile_transformations (void)
             will be added before the current statement, and that the
             current statement remain valid (although possibly
             modified) upon return.  */
-         if (flag_value_profile_transformations
-             && (gimple_mod_subtract_transform (&gsi)
-                 || gimple_divmod_fixed_value_transform (&gsi)
-                 || gimple_mod_pow2_value_transform (&gsi)
-                 || gimple_stringops_transform (&gsi)
-                 || gimple_ic_transform (stmt)))
+         if (gimple_mod_subtract_transform (&gsi)
+             || gimple_divmod_fixed_value_transform (&gsi)
+             || gimple_mod_pow2_value_transform (&gsi)
+             || gimple_stringops_transform (&gsi)
+             || gimple_ic_transform (&gsi))
            {
              stmt = gsi_stmt (gsi);
              changed = true;
@@ -1283,8 +1317,9 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
  */
 
 static bool
-gimple_ic_transform (gimple stmt)
+gimple_ic_transform (gimple_stmt_iterator *gsi)
 {
+  gimple stmt = gsi_stmt (*gsi);
   histogram_value histogram;
   gcov_type val, count, all, bb_all;
   gcov_type prob;
@@ -1749,12 +1784,9 @@ gimple_stringops_values_to_profile (gimple stmt, histogram_values *values)
 static void
 gimple_values_to_profile (gimple stmt, histogram_values *values)
 {
-  if (flag_value_profile_transformations)
-    {
-      gimple_divmod_values_to_profile (stmt, values);
-      gimple_stringops_values_to_profile (stmt, values);
-      gimple_indirect_call_to_profile (stmt, values);
-    }
+  gimple_divmod_values_to_profile (stmt, values);
+  gimple_stringops_values_to_profile (stmt, values);
+  gimple_indirect_call_to_profile (stmt, values);
 }
 
 void