> Hi, all
> 
> This is the new patch for gcov-tool (previously profile-tool).
> 
> Honza: can you comment on the new merge interface? David posted some
> comments in an earlier email and we want to know what's your opinion.
> 
> Test patch has been tested with boostrap, regresssion,
> profiledbootstrap and SPEC2006.
> 
> Noticeable changes from the earlier version:
> 
> 1. create a new file libgcov.h and move libgcov-*.h headers to libgcov.h
> So we can included multiple libgcov-*.c without adding new macros.
> 
> 2. split libgcov.h specific code in gcvo-io.h to libcc/libgcov.h
> Avoid multiple-page of code under IN_LIBGCOV macro -- this
> improves the readability.
> 
> 3. make gcov_var static, and move the definition from gcov-io.h to
> gcov-io.c. Also
>    move some static functions accessing gcov_var to gcvo-io.c
> Current code rely on GCOV_LINKAGE tricks to avoid multi-definition. I don't 
> see
> a reason that gcov_var needs to exposed as a global.
> 
> 4. expose gcov_write_strings() and gcov_sync() to gcov_tool usage
> 
> 5. rename profile-tool to gcov-tool per Honza's suggestion.
> 
> Thanks,

Hi,
I did not read in deatil the gcov-tool source itself, but lets first make the 
interface changes
needed.

> 2013-11-18  Rong Xu  <x...@google.com>
> 
>       * gcc/gcov-io.c (gcov_var): Moved from gcov-io.h and make it static.
>       (gcov_position): Move from gcov-io.h
>       (gcov_is_error): Ditto.
>       (gcov_rewrite): Ditto.
>       * gcc/gcov-io.h: Re-factoring. Move gcov_var to gcov-io.h and
>         move the libgcov only part of libgcc/libgcov.h.
>       * libgcc/libgcov.h: New common header files for libgcov-*.h
>       * libgcc/Makefile.in: Add dependence to libgcov.h
>       * libgcc/libgcov-profiler.c: Use libgcov.h
>       * libgcc/libgcov-driver.c: Ditto.
>       * libgcc/libgcov-interface.c: Ditto.
>       * libgcc/libgcov-driver-system.c (allocate_filename_struct): use
>       xmalloc instread of malloc.
>       * libgcc/libgcov-merge.c (void __gcov_merge_delta): Add more
>       parameters to merge function.
>       (__gcov_merge_add): Ditto.
>       (__gcov_merge_ior): Ditto.
>       (__gcov_merge_time_profile): Ditto.
>       (__gcov_merge_single): Ditto.
>       (__gcov_merge_delta): Ditto.
>       * libgcc/libgcov-tool.c (void gcov_tool_set_verbose): New for
>       gcov-tool support.
>       (set_fn_ctrs): Ditto.
>       (tag_function): Ditto.
>       (tag_blocks): Ditto.
>       (tag_arcs): Ditto.
>       (tag_lines): Ditto.
>       (tag_counters): Ditto.
>       (tag_summary): Ditto.
>       (read_gcda_finalize): Ditto.
>       (read_gcda_file): Ditto.
>       (ftw_read_file): Ditto.
>       (read_profile_dir_init) Ditto.:
>       (gcov_read_profile_dir): Ditto.
>       (gcov_merge): Ditto.
>       (find_match_gcov_inf Ditto.o):
>       (gcov_profile_merge): Ditto.
>       (__gcov_scale_add): Ditto.
>       (__gcov_scale_ior): Ditto.
>       (__gcov_scale_delta): Ditto.
>       (__gcov_scale_single): Ditto.
>       (gcov_profile_scale): Ditto.
>       (gcov_profile_normalize): Ditto.
>       (__gcov_scale2_add): Ditto.
>       (__gcov_scale2_ior): Ditto.
>       (__gcov_scale2_delta): Ditto.
>       (__gcov_scale2_single): Ditto.
>       (gcov_profile_scale2): Ditto.
>       * gcc/gcov-tool.c (unlink_file): Gcov-tool driver support.
>       (unlink_dir): Ditto.
>       (profile_merge): Ditto.
>       (print_merge_usage_message): Ditto.
>       (merge_usage): Ditto.
>       (do_merge): Ditto.
>       (profile_rewrite2): Ditto.
>       (profile_rewrite): Ditto.
>       (print_rewrite_usage_message): Ditto.
>       (rewrite_usage): Ditto.
>       (do_rewrite): Ditto.
>       (print_usage): Ditto.
>       (print_version): Ditto.
>       (process_args): Ditto.
>       (main): Ditto.
>       * gcc/Makefile.in: Build and install gcov-tool.

