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

Reply via email to