+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ * doc/invoke.texi: Remove param.
+ * gcov-counter.def (GCOV_COUNTER_ICALL_TOPNV):
+ Remove.
+ * gcov-io.h (GCOV_ICALL_TOPN_VAL): Likewise.
+ (GCOV_ICALL_TOPN_NCOUNTS): Likewise.
+ * params.def (PARAM_INDIR_CALL_TOPN_PROFILE): Likewise.
+ * profile.c (instrument_values): Remove
+ HIST_TYPE_INDIR_CALL_TOPN.
+ * tree-profile.c (init_ic_make_global_vars):
+ Always build __gcov_indirect_call only.
+ (gimple_init_gcov_profiler): Remove usage
+ of PARAM_INDIR_CALL_TOPN_PROFILE.
+ (gimple_gen_ic_profiler): Likewise.
+ * value-prof.c (dump_histogram_value): Likewise.
+ (stream_in_histogram_value): Likewise.
+ (gimple_indirect_call_to_profile): Likewise.
+ (gimple_find_values_to_profile): Likewise.
+ * value-prof.h (enum hist_type): Likewise.
+
2019-06-07 Martin Liska <mliska@suse.cz>
* tree-ssa-loop.c (get_lsm_tmp_name): Return at the end of the
Maximum number of nested calls to search for control dependencies
during uninitialized variable analysis.
-@item indir-call-topn-profile
-Track top N target addresses in indirect-call profile.
-
@item max-once-peeled-insns
The maximum number of insns of a peeled loop that rolls only once.
/* Time profile collecting first run of a function */
DEF_GCOV_COUNTER(GCOV_TIME_PROFILER, "time_profiler", _time_profile)
-
-/* Top N value tracking for indirect calls. */
-DEF_GCOV_COUNTER(GCOV_COUNTER_ICALL_TOPNV, "indirect_call_topn", _icall_topn)
#define GCOV_N_VALUE_COUNTERS \
(GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1)
-/* The number of hottest callees to be tracked. */
-#define GCOV_ICALL_TOPN_VAL 2
-
-/* The number of counter entries per icall callsite. */
-#define GCOV_ICALL_TOPN_NCOUNTS (1 + GCOV_ICALL_TOPN_VAL * 4)
-
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
(GCOV_TAG_COUNTER_BASE + ((gcov_unsigned_t)(COUNT) << 17))
"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_v3 which tracks single target. */
-DEFPARAM (PARAM_INDIR_CALL_TOPN_PROFILE,
- "indir-call-topn-profile",
- "Track top N 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;
ic_tuple_var
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier (
- (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
- "__gcov_indirect_call_topn" :
- "__gcov_indirect_call")),
- tuple_type);
+ get_identifier ("__gcov_indirect_call"), tuple_type);
TREE_PUBLIC (ic_tuple_var) = 1;
DECL_ARTIFICIAL (ic_tuple_var) = 1;
DECL_INITIAL (ic_tuple_var) = NULL;
ptr_type_node,
NULL_TREE);
profiler_fn_name = "__gcov_indirect_call_profiler_v3";
- if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
- profiler_fn_name = "__gcov_indirect_call_topn_profiler";
tree_indirect_call_profiler_fn
= build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
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);
}
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 ();
}
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,
- PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
- HIST_TYPE_INDIR_CALL_TOPN :
- HIST_TYPE_INDIR_CALL,
- stmt, callee));
+ values->quick_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
+ stmt, callee));
return;
}
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
};
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ * Makefile.in: Remove usage of
+ _gcov_merge_icall_topn.
+ * libgcov-driver.c (gcov_sort_n_vals): Remove.
+ (gcov_sort_icall_topn_counter): Likewise.
+ (gcov_sort_topn_counter_arrays): Likewise.
+ (dump_one_gcov): Remove call to gcov_sort_topn_counter_arrays.
+ * libgcov-merge.c (__gcov_merge_icall_topn): Remove.
+ * libgcov-profiler.c (__gcov_topn_value_profiler_body):
+ Likewise.
+ (GCOV_ICALL_COUNTER_CLEAR_THRESHOLD): Remove.
+ (struct indirect_call_tuple): Remove.
+ (__gcov_indirect_call_topn_profiler): Remove.
+ * libgcov-util.c (__gcov_icall_topn_counter_op): Remove.
+ * libgcov.h (gcov_sort_n_vals): Remove.
+ (L_gcov_merge_icall_topn): Likewise.
+ (__gcov_merge_icall_topn): Likewise.
+ (__gcov_indirect_call_topn_profiler): Likewise.
+
2019-06-06 Iain Sandoe <iain@sandoe.co.uk>
* config/rs6000/t-darwin: Ensure that the unwinder is built with
# Build libgcov components.
LIBGCOV_MERGE = _gcov_merge_add _gcov_merge_single \
- _gcov_merge_ior _gcov_merge_time_profile _gcov_merge_icall_topn
+ _gcov_merge_ior _gcov_merge_time_profile
LIBGCOV_PROFILER = _gcov_interval_profiler \
_gcov_interval_profiler_atomic \
_gcov_pow2_profiler \
_gcov_ior_profiler \
_gcov_ior_profiler_atomic \
_gcov_indirect_call_profiler_v3 \
- _gcov_time_profiler \
- _gcov_indirect_call_topn_profiler
+ _gcov_time_profiler
LIBGCOV_INTERFACE = _gcov_dump _gcov_flush _gcov_fork \
_gcov_execl _gcov_execlp \
_gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset
}
}
-/* Sort N entries in VALUE_ARRAY in descending order.
- Each entry in VALUE_ARRAY has two values. The sorting
- is based on the second value. */
-
-GCOV_LINKAGE void
-gcov_sort_n_vals (gcov_type *value_array, int n)
-{
- int j, k;
-
- for (j = 2; j < n; j += 2)
- {
- gcov_type cur_ent[2];
-
- cur_ent[0] = value_array[j];
- cur_ent[1] = value_array[j + 1];
- k = j - 2;
- while (k >= 0 && value_array[k + 1] < cur_ent[1])
- {
- value_array[k + 2] = value_array[k];
- value_array[k + 3] = value_array[k+1];
- k -= 2;
- }
- value_array[k + 2] = cur_ent[0];
- value_array[k + 3] = cur_ent[1];
- }
-}
-
-/* Sort the profile counters for all indirect call sites. Counters
- for each call site are allocated in array COUNTERS. */
-
-static void
-gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
-{
- int i;
- gcov_type *values;
- int n = counters->num;
-
- gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
- values = counters->values;
-
- for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
- {
- gcov_type *value_array = &values[i + 1];
- gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
- }
-}
-
-/* Sort topn indirect_call profile counters in GI_PTR. */
-
-static void
-gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
-{
- unsigned int i;
- int f_ix;
- const struct gcov_fn_info *gfi_ptr;
- const struct gcov_ctr_info *ci_ptr;
-
- if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
- return;
-
- for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
- {
- gfi_ptr = gi_ptr->functions[f_ix];
- ci_ptr = gfi_ptr->ctrs;
- for (i = 0; i < GCOV_COUNTERS; i++)
- {
- if (!gi_ptr->merge[i])
- continue;
- if (i == GCOV_COUNTER_ICALL_TOPNV)
- {
- gcov_sort_icall_topn_counter (ci_ptr);
- break;
- }
- ci_ptr++;
- }
- }
-}
-
/* Dump the coverage counts for one gcov_info object. We merge with existing
counts when possible, to avoid growing the .da files ad infinitum. We use
this program's checksum to make sure we only accumulate whole program
fn_buffer = 0;
- gcov_sort_topn_counter_arrays (gi_ptr);
-
error = gcov_exit_open_gcda_file (gi_ptr, gf);
if (error == -1)
return;
}
#endif /* L_gcov_merge_single */
-#ifdef L_gcov_merge_icall_topn
-/* The profile merging function used for merging indirect call counts
- This function is given array COUNTERS of N_COUNTERS old counters and it
- reads the same number of counters from the gcov file. */
-
-void
-__gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
-{
- unsigned i, j, k, m;
-
- gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
- for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
- {
- gcov_type *value_array = &counters[i + 1];
- unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1);
- gcov_type *tmp_array
- = (gcov_type *) alloca (tmp_size * sizeof (gcov_type));
-
- for (j = 0; j < tmp_size; j++)
- tmp_array[j] = 0;
-
- for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
- {
- tmp_array[j] = value_array[j];
- tmp_array[j + 1] = value_array [j + 1];
- }
-
- /* Skip the number_of_eviction entry. */
- gcov_get_counter ();
- for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
- {
- int found = 0;
- gcov_type global_id = gcov_get_counter_target ();
- gcov_type call_count = gcov_get_counter ();
- for (m = 0; m < j; m += 2)
- {
- if (tmp_array[m] == global_id)
- {
- found = 1;
- tmp_array[m + 1] += call_count;
- break;
- }
- }
- if (!found)
- {
- tmp_array[j] = global_id;
- tmp_array[j + 1] = call_count;
- j += 2;
- }
- }
- /* Now sort the temp array */
- gcov_sort_n_vals (tmp_array, j);
-
- /* Now copy back the top half of the temp array */
- for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
- {
- value_array[k] = tmp_array[k];
- value_array[k + 1] = tmp_array[k + 1];
- }
- }
-}
-#endif /* L_gcov_merge_icall_topn */
#endif /* inhibit_libc */
}
#endif
-#ifdef L_gcov_indirect_call_topn_profiler
-/* Tries to keep track the most frequent N values in the counters where
- N is specified by parameter TOPN_VAL. To track top N values, 2*N counter
- entries are used.
- counter[0] --- the accumative count of the number of times one entry in
- in the counters gets evicted/replaced due to limited capacity.
- When this value reaches a threshold, the bottom N values are
- cleared.
- counter[1] through counter[2*N] records the top 2*N values collected so far.
- Each value is represented by two entries: count[2*i+1] is the ith value, and
- count[2*i+2] is the number of times the value is seen. */
-
-static void
-__gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value)
-{
- unsigned i, found = 0, have_zero_count = 0;
- gcov_type *entry;
- gcov_type *lfu_entry = &counters[1];
- gcov_type *value_array = &counters[1];
- gcov_type *num_eviction = &counters[0];
- gcov_unsigned_t topn_val = GCOV_ICALL_TOPN_VAL;
-
- /* There are 2*topn_val values tracked, each value takes two slots in the
- counter array. */
- for (i = 0; i < (topn_val << 2); i += 2)
- {
- entry = &value_array[i];
- if (entry[0] == value)
- {
- entry[1]++ ;
- found = 1;
- break;
- }
- else if (entry[1] == 0)
- {
- lfu_entry = entry;
- have_zero_count = 1;
- }
- else if (entry[1] < lfu_entry[1])
- lfu_entry = entry;
- }
-
- if (found)
- return;
-
- /* lfu_entry is either an empty entry or an entry
- with lowest count, which will be evicted. */
- lfu_entry[0] = value;
- lfu_entry[1] = 1;
-
-#define GCOV_ICALL_COUNTER_CLEAR_THRESHOLD 3000
-
- /* Too many evictions -- time to clear bottom entries to
- avoid hot values bumping each other out. */
- if (!have_zero_count
- && ++*num_eviction >= GCOV_ICALL_COUNTER_CLEAR_THRESHOLD)
- {
- unsigned i, j;
- gcov_type *p, minv;
- gcov_type* tmp_cnts
- = (gcov_type *)alloca (topn_val * sizeof (gcov_type));
-
- *num_eviction = 0;
-
- for (i = 0; i < topn_val; i++)
- tmp_cnts[i] = 0;
-
- /* Find the largest topn_val values from the group of
- 2*topn_val values and put them into tmp_cnts. */
-
- for (i = 0; i < 2 * topn_val; i += 2)
- {
- p = 0;
- for (j = 0; j < topn_val; j++)
- {
- if (!p || tmp_cnts[j] < *p)
- p = &tmp_cnts[j];
- }
- if (value_array[i + 1] > *p)
- *p = value_array[i + 1];
- }
-
- minv = tmp_cnts[0];
- for (j = 1; j < topn_val; j++)
- {
- if (tmp_cnts[j] < minv)
- minv = tmp_cnts[j];
- }
- /* Zero out low value entries. */
- for (i = 0; i < 2 * topn_val; i += 2)
- {
- if (value_array[i + 1] < minv)
- {
- value_array[i] = 0;
- value_array[i + 1] = 0;
- }
- }
- }
-}
-
-/* These two variables are used to actually track caller and callee. Keep
- them in TLS memory so races are not common (they are written to often).
- The variables are set directly by GCC instrumented code, so declaration
- here must match one in tree-profile.c. */
-
-#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
-__thread
-#endif
-struct indirect_call_tuple __gcov_indirect_call_topn;
-
-#ifdef TARGET_VTABLE_USES_DESCRIPTORS
-#define VTABLE_USES_DESCRIPTORS 1
-#else
-#define VTABLE_USES_DESCRIPTORS 0
-#endif
-
-/* This fucntion is instrumented at function entry to track topn indirect
- calls to CUR_FUNC. */
-
-void
-__gcov_indirect_call_topn_profiler (gcov_type value, void* cur_func)
-{
- void *callee_func = __gcov_indirect_call_topn.callee;
- /* If the C++ virtual tables contain function descriptors then one
- function may have multiple descriptors and we need to dereference
- the descriptors to see if they point to the same function. */
- if (cur_func == callee_func
- || (VTABLE_USES_DESCRIPTORS && callee_func
- && *(void **) cur_func == *(void **) callee_func))
- __gcov_topn_value_profiler_body (__gcov_indirect_call_topn.counters, value);
-}
-#endif
-
#ifdef L_gcov_indirect_call_profiler_v3
/* These two variables are used to actually track caller and callee. Keep
}
}
-/* Performing FN upon indirect-call profile counters. */
-
-static void
-__gcov_icall_topn_counter_op (gcov_type *counters, unsigned n_counters,
- counter_op_fn fn, void *data1, void *data2)
-{
- unsigned i;
-
- gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
- for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
- {
- unsigned j;
- gcov_type *value_array = &counters[i + 1];
-
- for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
- value_array[j + 1] = fn (value_array[j + 1], data1, data2);
- }
-}
-
/* Scaling the counter value V by multiplying *(float*) DATA1. */
static gcov_type
#define gcov_read_unsigned __gcov_read_unsigned
#define gcov_read_counter __gcov_read_counter
#define gcov_read_summary __gcov_read_summary
-#define gcov_sort_n_vals __gcov_sort_n_vals
#else /* IN_GCOV_TOOL */
/* About the host. */
#define L_gcov_merge_single 1
#define L_gcov_merge_ior 1
#define L_gcov_merge_time_profile 1
-#define L_gcov_merge_icall_topn 1
extern gcov_type gcov_read_counter_mem ();
extern unsigned gcov_get_merge_weight ();
/* The merge function that just ors the counters together. */
extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
-/* The merge function is used for topn indirect call counters. */
-extern void __gcov_merge_icall_topn (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
-
/* The profiler functions. */
extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned);
extern void __gcov_interval_profiler_atomic (gcov_type *, gcov_type, int,
extern void __gcov_average_profiler_atomic (gcov_type *, gcov_type);
extern void __gcov_ior_profiler (gcov_type *, gcov_type);
extern void __gcov_ior_profiler_atomic (gcov_type *, gcov_type);
-extern void __gcov_indirect_call_topn_profiler (gcov_type, void *);
-extern void gcov_sort_n_vals (gcov_type *, int);
#ifndef inhibit_libc
/* The wrappers around some library functions.. */