> Index: gcc/gcov-io.c
> ===================================================================
> --- gcc/gcov-io.c     (revision 204895)
> +++ gcc/gcov-io.c     (working copy)
> @@ -36,6 +36,37 @@ static const gcov_unsigned_t *gcov_read_words (uns
>  static void gcov_allocate (unsigned);
>  #endif
>  
> +/* Moved for gcov-io.h and make it static.  */
> +static struct gcov_var gcov_var;

This is more an changelog message than a comment in source file.
Just describe what gcov_var is.

Do you know how the size of libgcov changed with your patch? 
Quick check of current mainline on compiling empty main gives:

jh@gcc10:~/trunk/build/gcc$ cat t.c
main()
{
}
jh@gcc10:~/trunk/build/gcc$ ./xgcc -B ./ -O2 -fprofile-generate -o a.out-new 
--static t.c
jh@gcc10:~/trunk/build/gcc$ gcc -O2 -fprofile-generate -o a.out-old --static t.c
jh@gcc10:~/trunk/build/gcc$ size a.out-old
   text    data     bss     dec     hex filename
 608141    3560   16728  628429   996cd a.out-old
jh@gcc10:~/trunk/build/gcc$ size a.out-new
   text    data     bss     dec     hex filename
 612621    3688   22880  639189   9c0d5 a.out-new

Without profiling I get:
jh@gcc10:~/trunk/build/gcc$ size a.out-new-no
jh@gcc10:~/trunk/build/gcc$ size a.out-old-no
   text    data     bss     dec     hex filename
 599719    3448   12568  615735   96537 a.out-old-no
   text    data     bss     dec     hex filename
 600247    3448   12568  616263   96747 a.out-new-no

Quite big for empty program, but mostly glibc fault, I suppose
(that won't be an issue for embedded platforms). But anyway
we increased text size overhead from 8k to 12k, BSS size
overhead from 4k to 10k and data by another 1k.

   text    data     bss     dec     hex filename
    126       0       0     126      7e _gcov_merge_add.o (ex libgcov.a)
    251       0       0     251      fb _gcov_merge_single.o (ex libgcov.a)
    242       0       0     242      f2 _gcov_merge_delta.o (ex libgcov.a)
    126       0       0     126      7e _gcov_merge_ior.o (ex libgcov.a)
    156       0       0     156      9c _gcov_merge_time_profile.o (ex 
libgcov.a)
     89       0       0      89      59 _gcov_interval_profiler.o (ex libgcov.a)
     69       0       0      69      45 _gcov_pow2_profiler.o (ex libgcov.a)
    115       0       0     115      73 _gcov_one_value_profiler.o (ex 
libgcov.a)
    122       0       0     122      7a _gcov_indirect_call_profiler.o (ex 
libgcov.a)
     57       0       0      57      39 _gcov_average_profiler.o (ex libgcov.a)
     52       0       0      52      34 _gcov_ior_profiler.o (ex libgcov.a)
    178       0      16     194      c2 _gcov_indirect_call_profiler_v2.o (ex 
libgcov.a)
     77       0       8      85      55 _gcov_time_profiler.o (ex libgcov.a)
    126       0      40     166      a6 _gcov_flush.o (ex libgcov.a)
    101       0       0     101      65 _gcov_fork.o (ex libgcov.a)
    471       0       0     471     1d7 _gcov_execl.o (ex libgcov.a)
    471       0       0     471     1d7 _gcov_execlp.o (ex libgcov.a)
    524       0       0     524     20c _gcov_execle.o (ex libgcov.a)
     98       0       0      98      62 _gcov_execv.o (ex libgcov.a)
     98       0       0      98      62 _gcov_execvp.o (ex libgcov.a)
    108       0       0     108      6c _gcov_execve.o (ex libgcov.a)
     66       0       0      66      42 _gcov_reset.o (ex libgcov.a)
     66       0       0      66      42 _gcov_dump.o (ex libgcov.a)
   9505       0    6144   15649    3d21 _gcov.o (ex libgcov.a)

I think we definitely need to move those 6k of bss space out.  I think those 
are new
static vars you introduced that I think are unsafe anyway because multiple 
streaming
may run at once in threaded program where locking mechanizm fails.
(it will probably do other bad things, but definitely we do not want to
conflict on things like filename to write into).

Compared to my system gcov:
   text    data     bss     dec     hex filename
   9765       0      64    9829    2665 _gcov.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    125       0       0     125      7d _gcov_merge_add.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    251       0       0     251      fb _gcov_merge_single.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    242       0       0     242      f2 _gcov_merge_delta.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    101       0       0     101      65 _gcov_fork.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    471       0       0     471     1d7 _gcov_execl.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    471       0       0     471     1d7 _gcov_execlp.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    524       0       0     524     20c _gcov_execle.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     98       0       0      98      62 _gcov_execv.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     98       0       0      98      62 _gcov_execvp.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    108       0       0     108      6c _gcov_execve.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     72       0       0      72      48 _gcov_reset.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     72       0       0      72      48 _gcov_dump.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     89       0       0      89      59 _gcov_interval_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     69       0       0      69      45 _gcov_pow2_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    115       0       0     115      73 _gcov_one_value_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    122       0       0     122      7a _gcov_indirect_call_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     57       0       0      57      39 _gcov_average_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
     52       0       0      52      34 _gcov_ior_profiler.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)
    125       0       0     125      7d _gcov_merge_ior.o (ex 
./lib64/gcc/x86_64-suse-linux/4.8/libgcov.a)

> Index: gcc/gcov-io.h
> ===================================================================
> --- gcc/gcov-io.h     (revision 204895)
> +++ gcc/gcov-io.h     (working copy)
> @@ -164,51 +164,7 @@ see the files COPYING3 and COPYING.RUNTIME respect
>  #ifndef GCC_GCOV_IO_H
>  #define GCC_GCOV_IO_H
>  
> -#if IN_LIBGCOV
> -/* About the target */
> -
> -#if BITS_PER_UNIT == 8
> -typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI)));
> -typedef unsigned gcov_position_t __attribute__ ((mode (SI)));
> -#if LONG_LONG_TYPE_SIZE > 32
> -typedef signed gcov_type __attribute__ ((mode (DI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (DI)));
> -#else
> -typedef signed gcov_type __attribute__ ((mode (SI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI)));
> -#endif
> -#else
> -#if BITS_PER_UNIT == 16
> -typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI)));
> -typedef unsigned gcov_position_t __attribute__ ((mode (HI)));
> -#if LONG_LONG_TYPE_SIZE > 32
> -typedef signed gcov_type __attribute__ ((mode (SI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI)));
> -#else
> -typedef signed gcov_type __attribute__ ((mode (HI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI)));
> -#endif
> -#else
> -typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI)));
> -typedef unsigned gcov_position_t __attribute__ ((mode (QI)));
> -#if LONG_LONG_TYPE_SIZE > 32
> -typedef signed gcov_type __attribute__ ((mode (HI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI)));
> -#else
> -typedef signed gcov_type __attribute__ ((mode (QI)));
> -typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI)));
> -#endif
> -#endif
> -#endif

