Rong,
Would be possible to use topn profiler to get resonale histograms for switch
expansion, too? In that case it may make sense to have value version of it as well.
Otherwise the patch seems OK. I would implement it myself by introducing separate
variables holding the topn profiler declaration, but can not think of downsides of
doing it your way.
The topn profiler should be better on determining the dominating target, so perhaps
you could look into hooking it into ipa-profile.c. Extending speculative edges for
multiple targets ought to be also quite easy - we need to update speculative_call_info
to collect edges annotated to a given call stmt into a vector instead of taking the
two references it does now.
It would be also very nice to update it to handle case where all the edges are direct
so we can use it tospeculatively inlinine functions that can be interposed at runtime.
Thanks,
Honza
Index: gcc/tree-profile.c
===================================================================
--- gcc/tree-profile.c (revision 215886)
+++ gcc/tree-profile.c (working copy)
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "tree-cfgcleanup.h"
#include "tree-nested.h"
+#include "params.h"
static GTY(()) tree gcov_type_node;
static GTY(()) tree tree_interval_profiler_fn;
@@ -101,7 +102,10 @@ init_ic_make_global_vars (void)
{
ic_void_ptr_var
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_callee"),
+ get_identifier (
+ (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ "__gcov_indirect_call_topn_callee" :
+ "__gcov_indirect_call_callee")),
ptr_void);
TREE_PUBLIC (ic_void_ptr_var) = 1;
DECL_EXTERNAL (ic_void_ptr_var) = 1;
@@ -131,7 +135,10 @@ init_ic_make_global_vars (void)
{
ic_gcov_type_ptr_var
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier ("__gcov_indirect_call_counters"),
+ get_identifier (
+ (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ "__gcov_indirect_call_topn_counters" :
+ "__gcov_indirect_call_counters")),
gcov_type_ptr);
TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
@@ -226,8 +233,10 @@ gimple_init_edge_profiler (void)
ptr_void,
NULL_TREE);
tree_indirect_call_profiler_fn
- = build_fn_decl ("__gcov_indirect_call_profiler_v2",
- ic_profiler_fn_type);
+ = build_fn_decl ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ "__gcov_indirect_call_topn_profiler":
+ "__gcov_indirect_call_profiler_v2"),
+ ic_profiler_fn_type);
}
TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
@@ -398,6 +407,12 @@ gimple_gen_ic_profiler (histogram_value value, uns
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
+ if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
+ tag == GCOV_COUNTER_V_INDIR) ||
+ (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
+ tag == GCOV_COUNTER_ICALL_TOPNV))
+ return;
+
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
@@ -442,8 +457,7 @@ gimple_gen_ic_func_profiler (void)
stmt1: __gcov_indirect_call_profiler_v2 (profile_id,
¤t_function_decl)
*/
- gsi =
- gsi_after_labels (split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
+ gsi = gsi_after_labels (split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))));
cur_func = force_gimple_operand_gsi (&gsi,
build_addr (current_function_decl,
Index: gcc/value-prof.c
===================================================================
--- gcc/value-prof.c (revision 215886)
+++ gcc/value-prof.c (working copy)
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "tree-nested.h"
#include "hash-set.h"
+#include "params.h"
/* In this file value profile based optimizations are placed. Currently the
following optimizations are implemented (for more detailed descriptions
@@ -359,6 +360,22 @@ dump_histogram_value (FILE *dump_file, histogram_v
}
fprintf (dump_file, ".\n");
break;
+ case HIST_TYPE_INDIR_CALL_TOPN:
+ fprintf (dump_file, "Indirect call topn ");
+ if (hist->hvalue.counters)
+ {
+ int i;
+
+ fprintf (dump_file, "accu:%"PRId64, hist->hvalue.counters[0]);
+ for (i = 1; i < (GCOV_ICALL_TOPN_VAL << 2); i += 2)
+ {
+ fprintf (dump_file, " target:%"PRId64 " value:%"PRId64,
+ (int64_t) hist->hvalue.counters[i],
+ (int64_t) hist->hvalue.counters[i+1]);
+ }
+ }
+ fprintf (dump_file, ".\n");
+ break;
case HIST_TYPE_MAX:
gcc_unreachable ();
}
@@ -432,9 +449,14 @@ stream_in_histogram_value (struct lto_input_block
break;
case HIST_TYPE_IOR:
- case HIST_TYPE_TIME_PROFILE:
+ case HIST_TYPE_TIME_PROFILE:
ncounters = 1;
break;
+
+ case HIST_TYPE_INDIR_CALL_TOPN:
+ ncounters = (GCOV_ICALL_TOPN_VAL << 2) + 1;
+ break;
+
case HIST_TYPE_MAX:
gcc_unreachable ();
}
@@ -1920,8 +1942,12 @@ gimple_indirect_call_to_profile (gimple stmt, hist
values->reserve (3);
- values->quick_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
- stmt, callee));
+ values->quick_push (gimple_alloc_histogram_value (
+ cfun,
+ PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
+ HIST_TYPE_INDIR_CALL_TOPN :
+ HIST_TYPE_INDIR_CALL,
+ stmt, callee));
return;
}
@@ -2011,9 +2037,9 @@ gimple_find_values_to_profile (histogram_values *v
hist->n_counters = 3;
break;
- case HIST_TYPE_TIME_PROFILE:
- hist->n_counters = 1;
- break;
+ case HIST_TYPE_TIME_PROFILE:
+ hist->n_counters = 1;
+ break;
case HIST_TYPE_AVERAGE:
hist->n_counters = 2;
@@ -2023,6 +2049,10 @@ gimple_find_values_to_profile (histogram_values *v
hist->n_counters = 1;
break;
+ case HIST_TYPE_INDIR_CALL_TOPN:
+ hist->n_counters = GCOV_ICALL_TOPN_NCOUNTS;
+ break;
+
default:
gcc_unreachable ();
}
Index: gcc/value-prof.h
===================================================================
--- gcc/value-prof.h (revision 215886)
+++ gcc/value-prof.h (working copy)
@@ -35,6 +35,8 @@ enum hist_type
HIST_TYPE_AVERAGE, /* Compute average value (sum of all values). */
HIST_TYPE_IOR, /* Used to compute expected alignment. */
HIST_TYPE_TIME_PROFILE, /* Used for time profile */
+ HIST_TYPE_INDIR_CALL_TOPN, /* Tries to identify the top N most frequently
+ called functions in indirect call. */
HIST_TYPE_MAX
};
Index: gcc/profile.c
===================================================================
--- gcc/profile.c (revision 215886)
+++ gcc/profile.c (working copy)
@@ -183,6 +183,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;