"use internal function id in profile lookup",
0, 0, 1)
+/* When the parameter is 1, track the most frequent N target
+ addresses in indirect-call profile. This disables
+ indirect_call_profiler_v2 which tracks single target. */
+DEFPARAM (PARAM_INDIR_CALL_TOPN_PROFILE,
+ "indir-call-topn-profile",
+ "track topn target addresses in indirect-call profile",
+ 0, 0, 1)
+
/* Avoid SLP vectorization of large basic blocks. */
DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
"slp-max-insns-in-bb",
break;
case HIST_TYPE_INDIR_CALL:
+ case HIST_TYPE_INDIR_CALL_TOPN:
gimple_gen_ic_profiler (hist, t, 0);
break;
#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;
{
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;
{
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;
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)
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);
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,
#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
}
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 ();
}
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 ();
}
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;
}
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;
hist->n_counters = 1;
break;
+ case HIST_TYPE_INDIR_CALL_TOPN:
+ hist->n_counters = GCOV_ICALL_TOPN_NCOUNTS;
+ break;
+
default:
gcc_unreachable ();
}
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
};