So this part basically moves libgcov specific bits into libgcov.h? That OK fine 
by
itself.
> Index: libgcc/libgcov-profiler.c
> ===================================================================
> --- libgcc/libgcov-profiler.c (revision 204895)
> +++ libgcc/libgcov-profiler.c (working copy)
> @@ -23,15 +23,8 @@ a copy of the GCC Runtime Library Exception along
>  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  <http://www.gnu.org/licenses/>.  */
>  
> -#include "tconfig.h"
> -#include "tsystem.h"
> -#include "coretypes.h"
> -#include "tm.h"
> -#include "libgcc_tm.h"
> -
> +#include "libgcov.h"
>  #if !defined(inhibit_libc)
> -#define IN_LIBGCOV 1
> -#include "gcov-io.h"

I did not pay that much attention into the current include file changes, but 
wasn't
idea to avoid #include file to include random other #includes?
So perhaps the first block of includes should stay, followed by libgcov.h and 
gcov-io.h
last?
> @@ -325,6 +311,9 @@ static struct gcov_summary all_prg;
>  #endif
>  /* crc32 for this program.  */
>  static gcov_unsigned_t crc32;
> +/* Use this summary checksum rather the computed one if the value is
> + *    non-zero.  */
> +static gcov_unsigned_t saved_summary_checksum;

Why do you need to save the checksum? Won't it reset summary back with multiple 
streaming?

