> diff --git a/gcc/ChangeLog b/gcc/ChangeLog > index fca665b..3b62bcc 100644 > --- a/gcc/ChangeLog > +++ b/gcc/ChangeLog > @@ -1,3 +1,31 @@ > +2013-10-29 Martin Liska <marxin.li...@gmail.com> > + Jan Hubicka <j...@suse.cz> > + > + * cgraph.c (dump_cgraph_node): Profile dump added. > + * cgraph.h (struct cgraph_node): New time profile variable added. > + * cgraphclones.c (cgraph_clone_node): Time profile is cloned. > + * gcov-io.h (gcov_type): New profiler type introduced. > + * ipa-profile.c (lto_output_node): Streaming for time profile added. > + (input_node): Time profiler is read from LTO stream. > + * predict.c (maybe_hot_count_p): Hot prediction changed. > + * profile.c (instrument_values): New case for time profiler added. > + (compute_value_histograms): Read of time profile. > + * tree-pretty-print.c (dump_function_header): Time profiler is dumped. > + * tree-profile.c (init_ic_make_global_vars): Time profiler function > added. > + (gimple_init_edge_profiler): TP function instrumentation. > + (gimple_gen_time_profiler): New. > + * value-prof.c (gimple_add_histogram_value): Support for time profiler > + added. > + (dump_histogram_value): TP type added to dumps. > + (visit_hist): More sensitive check that takes TP into account. > + (gimple_find_values_to_profile): TP instrumentation. > + * value-prof.h (hist_type): New histogram type added. > + (struct histogram_value_t): Pointer to struct function added. > + * libgcc/Makefile.in: New GCOV merge function for TP added. > + * libgcov.c: function_counter variable introduced. > + (_gcov_merge_time_profile): New. > + (_gcov_time_profiler): New. > + > 2013-10-29 David Malcolm <dmalc...@redhat.com> > > * doc/gty.texi ("Inheritance and GTY"): Make it clear that > diff --git a/gcc/cgraph.c b/gcc/cgraph.c > index 52d9ab0..c95a54e 100644 > --- a/gcc/cgraph.c > +++ b/gcc/cgraph.c > @@ -1890,6 +1890,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) > if (node->profile_id) > fprintf (f, " Profile id: %i\n", > node->profile_id); > + fprintf (f, " First run: %i\n", node->tp_first_run); > fprintf (f, " Function flags:"); > if (node->count) > fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x", > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index 7706419..479d49f 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -247,7 +247,6 @@ struct GTY(()) cgraph_clone_info > bitmap combined_args_to_skip; > }; > > - > /* The cgraph data structure. > Each function decl has assigned cgraph_node listing callees and callers. > */ > > @@ -324,6 +323,8 @@ struct GTY(()) cgraph_node { > unsigned tm_clone : 1; > /* True if this decl is a dispatcher for function versions. */ > unsigned dispatcher_function : 1; > + /* Time profiler: first run of function. */ > + int tp_first_run;
Move this up after profile_id. > --- a/gcc/gcov-io.c > +++ b/gcc/gcov-io.c > @@ -68,7 +68,7 @@ gcov_open (const char *name, int mode) > #if IN_LIBGCOV > const int mode = 0; > #endif > -#if GCOV_LOCKED > +#if GCOV_LOCKED > struct flock s_flock; > int fd; > Accidental change? > @@ -651,6 +658,9 @@ lto_symtab_prevailing_decl (tree decl) > if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) > return decl; > > + if (!DECL_ASSEMBLER_NAME_SET_P (decl)) > + return decl; > + > /* Ensure DECL_ASSEMBLER_NAME will not set assembler name. */ > gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); > Remove this change - it is unrelated hack from my old tree. > diff --git a/gcc/predict.c b/gcc/predict.c > index cc9a053..4b655d3 100644 > --- a/gcc/predict.c > +++ b/gcc/predict.c > @@ -170,7 +170,7 @@ maybe_hot_count_p (struct function *fun, gcov_type count) > if (fun && profile_status_for_function (fun) != PROFILE_READ) > return true; > /* Code executed at most once is not hot. */ > - if (profile_info->runs >= count) > + if (count <= 1) > return false; > return (count >= get_hot_bb_threshold ()); > } And also this change. > @@ -895,9 +907,19 @@ compute_value_histograms (histogram_values values, > unsigned cfg_checksum, > hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); > for (j = 0; j < hist->n_counters; j++) > if (aact_count) > - hist->hvalue.counters[j] = aact_count[j]; > - else > - hist->hvalue.counters[j] = 0; > + hist->hvalue.counters[j] = aact_count[j]; > + else > + hist->hvalue.counters[j] = 0; > + > + if (hist->type == HIST_TYPE_TIME_PROFILE) > + { > + node = cgraph_get_node (hist->fun->decl); > + > + node->tp_first_run = hist->hvalue.counters[0]; > + > + if (dump_file) > + fprintf (dump_file, "Read tp_first_run: %d\n", > node->tp_first_run); > + } Probably add a comment why you need to annotate counter here. > diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c > index b2c5411..0fe262c 100644 > --- a/gcc/tree-pretty-print.c > +++ b/gcc/tree-pretty-print.c > @@ -3390,7 +3390,9 @@ dump_function_header (FILE *dump_file, tree fdecl, int > flags) > fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl)); > if (node) > { > - fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->symbol.order, > + fprintf (dump_file, ", tp_first_run=%d, symbol_order=%d)%s\n\n", > + node->tp_first_run, > + node->symbol.order, > node->frequency == NODE_FREQUENCY_HOT > ? " (hot)" > : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED I would skip this change for now - we do not want to increase verbosity too much. Pehraps this can go with -details or so. > static void > init_ic_make_global_vars (void) > { > - tree gcov_type_ptr; > + tree gcov_type_ptr; > > - ptr_void = build_pointer_type (void_type_node); > + ptr_void = build_pointer_type (void_type_node); Be cureful about accidental whitespace changes. > > /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. > */ > if (flag_lto) > @@ -102,7 +104,7 @@ init_ic_make_global_vars (void) > > varpool_finalize_decl (ic_void_ptr_var); > > - gcov_type_ptr = build_pointer_type (get_gcov_type ()); > + gcov_type_ptr = build_pointer_type (get_gcov_type ()); > /* Workaround for binutils bug 14342. Once it is fixed, remove lto path. > */ > if (flag_lto) > { Here too. > @@ -455,6 +471,20 @@ gimple_gen_ic_func_profiler (void) > gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); > } > > + > +void > +gimple_gen_time_profiler (unsigned tag, unsigned base, > + gimple_stmt_iterator &gsi) Add block comment before function. > @@ -545,7 +575,7 @@ tree_profiling (void) > > if (! flag_branch_probabilities > && flag_profile_values) > - gimple_gen_ic_func_profiler (); > + gimple_gen_ic_func_profiler (); > > if (flag_branch_probabilities > && flag_profile_values Maybe also accidental? > @@ -692,13 +702,16 @@ gcov_exit (void) > > if (gi_ptr->merge[t_ix]) > { > - if (!cs_prg->runs++) > + int first_run = !cs_prg->runs; > + > + cs_prg->runs++; > + if (first_run) > cs_prg->num = cs_tprg->num; > cs_prg->sum_all += cs_tprg->sum_all; > if (cs_prg->run_max < cs_tprg->run_max) > cs_prg->run_max = cs_tprg->run_max; > cs_prg->sum_max += cs_tprg->run_max; > - if (cs_prg->runs == 1) > + if (first_run) > memcpy (cs_prg->histogram, cs_tprg->histogram, > sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); > else This change is probably part of the patch getting fork working right and unrelated to this patch, right? I would skip it along with the whitespace changes so Rons' patch to break up libgcov have fewer rejects. > @@ -795,17 +808,23 @@ gcov_exit (void) > gcov_write_unsigned (gfi_ptr->cfg_checksum); > > ci_ptr = gfi_ptr->ctrs; > + > for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) > { > - if (!gi_ptr->merge[t_ix]) > + gcov_merge_fn merge = gi_ptr->merge[t_ix]; > + > + if (!merge) > continue; > > n_counts = ci_ptr->num; > gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), > GCOV_TAG_COUNTER_LENGTH (n_counts)); > + > gcov_type *c_ptr = ci_ptr->values; > + gcov_type value; Whitespace looks wrong. > while (n_counts--) > - gcov_write_counter (*c_ptr++); > + gcov_write_counter (*c_ptr++); > + > ci_ptr++; > } > if (buffered) > @@ -824,6 +843,8 @@ gcov_exit (void) > "profiling:%s:Error writing\n", > gi_filename); > } > + > + gcov_clear (); > } > > /* Reset all counters to zero. */ I believe this is also unrelated (part of fork/vfork changes) > @@ -851,6 +872,7 @@ gcov_clear (void) > continue; > > memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); > + > ci_ptr++; > } > } > @@ -912,7 +934,6 @@ __gcov_flush (void) > __gthread_mutex_lock (&__gcov_flush_mx); > > gcov_exit (); > - gcov_clear (); > > __gthread_mutex_unlock (&__gcov_flush_mx); > } Also unrelated. > @@ -974,6 +995,24 @@ __gcov_merge_ior (gcov_type *counters, unsigned > n_counters) > } > #endif > > +#ifdef L_gcov_merge_time_profile > +void > +__gcov_merge_time_profile (gcov_type *counters, unsigned n_counters) > +{ > + unsigned int i; > + gcov_type value; > + > + for (i = 0; i < n_counters; i++) > + { > + value = gcov_read_counter (); > + > + if (value && (!counters[i] || value < counters[i])) > + counters[i] = value; > + } > +} > +#endif /* L_gcov_merge_time_profile */ Add comments for this function explaining how merging goes and also for L_gcov_time_profiler. > + > + > #ifdef L_gcov_merge_single > /* The profile merging function for choosing the most common value. > It is given an array COUNTERS of N_COUNTERS old counters and it > @@ -1171,6 +1210,7 @@ __thread > #endif > gcov_type * __gcov_indirect_call_counters; > > + > /* By default, the C++ compiler will use function addresses in the > vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero > tells the compiler to use function descriptors instead. The value > @@ -1202,6 +1242,16 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, > void* cur_func) > } > #endif > > +#ifdef L_gcov_time_profiler > + > +void > +__gcov_time_profiler (gcov_type* counters) > +{ > + if (!counters[0]) > + counters[0] = ++function_counter; > +} > +#endif > + > #ifdef L_gcov_average_profiler > /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want > to saturate up. */ > @@ -1233,10 +1283,12 @@ __gcov_fork (void) > { > pid_t pid; > extern __gthread_mutex_t __gcov_flush_mx; > + > __gcov_flush (); > pid = fork (); > if (pid == 0) > __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx); > + > return pid; > } > #endif Please post updated patch. Basically it looks fine with these changes. Try to also prepare a testcase (in testsuite/gcc.dg/tree-prof you can see existing examples how to profile and grep dump files for first run counters). Honza