On Wed, Dec 19, 2012 at 12:11 PM, Rong Xu <x...@google.com> wrote: > Hi, > > This patch updates the support for FDO build in linux kernel for gcc 4.7. > Tested with 2.6.34 kernel and google internal benchmarks. > > Thanks, > > -Rong > > 2012-12-19 Rong Xu <x...@google.com> > > * libgcc/libgcov.c > (gcov_counter_active): v4.7 kernel fdo support. > (crc32_unsigned): Include in GCOV_KERNEL build. > (gcov_alloc_filename): Remove from GCOV_KERNEL build. > (gcov_sort_icall_topn_counter): Ditto. > (gcov_dump_module_info): Ditto. > (gcov_compute_histogram): v4.7 kernel fdo support. > (gcov_merge_gcda_file): Ditto. > (gcov_gcda_file_size): Ditto. > (gcov_write_gcda_file): Ditto. > (__gcov_topn_value_profiler_body): Ditto. > (gcov_set_vfile): Ditto. > (gcov_kernel_dump_gcov_init): Ditto. > (gcov_kernel_dump_one_gcov): Ditto. > * gcc/gcov-io.c (gcov_read_string): Ditto. > (static int k_popcountll): Ditto. > (gcov_read_summary): Ditto. > (kernel_file_fclose): Ditto. > (kernel_file_ftell): Ditto. > (kernel_file_fwrite): Ditto. > * gcc/gcov-io.h (struct gcov_info): remove const keyword. > > Index: libgcc/libgcov.c > =================================================================== > --- libgcc/libgcov.c (revision 194562) > +++ libgcc/libgcov.c (working copy) > @@ -46,11 +46,11 @@ see the files COPYING3 and COPYING.RUNTIME respect > #include "tsystem.h" > #include "coretypes.h" > #include "tm.h" > -#endif /* __KERNEL__ */ > #include "libgcc_tm.h" > #include "gthr.h" > +#endif /* __KERNEL__ */ > > -#if 1 > +#ifndef __KERNEL__ > #define THREAD_PREFIX __thread > #else > #define THREAD_PREFIX > @@ -120,6 +120,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN; > #ifdef L_gcov > #include "gcov-io.c" > > +#ifndef __GCOV_KERNEL__ > /* Create a strong reference to these symbols so that they are > unconditionally pulled into the instrumented binary, even when > the only reference is a weak reference. This is necessary because > @@ -134,6 +135,7 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN; > these symbols will always need to be resolved. */ > void (*__gcov_dummy_ref1)() = &__gcov_reset; > void (*__gcov_dummy_ref2)() = &__gcov_dump; > +#endif /* __GCOV_KERNEL__ */ > > /* Utility function for outputing errors. */ > static int > @@ -151,6 +153,10 @@ gcov_error (const char *fmt, ...) > return ret; > } > > +/* A program checksum allows us to distinguish program data for an > + object file included in multiple programs. */ > +static gcov_unsigned_t gcov_crc32; > + > #ifndef __GCOV_KERNEL__ > /* Emitted in coverage.c. */ > extern char * __gcov_pmu_profile_filename; > @@ -183,10 +189,6 @@ THREAD_PREFIX gcov_unsigned_t __gcov_sample_counte > /* Chain of per-object gcov structures. */ > extern struct gcov_info *__gcov_list; > > -/* A program checksum allows us to distinguish program data for an > - object file included in multiple programs. */ > -static gcov_unsigned_t gcov_crc32; > - > /* Size of the longest file name. */ > static size_t gcov_max_filename = 0; > > @@ -323,8 +325,6 @@ gcov_counter_active (const struct gcov_info *info, > return (info->merge[type] != 0); > } > > -#ifndef __GCOV_KERNEL__ > - > /* Add an unsigned value to the current crc */ > > static gcov_unsigned_t > @@ -344,6 +344,8 @@ crc32_unsigned (gcov_unsigned_t crc32, gcov_unsign > return crc32; > } > > +#ifndef __GCOV_KERNEL__ > + > /* Check if VERSION of the info block PTR matches libgcov one. > Return 1 on success, or zero in case of versions mismatch. > If FILENAME is not NULL, its value used for reporting purposes > @@ -464,6 +466,8 @@ gcov_alloc_filename (void) > gi_filename_up = gi_filename + prefix_length; > } > > +#endif /* __GCOV_KERNEL__ */ > + > /* 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. */ > @@ -509,6 +513,8 @@ gcov_sort_icall_topn_counter (const struct gcov_ct > } > } > > +#ifndef __GCOV_KERNEL__ > + > /* Write imported files (auxiliary modules) for primary module GI_PTR > into file GI_FILENAME. */ > > @@ -586,6 +592,8 @@ gcov_dump_module_info (void) > __gcov_finalize_dyn_callgraph (); > } > > +#endif /* __GCOV_KERNEL__ */ > + > /* Insert counter VALUE into HISTOGRAM. */ > > static void > @@ -656,6 +664,8 @@ gcov_compute_histogram (struct gcov_summary *sum) > } > } > > +#ifndef __GCOV_KERNEL__ > + > /* Dump the coverage counts. 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 > @@ -1013,12 +1023,7 @@ gcov_merge_gcda_file (struct gcov_info *gi_ptr) > goto read_error; > } > if (tag && tag != GCOV_TAG_MODULE_INFO) > - { > - read_mismatch:; > - fprintf (stderr, "profiling:%s:Merge mismatch for %s\n", > - gi_filename, f_ix + 1 ? "function" : "summaries"); > - goto read_fatal; > - } > + goto read_mismatch; > } > goto rewrite; > > @@ -1031,6 +1036,11 @@ read_error:; > > goto rewrite; > > +read_mismatch:; > + gcov_error ("profiling:%s:Merge mismatch for %s\n", > + gi_filename, f_ix + 1 ? "function" : "summaries"); > + goto read_fatal; > + > read_fatal:; > gcov_close (); > return 1; > @@ -1076,7 +1086,7 @@ rewrite:; > sizeof (*cs_all) - (sizeof (gcov_bucket_type) > * GCOV_HISTOGRAM_SIZE))) > { > - fprintf (stderr, "profiling:%s:Invocation mismatch - " > + gcov_error ("profiling:%s:Invocation mismatch - " > "some data files may have been removed%s\n", > gi_filename, GCOV_LOCKED > ? "" : " or concurrent update without locking support"); > @@ -1093,14 +1103,14 @@ rewrite:; > the size is in units of gcov_type. */ > > GCOV_LINKAGE unsigned > -gcov_gcda_file_size (struct gcov_info *gi_ptr, > - struct gcov_summary *sum) > +gcov_gcda_file_size (struct gcov_info *gi_ptr) > { > unsigned size; > const struct gcov_fn_info *fi_ptr; > unsigned f_ix, t_ix, h_ix, h_cnt = 0; > unsigned n_counts; > const struct gcov_ctr_info *ci_ptr; > + struct gcov_summary *sum = &this_program; > const struct gcov_ctr_summary *csum; > > /* GCOV_DATA_MAGIC, GCOV_VERSION and time_stamp. */ > @@ -1181,13 +1191,14 @@ gcov_write_gcda_file (struct gcov_info *gi_ptr) > ci_ptr = gfi_ptr->ctrs; > for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) > { > + gcov_type *c_ptr; > if (!gi_ptr->merge[t_ix]) > 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; > + c_ptr = ci_ptr->values; > while (n_counts--) > gcov_write_counter (*c_ptr++); > ci_ptr++; > @@ -1692,7 +1703,7 @@ __gcov_topn_value_profiler_body (gcov_type *counte > { > unsigned i, j; > gcov_type *p, minv; > - gcov_type* tmp_cnts > + gcov_type* tmp_cnts > = (gcov_type *)alloca (topn_val * sizeof(gcov_type)); > > *num_eviction = 0; > @@ -2050,15 +2061,20 @@ gcov_set_vfile (gcov_kernel_vfile *file) > gcov_current_file = file; > } > > +/* Init function before dumping the gcda file in kernel. */ > + > +void > +gcov_kernel_dump_gcov_init (void) > +{ > + gcov_exit_init (); > +} > + > /* Dump one entry in the gcov_info list (for one object) in kernel. */ > > void > gcov_kernel_dump_one_gcov (struct gcov_info *info) > { > gcc_assert (gcov_current_file); > - > - gcov_exit_init (); > - > gcov_dump_one_gcov (info); > } > > Index: gcc/gcov-io.c > =================================================================== > --- gcc/gcov-io.c (revision 194562) > +++ gcc/gcov-io.c (working copy) > @@ -662,6 +662,30 @@ gcov_read_string (void) > return (const char *) gcov_read_words (length); > } > > +#ifdef __GCOV_KERNEL__ > +static const unsigned char __popcount_tab[256] = > +{ > + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, > + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, > + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, > + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, > + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, > + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, > + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, > + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 > +}; > + > +static int k_popcountll (long long x) > +{ > + int i, ret = 0; > + > + for (i = 0; i < 8*sizeof(long long) ; i += 8) > + ret += __popcount_tab[(x >> i) & 0xff]; > + > + return ret; > +} > +#endif > + > GCOV_LINKAGE void > gcov_read_summary (struct gcov_summary *summary) > { > @@ -683,7 +707,11 @@ gcov_read_summary (struct gcov_summary *summary) > for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) > { > histo_bitvector[bv_ix] = gcov_read_unsigned (); > +#ifndef __GCOV_KERNEL__ > h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]); > +#else > + h_cnt += k_popcountll (histo_bitvector[bv_ix]); > +#endif
Is the issue here that __builtin_popcountll is not available? I just committed a fix to trunk to deal with a similar issue, can you see if this would address the problem here too? http://gcc.gnu.org/ml/gcc-bugs/2012-12/msg01976.html Thanks, Teresa > } > bv_ix = 0; > h_ix = 0; > @@ -1137,7 +1165,6 @@ kernel_file_fclose (gcov_kernel_vfile *fp) > long > kernel_file_ftell (gcov_kernel_vfile *fp) > { > - gcc_assert (0); /* should not reach here */ > return 0; > } > > @@ -1192,8 +1219,9 @@ kernel_file_fwrite (const void *ptr, size_t size, > if (vsize <= vpos) > { > printk (KERN_ERR > - "GCOV_KERNEL: something wrong: vbuf=%p vsize=%u vpos=%u\n", > - vbuf, vsize, vpos); > + "GCOV_KERNEL: something wrong in file %s: vbuf=%p vsize=%u" > + " vpos=%u\n", > + fp->info->filename, vbuf, vsize, vpos); > return 0; > } > len = vsize - vpos; > @@ -1207,8 +1235,9 @@ kernel_file_fwrite (const void *ptr, size_t size, > > if (len != nitems) > printk (KERN_ERR > - "GCOV_KERNEL: something wrong: size=%lu nitems=%lu ret=%d\n", > - size, nitems, len); > + "GCOV_KERNEL: something wrong in file %s: size=%lu nitems=%lu" > + " ret=%d, vsize=%u vpos=%u \n", > + fp->info->filename, size, nitems, len, vsize, vpos); > return len; > } > > Index: gcc/gcov-io.h > =================================================================== > --- gcc/gcov-io.h (revision 194562) > +++ gcc/gcov-io.h (working copy) > @@ -300,6 +300,14 @@ typedef unsigned gcov_type_unsigned __attribute__ > > #endif /* BITS_PER_UNIT == 8 */ > > +#if LONG_LONG_TYPE_SIZE > 32 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8 > +#else > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4 > +#endif > + > #undef EXTRACT_MODULE_ID_FROM_GLOBAL_ID > #undef EXTRACT_FUNC_ID_FROM_GLOBAL_ID > #undef GEN_FUNC_GLOBAL_ID > @@ -322,6 +330,18 @@ typedef unsigned gcov_type_unsigned __attribute__ > typedef unsigned gcov_unsigned_t; > typedef unsigned gcov_position_t; > > +#if LONG_LONG_TYPE_SIZE > 32 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_8 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_8 > +#else > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD_FN __sync_fetch_and_add_4 > +#define GCOV_TYPE_SYNC_FETCH_AND_ADD BUILT_IN_SYNC_FETCH_AND_ADD_4 > +#endif > +#define PROFILE_GEN_EDGE_ATOMIC (flag_profile_gen_atomic == 1 || \ > + flag_profile_gen_atomic == 3) > +#define PROFILE_GEN_VALUE_ATOMIC (flag_profile_gen_atomic == 2 || \ > + flag_profile_gen_atomic == 3) > + > /* gcov_type is typedef'd elsewhere for the compiler */ > #if IN_GCOV > #define GCOV_LINKAGE static > @@ -781,8 +801,8 @@ struct gcov_info > unused) */ > > unsigned n_functions; /* number of functions */ > - const struct gcov_fn_info *const *functions; /* pointer to pointers > - to function information */ > + const struct gcov_fn_info **functions; /* pointer to pointers > + to function information */ > }; > > /* Information about a single imported module. */ > @@ -988,8 +1008,7 @@ static void gcov_rewrite (void); > GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; > GCOV_LINKAGE void gcov_truncate (void) ATTRIBUTE_HIDDEN; > GCOV_LINKAGE gcov_unsigned_t gcov_string_length (const char *) > ATTRIBUTE_HIDDEN; > -GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *, > - struct gcov_summary *); > +GCOV_LINKAGE unsigned gcov_gcda_file_size (struct gcov_info *); > #else > /* Available outside libgcov */ > GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, > > -- > This patch is available for review at http://codereview.appspot.com/6968046 -- Teresa Johnson | Software Engineer | tejohn...@google.com | 408-460-2413