I would really like to avoid introducing those static vars that are used 
exclusively
by gcov_exit.  What about putting them into an gcov_context structure that
is passed around the functions that was broken out?
> Index: libgcc/libgcov-merge.c
> ===================================================================
> --- libgcc/libgcov-merge.c    (revision 204895)
> +++ libgcc/libgcov-merge.c    (working copy)
> @@ -23,107 +23,150 @@ a copy of the GCC Runtime Library Exception along
>  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  <http://www.gnu.org/licenses/>.  */
>  
> -#include "tconfig.h"
> -#include "tsystem.h"
> -#include "coretypes.h"
> -#include "tm.h"
> -#include "libgcc_tm.h"
> +#include "libgcov.h"
>  
> -#if defined(inhibit_libc)
> -#define IN_LIBGCOV (-1)
> -#else
> -#define IN_LIBGCOV 1
> +#include "gcov-io-libgcov.h"
>  #endif
>  
> -#include "gcov-io.h"
> -
>  #if defined(inhibit_libc)
>  /* If libc and its header files are not available, provide dummy functions.  
> */
>  
>  #ifdef L_gcov_merge_add
>  void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
> -                       unsigned n_counters __attribute__ ((unused))) {}
> +                       unsigned n_counters __attribute__ ((unused)),
> +                       unsigned gcov_type *src __attribute__ ((unused)),
> +                       unsigned w __attribute__ ((unused))) {}
>  #endif
>  
>  #ifdef L_gcov_merge_single
>  void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
> -                          unsigned n_counters __attribute__ ((unused))) {}
> +                          unsigned n_counters __attribute__ ((unused)),
> +                          unsigned gcov_type *src __attribute__ ((unused)),
> +                          unsigned w __attribute__ ((unused))) {}
>  #endif
>  
>  #ifdef L_gcov_merge_delta
>  void __gcov_merge_delta (gcov_type *counters  __attribute__ ((unused)),
> -                         unsigned n_counters __attribute__ ((unused))) {}
> +                         unsigned n_counters __attribute__ ((unused)),
> +                         unsigned gcov_type *src __attribute__ ((unused)),
> +                         unsigned w __attribute__ ((unused))) {}
>  #endif
>  
>  #else
>  
>  #ifdef L_gcov_merge_add
>  /* The profile merging function that just adds the counters.  It is given
> -   an array COUNTERS of N_COUNTERS old counters and it reads the same number
> -   of counters from the gcov file.  */
> +   an array COUNTERS of N_COUNTERS old counters. 
> +   When SRC==NULL, it reads the same number of counters from the gcov file.
> +   Otherwise, it reads from SRC array. These read values will be multiplied
> +   by weight W before adding to the old counters.  */
>  void
> -__gcov_merge_add (gcov_type *counters, unsigned n_counters)
> +__gcov_merge_add (gcov_type *counters, unsigned n_counters,
> +                  gcov_type *src, unsigned w)
>  {
> +  int in_mem = (src != 0);
> +
>    for (; n_counters; counters++, n_counters--)
> -    *counters += gcov_read_counter ();
> +    {
> +      gcov_type value;
> +
> +      if (in_mem)
> +        value = *(src++);
> +      else
> +        value = gcov_read_counter ();
> +
> +      *counters += w * value;
> +    }
>  }
>  #endif /* L_gcov_merge_add */
>  
>  #ifdef L_gcov_merge_ior
>  /* The profile merging function that just adds the counters.  It is given
> -   an array COUNTERS of N_COUNTERS old counters and it reads the same number
> -   of counters from the gcov file.  */
> +   an array COUNTERS of N_COUNTERS old counters. 
> +   When SRC==NULL, it reads the same number of counters from the gcov file.
> +   Otherwise, it reads from SRC array.  */
>  void
> -__gcov_merge_ior (gcov_type *counters, unsigned n_counters)
> +__gcov_merge_ior (gcov_type *counters, unsigned n_counters,
> +                  gcov_type *src, unsigned w __attribute__ ((unused)))

So the new in-memory variants are introduced for merging tool, while libgcc use 
gcov_read_counter
interface?
Perhaps we can actually just duplicate the functions to avoid runtime to do all 
the scalling
and in_mem tests it won't need?

I would suggest going with libgcov.h changes and clenaups first, with interface 
changes next
and the gcov-tool is probably quite obvious at the end?
Do you think you can split the patch this way?

Thanks and sorry for taking long to review. I should have more time again now.
Honza

Reply via email to