mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-31 16:20:21 +08:00
Makefile.in (LIBGCC_DEPS): Add gcov headers.
* Makefile.in (LIBGCC_DEPS): Add gcov headers. (libgcov.a): Depends on LIBGCC_DEPS. * basic-block.h (profile_info): Moved here from coverage.h. Made a pointer. * coverage.c (struct function_list): Fixed array of counter types. (struct counts_entry): Keyed by counter type, contains summary. (profile_info): Moved to profile.c. (prg_ctr_mask, prg_n_ctrs, fn_ctr_mask, fn_n_ctrs): New global vars. (profiler_label): Remove. (ctr_labels): New. (set_purpose, label_for_tag, build_counter_section_fields, build_counter_section_value, build_counter_section_data_fields, build_counter_section_data_values, build_function_info_fields, build_function_info_value, gcov_info_fields, gcov_info_value): Remove. (build_fn_info_type, build_fn_info_value, build_ctr_info_type, build_ctr_info_value, build_gcov_info): New. (htab_counts_entry_hash, htab_counts_entry_eq): Adjust. (reads_counts_file): Adjust. (get_coverage_counts): Takes counter number. Add summary parameter. Adjust. (coverage_counter_ref): Tkaes counter number. Adjust. Lazily create counter array labels. (coverage_end_function): Adjust. (create_coverage): Adjust. (find_counters_section): Remove. * coverage.h (MAX_COUNTER_SECTIONS): Remove. (struct section_info, struct profile_info): Remove. (profile_info): Moved to basic-block.h. (coverage_counter_ref): Takes a counter number. (get_coverage_counts): Takes a counter number. Added summary parameter. (find_counters_section): Remove. * gcov-dump.c (tag_arc_counts): Rename to ... (tag_counters): ... here. Adjust. (tag_table): Move tag_counters to 3rd entry. Remove PROGRAM_PLACEHOLDER and PROGRAM_INCORRECT entries. (dump_file): Check for counter tag values here. (tag_summary): Adjust. * gcov-io.c (gcov_write_summary, gcov_read_summary): Adjust. * gcov-io.h (GCOV_LOCKED): New. (GCOV_TAG_ARC_COUNTS): Rename to ... (GCOV_TAG_COUNTS_BASE): ... here. (GCOV_TAG_PLACEHOLDER_SUMMARY, GCOV_TAG_INCORRECT_SUMMARY): Remove. (GCOV_COUNTER_ARCS, GCOV_COUNTERS, GCOV_NAMES): New. (GCOV_TAG_FOR_COUNTER, GCOV_COUNTER_FOR_TAG, GCOV_TAG_IS_COUNTER): New. (struct gcov_ctr_summary): New. (struct gcov_summary): Adjust. (struct gcov_counter_section): Remove. struct gcov_counter_section_data): Remove. (struct gcov_function_info): Rename to ... (struct gcov_fn_info): ... here. Adjust. (struct gcov_ctr_info): New. (struct gcov_info): Adjust. * gcov.c (read_count_file): Adjust. (output_lines): Adjust. * libgcov.c (gcov_exit): Adjust. (__gcov_flush): Adjust. * mklibgcc.in (libgcc2_c_dep): Add gcov headers. * predict.c (maybe_hot_bb_p, probably_cold_bb_p, probably_never_executed_bb_p, compute_frequency_function): Adjust profile_info use. * profile.c (struct counts_entry): Remove. (profile_info): Define here. (get_exec_counts): Adjust get_coverage_counts call. (compute_branch_probablilities): Remove find_counters_section call. (gen_edge_profiler): Adjust coverage_counter_ref call. * tracer.c (tail_duplicate): Adjust profile_info use. From-SVN: r65990
This commit is contained in:
parent
2be3b5ce22
commit
cdb2376773
@ -1,3 +1,77 @@
|
||||
2003-04-23 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* Makefile.in (LIBGCC_DEPS): Add gcov headers.
|
||||
(libgcov.a): Depends on LIBGCC_DEPS.
|
||||
* basic-block.h (profile_info): Moved here from coverage.h. Made
|
||||
a pointer.
|
||||
* coverage.c (struct function_list): Fixed array of counter types.
|
||||
(struct counts_entry): Keyed by counter type, contains summary.
|
||||
(profile_info): Moved to profile.c.
|
||||
(prg_ctr_mask, prg_n_ctrs, fn_ctr_mask, fn_n_ctrs): New global
|
||||
vars.
|
||||
(profiler_label): Remove.
|
||||
(ctr_labels): New.
|
||||
(set_purpose, label_for_tag, build_counter_section_fields,
|
||||
build_counter_section_value, build_counter_section_data_fields,
|
||||
build_counter_section_data_values, build_function_info_fields,
|
||||
build_function_info_value, gcov_info_fields, gcov_info_value): Remove.
|
||||
(build_fn_info_type, build_fn_info_value, build_ctr_info_type,
|
||||
build_ctr_info_value, build_gcov_info): New.
|
||||
(htab_counts_entry_hash, htab_counts_entry_eq): Adjust.
|
||||
(reads_counts_file): Adjust.
|
||||
(get_coverage_counts): Takes counter number. Add summary
|
||||
parameter. Adjust.
|
||||
(coverage_counter_ref): Tkaes counter number. Adjust. Lazily
|
||||
create counter array labels.
|
||||
(coverage_end_function): Adjust.
|
||||
(create_coverage): Adjust.
|
||||
(find_counters_section): Remove.
|
||||
* coverage.h (MAX_COUNTER_SECTIONS): Remove.
|
||||
(struct section_info, struct profile_info): Remove.
|
||||
(profile_info): Moved to basic-block.h.
|
||||
(coverage_counter_ref): Takes a counter number.
|
||||
(get_coverage_counts): Takes a counter number. Added summary
|
||||
parameter.
|
||||
(find_counters_section): Remove.
|
||||
* gcov-dump.c (tag_arc_counts): Rename to ...
|
||||
(tag_counters): ... here. Adjust.
|
||||
(tag_table): Move tag_counters to 3rd entry. Remove
|
||||
PROGRAM_PLACEHOLDER and PROGRAM_INCORRECT entries.
|
||||
(dump_file): Check for counter tag values here.
|
||||
(tag_summary): Adjust.
|
||||
* gcov-io.c (gcov_write_summary, gcov_read_summary): Adjust.
|
||||
* gcov-io.h (GCOV_LOCKED): New.
|
||||
(GCOV_TAG_ARC_COUNTS): Rename to ...
|
||||
(GCOV_TAG_COUNTS_BASE): ... here.
|
||||
(GCOV_TAG_PLACEHOLDER_SUMMARY, GCOV_TAG_INCORRECT_SUMMARY):
|
||||
Remove.
|
||||
(GCOV_COUNTER_ARCS, GCOV_COUNTERS, GCOV_NAMES): New.
|
||||
(GCOV_TAG_FOR_COUNTER, GCOV_COUNTER_FOR_TAG,
|
||||
GCOV_TAG_IS_COUNTER): New.
|
||||
(struct gcov_ctr_summary): New.
|
||||
(struct gcov_summary): Adjust.
|
||||
(struct gcov_counter_section): Remove.
|
||||
struct gcov_counter_section_data): Remove.
|
||||
(struct gcov_function_info): Rename to ...
|
||||
(struct gcov_fn_info): ... here. Adjust.
|
||||
(struct gcov_ctr_info): New.
|
||||
(struct gcov_info): Adjust.
|
||||
* gcov.c (read_count_file): Adjust.
|
||||
(output_lines): Adjust.
|
||||
* libgcov.c (gcov_exit): Adjust.
|
||||
(__gcov_flush): Adjust.
|
||||
* mklibgcc.in (libgcc2_c_dep): Add gcov headers.
|
||||
* predict.c (maybe_hot_bb_p, probably_cold_bb_p,
|
||||
probably_never_executed_bb_p, compute_frequency_function): Adjust
|
||||
profile_info use.
|
||||
* profile.c (struct counts_entry): Remove.
|
||||
(profile_info): Define here.
|
||||
(get_exec_counts): Adjust get_coverage_counts call.
|
||||
(compute_branch_probablilities): Remove find_counters_section
|
||||
call.
|
||||
(gen_edge_profiler): Adjust coverage_counter_ref call.
|
||||
* tracer.c (tail_duplicate): Adjust profile_info use.
|
||||
|
||||
2003-04-23 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/10339
|
||||
|
@ -1112,9 +1112,9 @@ LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
|
||||
$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
|
||||
tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
|
||||
$(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
|
||||
$(srcdir)/config/$(LIB1ASMSRC)
|
||||
$(srcdir)/config/$(LIB1ASMSRC) gcov-io.h gcov-io.c gcov-iov.h
|
||||
|
||||
libgcov.a: libgcc.a; @true
|
||||
libgcov.a: $(LIBGCC_DEPS); @true
|
||||
|
||||
libgcc.a: $(LIBGCC_DEPS)
|
||||
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
|
||||
|
@ -155,6 +155,10 @@ typedef struct edge_def {
|
||||
|
||||
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
|
||||
|
||||
/* Counter summary from the last set of coverage counts read by
|
||||
profile.c. */
|
||||
extern const struct gcov_ctr_summary *profile_info;
|
||||
|
||||
/* Declared in cfgloop.h. */
|
||||
struct loop;
|
||||
struct loops;
|
||||
|
851
gcc/coverage.c
851
gcc/coverage.c
File diff suppressed because it is too large
Load Diff
@ -23,50 +23,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
#include "gcov-io.h"
|
||||
|
||||
/* The number of different counter sections. */
|
||||
#define MAX_COUNTER_SECTIONS 1
|
||||
|
||||
/* Info about number of counters in the section. */
|
||||
struct section_info
|
||||
{
|
||||
unsigned tag; /* Section tag. */
|
||||
int present; /* Are the data from this section read into gcc? */
|
||||
int n_counters; /* Total number of counters. */
|
||||
int n_counters_now; /* Number of counters in the current function. */
|
||||
};
|
||||
|
||||
struct profile_info
|
||||
{
|
||||
/* Information about numbers of counters in counter sections, for
|
||||
allocating the storage and storing the sizes. */
|
||||
unsigned n_sections;
|
||||
struct section_info section_info[MAX_COUNTER_SECTIONS];
|
||||
|
||||
/* Checksum of the cfg. Used for 'identification' of code.
|
||||
Used by final. */
|
||||
|
||||
unsigned current_function_cfg_checksum;
|
||||
|
||||
/* Max. value of counter in program corresponding to the profile data
|
||||
for the current function. */
|
||||
|
||||
gcov_type max_counter_in_program;
|
||||
|
||||
/* The number of profiles merged to form the profile data for the current
|
||||
function. */
|
||||
int count_profiles_merged;
|
||||
};
|
||||
|
||||
extern struct profile_info profile_info;
|
||||
|
||||
extern void coverage_init (const char *);
|
||||
extern void coverage_finish (void);
|
||||
extern void coverage_end_function (void);
|
||||
extern int coverage_begin_output (void);
|
||||
extern rtx coverage_counter_ref (unsigned /*tag*/, unsigned/*num*/);
|
||||
|
||||
gcov_type *get_coverage_counts (unsigned /*tag*/, unsigned /*expected*/);
|
||||
struct section_info *find_counters_section PARAMS ((unsigned));
|
||||
|
||||
extern rtx coverage_counter_ref (unsigned /*counter*/, unsigned/*num*/);
|
||||
extern gcov_type *get_coverage_counts (unsigned /*counter*/,
|
||||
unsigned /*expected*/,
|
||||
const struct gcov_ctr_summary **);
|
||||
|
||||
#endif
|
||||
|
@ -35,7 +35,7 @@ static void tag_function PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_blocks PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_arcs PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_lines PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_arc_counts PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_counters PARAMS ((const char *, unsigned, unsigned));
|
||||
static void tag_summary PARAMS ((const char *, unsigned, unsigned));
|
||||
extern int main PARAMS ((int, char **));
|
||||
|
||||
@ -59,15 +59,13 @@ static const tag_format_t tag_table[] =
|
||||
{
|
||||
{0, "NOP", NULL},
|
||||
{0, "UNKNOWN", NULL},
|
||||
{0, "COUNTERS", tag_counters},
|
||||
{GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
|
||||
{GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
|
||||
{GCOV_TAG_ARCS, "ARCS", tag_arcs},
|
||||
{GCOV_TAG_LINES, "LINES", tag_lines},
|
||||
{GCOV_TAG_ARC_COUNTS, "ARC_COUNTS", tag_arc_counts},
|
||||
{GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
|
||||
{GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary},
|
||||
{GCOV_TAG_PLACEHOLDER_SUMMARY, "PROGRAM_PLACEHOLDER", tag_summary},
|
||||
{GCOV_TAG_INCORRECT_SUMMARY, "PROGRAM_INCORRECT", tag_summary},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -208,7 +206,7 @@ dump_file (filename)
|
||||
for (format = tag_table; format->name; format++)
|
||||
if (format->tag == tag)
|
||||
goto found;
|
||||
format = &tag_table[1];
|
||||
format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
|
||||
found:;
|
||||
if (tag)
|
||||
{
|
||||
@ -364,14 +362,16 @@ tag_lines (filename, tag, length)
|
||||
}
|
||||
|
||||
static void
|
||||
tag_arc_counts (filename, tag, length)
|
||||
tag_counters (filename, tag, length)
|
||||
const char *filename ATTRIBUTE_UNUSED;
|
||||
unsigned tag ATTRIBUTE_UNUSED;
|
||||
unsigned length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
static const char *const counter_names[] = GCOV_COUNTER_NAMES;
|
||||
unsigned n_counts = length / 8;
|
||||
|
||||
printf (" %u counts", n_counts);
|
||||
printf (" %s %u counts",
|
||||
counter_names[GCOV_COUNTER_FOR_TAG (tag)], n_counts);
|
||||
if (flag_dump_contents)
|
||||
{
|
||||
unsigned ix;
|
||||
@ -395,20 +395,21 @@ tag_summary (filename, tag, length)
|
||||
unsigned length ATTRIBUTE_UNUSED;
|
||||
{
|
||||
struct gcov_summary summary;
|
||||
|
||||
gcov_read_summary (&summary);
|
||||
unsigned ix;
|
||||
|
||||
gcov_read_summary (&summary);
|
||||
printf (" checksum=0x%08x", summary.checksum);
|
||||
|
||||
printf ("\n%s:\t\truns=%u, arcs=%u", filename,
|
||||
summary.runs, summary.arcs);
|
||||
printf ("\n%s:\t\tarc_sum=", filename);
|
||||
printf (HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.arc_sum);
|
||||
printf (", arc_max_one=");
|
||||
printf (HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.arc_max_one);
|
||||
printf (", sum_max=");
|
||||
printf (HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.arc_sum_max);
|
||||
for (ix = 0; ix != GCOV_COUNTERS; ix++)
|
||||
{
|
||||
printf ("\n%sL\t\tcounts=%u, runs=%u", filename,
|
||||
summary.ctrs[ix].num, summary.ctrs[ix].runs);
|
||||
|
||||
printf (", sum_all=" HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.ctrs[ix].sum_all);
|
||||
printf (", run_max=" HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.ctrs[ix].run_max);
|
||||
printf (", sum_max=" HOST_WIDEST_INT_PRINT_DEC,
|
||||
(HOST_WIDEST_INT)summary.ctrs[ix].sum_max);
|
||||
}
|
||||
}
|
||||
|
@ -305,15 +305,20 @@ gcov_write_length (unsigned long position)
|
||||
GCOV_LINKAGE void
|
||||
gcov_write_summary (unsigned tag, const struct gcov_summary *summary)
|
||||
{
|
||||
unsigned ix;
|
||||
const struct gcov_ctr_summary *csum;
|
||||
unsigned long base;
|
||||
|
||||
base = gcov_write_tag (tag);
|
||||
gcov_write_unsigned (summary->checksum);
|
||||
gcov_write_unsigned (summary->runs);
|
||||
gcov_write_unsigned (summary->arcs);
|
||||
gcov_write_counter (summary->arc_sum);
|
||||
gcov_write_counter (summary->arc_max_one);
|
||||
gcov_write_counter (summary->arc_sum_max);
|
||||
for (csum = summary->ctrs, ix = GCOV_COUNTERS; ix--; csum++)
|
||||
{
|
||||
gcov_write_unsigned (csum->num);
|
||||
gcov_write_unsigned (csum->runs);
|
||||
gcov_write_counter (csum->sum_all);
|
||||
gcov_write_counter (csum->run_max);
|
||||
gcov_write_counter (csum->sum_max);
|
||||
}
|
||||
gcov_write_length (base);
|
||||
}
|
||||
#endif /* IN_LIBGCOV */
|
||||
@ -406,15 +411,20 @@ gcov_read_string ()
|
||||
GCOV_LINKAGE void
|
||||
gcov_read_summary (struct gcov_summary *summary)
|
||||
{
|
||||
unsigned ix;
|
||||
struct gcov_ctr_summary *csum;
|
||||
|
||||
summary->checksum = gcov_read_unsigned ();
|
||||
summary->runs = gcov_read_unsigned ();
|
||||
summary->arcs = gcov_read_unsigned ();
|
||||
summary->arc_sum = gcov_read_counter ();
|
||||
summary->arc_max_one = gcov_read_counter ();
|
||||
summary->arc_sum_max = gcov_read_counter ();
|
||||
for (csum = summary->ctrs, ix = GCOV_COUNTERS; ix--; csum++)
|
||||
{
|
||||
csum->num = gcov_read_unsigned ();
|
||||
csum->runs = gcov_read_unsigned ();
|
||||
csum->sum_all = gcov_read_counter ();
|
||||
csum->run_max = gcov_read_counter ();
|
||||
csum->sum_max = gcov_read_counter ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if IN_GCOV > 0
|
||||
/* Return the modification time of the current gcov file. */
|
||||
|
||||
|
@ -127,8 +127,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
function-data: announce_function arc_counts
|
||||
announce_function: header string:name int32:checksum
|
||||
arc_counts: header int64:count*
|
||||
summary: in32:checksum int32:runs int32:arcs int64:sum int64:max \
|
||||
int64:sum_max
|
||||
summary: int32:checksum {count-summary}GCOV_COUNTERS
|
||||
count-summary: int32:num int32:runs int64:sum
|
||||
int64:max int64:sum_max
|
||||
|
||||
The ANNOUNCE_FUNCTION record is the same as that in the BBG file,
|
||||
but without the source location.
|
||||
@ -160,6 +161,11 @@ typedef long gcov_type;
|
||||
#else
|
||||
typedef long long gcov_type;
|
||||
#endif
|
||||
#if defined (TARGET_HAS_F_SETLKW)
|
||||
#define GCOV_LOCKED 1
|
||||
#else
|
||||
#define GCOV_LOCKED 0
|
||||
#endif
|
||||
#endif /* IN_LIBGCOV */
|
||||
#if IN_GCOV
|
||||
typedef HOST_WIDEST_INT gcov_type;
|
||||
@ -201,11 +207,26 @@ typedef HOST_WIDEST_INT gcov_type;
|
||||
#define GCOV_TAG_BLOCKS ((unsigned)0x01410000)
|
||||
#define GCOV_TAG_ARCS ((unsigned)0x01430000)
|
||||
#define GCOV_TAG_LINES ((unsigned)0x01450000)
|
||||
#define GCOV_TAG_ARC_COUNTS ((unsigned)0x01a10000)
|
||||
#define GCOV_TAG_COUNTER_BASE ((unsigned)0x01a10000) /* First counter */
|
||||
#define GCOV_TAG_OBJECT_SUMMARY ((unsigned)0xa1000000)
|
||||
#define GCOV_TAG_PROGRAM_SUMMARY ((unsigned)0xa3000000)
|
||||
#define GCOV_TAG_PLACEHOLDER_SUMMARY ((unsigned)0xa5000000)
|
||||
#define GCOV_TAG_INCORRECT_SUMMARY ((unsigned)0xa7000000)
|
||||
|
||||
/* Counters that are collected. */
|
||||
#define GCOV_COUNTER_ARCS 0 /* Arc transitions. */
|
||||
#define GCOV_COUNTERS 1
|
||||
|
||||
/* A list of human readable names of the counters */
|
||||
#define GCOV_COUNTER_NAMES {"arcs"}
|
||||
|
||||
/* Convert a counter index to a tag. */
|
||||
#define GCOV_TAG_FOR_COUNTER(COUNT) \
|
||||
(GCOV_TAG_COUNTER_BASE + ((COUNT) << 17))
|
||||
/* Convert a tag to a counter. */
|
||||
#define GCOV_COUNTER_FOR_TAG(TAG) \
|
||||
(((TAG) - GCOV_TAG_COUNTER_BASE) >> 17)
|
||||
/* Check whether a tag is a counter tag. */
|
||||
#define GCOV_TAG_IS_COUNTER(TAG) \
|
||||
(!((TAG) & 0xFFFF) && GCOV_COUNTER_FOR_TAG (TAG) < GCOV_COUNTERS)
|
||||
|
||||
/* The tag level mask has 1's in the position of the inner levels, &
|
||||
the lsb of the current level, and zero on the current and outer
|
||||
@ -231,44 +252,43 @@ typedef HOST_WIDEST_INT gcov_type;
|
||||
|
||||
/* Structured records. */
|
||||
|
||||
/* Cumulative counter data. */
|
||||
struct gcov_ctr_summary
|
||||
{
|
||||
unsigned num; /* number of counters. */
|
||||
unsigned runs; /* number of program runs */
|
||||
gcov_type sum_all; /* sum of all counters accumulated. */
|
||||
gcov_type run_max; /* maximum value on a single run. */
|
||||
gcov_type sum_max; /* sum of individual run max values. */
|
||||
};
|
||||
|
||||
/* Object & program summary record. */
|
||||
struct gcov_summary
|
||||
{
|
||||
unsigned checksum; /* checksum of program */
|
||||
unsigned runs; /* number of program runs */
|
||||
unsigned arcs; /* number of instrumented arcs */
|
||||
gcov_type arc_sum; /* sum of all arc counters */
|
||||
gcov_type arc_max_one; /* max counter on any one run */
|
||||
gcov_type arc_sum_max; /* sum of max_one */
|
||||
struct gcov_ctr_summary ctrs[GCOV_COUNTERS];
|
||||
};
|
||||
|
||||
/* Structures embedded in coveraged program. The structures generated
|
||||
by write_profile must match these. */
|
||||
|
||||
/* Information about section of counters for a function. */
|
||||
struct gcov_counter_section
|
||||
{
|
||||
unsigned tag; /* Tag of the section. */
|
||||
unsigned n_counters; /* Number of counters in the section. */
|
||||
};
|
||||
|
||||
#if IN_LIBGCOV
|
||||
/* Information about section of counters for an object file. */
|
||||
struct gcov_counter_section_data
|
||||
{
|
||||
unsigned tag; /* Tag of the section. */
|
||||
unsigned n_counters; /* Number of counters in the section. */
|
||||
gcov_type *counters; /* The data. */
|
||||
};
|
||||
|
||||
/* Information about a single function. */
|
||||
struct gcov_function_info
|
||||
/* Information about a single function. This uses the trailing array
|
||||
idiom. The number of counters is determined from the counter_mask
|
||||
in gcov_info. We hold an array of function info, so have to
|
||||
explicitly calculate the correct array stride. */
|
||||
struct gcov_fn_info
|
||||
{
|
||||
const char *name; /* (mangled) name of function */
|
||||
unsigned checksum; /* function checksum */
|
||||
unsigned n_counter_sections; /* Number of types of counters */
|
||||
const struct gcov_counter_section *counter_sections;
|
||||
/* The section descriptions */
|
||||
unsigned n_ctrs[0]; /* instrumented counters */
|
||||
};
|
||||
|
||||
/* Information about counters. */
|
||||
struct gcov_ctr_info
|
||||
{
|
||||
unsigned num; /* number of counters. */
|
||||
gcov_type *values; /* their values. */
|
||||
};
|
||||
|
||||
/* Information about a single object file. */
|
||||
@ -278,14 +298,15 @@ struct gcov_info
|
||||
struct gcov_info *next; /* link to next, used by libgcc */
|
||||
|
||||
const char *filename; /* output file name */
|
||||
long wkspc; /* libgcc workspace */
|
||||
|
||||
unsigned n_functions; /* number of functions */
|
||||
const struct gcov_function_info *functions; /* table of functions */
|
||||
const struct gcov_fn_info *functions; /* table of functions */
|
||||
|
||||
unsigned n_counter_sections; /* Number of types of counters */
|
||||
const struct gcov_counter_section_data *counter_sections;
|
||||
/* The data to be put into the sections. */
|
||||
unsigned ctr_mask; /* mask of counters instrumented. */
|
||||
struct gcov_ctr_info counts[0]; /* count data. The number of bits
|
||||
set in the ctr_mask field
|
||||
determines how big this array
|
||||
is. */
|
||||
};
|
||||
|
||||
/* Register a new object file module. */
|
||||
|
@ -1011,8 +1011,7 @@ read_count_file ()
|
||||
|
||||
if (tag == GCOV_TAG_OBJECT_SUMMARY)
|
||||
gcov_read_summary (&object_summary);
|
||||
else if (tag == GCOV_TAG_PROGRAM_SUMMARY
|
||||
|| tag == GCOV_TAG_INCORRECT_SUMMARY)
|
||||
else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
|
||||
program_count++;
|
||||
else if (tag == GCOV_TAG_FUNCTION)
|
||||
{
|
||||
@ -1045,7 +1044,7 @@ read_count_file ()
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else if (tag == GCOV_TAG_ARC_COUNTS && fn)
|
||||
else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn)
|
||||
{
|
||||
if (length != 8 * fn->num_counts)
|
||||
goto mismatch;
|
||||
@ -1801,7 +1800,8 @@ output_lines (gcov_file, src)
|
||||
fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name);
|
||||
fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name);
|
||||
fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, da_file_name);
|
||||
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, object_summary.runs);
|
||||
fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0,
|
||||
object_summary.ctrs[GCOV_COUNTER_ARCS].runs);
|
||||
fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count);
|
||||
|
||||
source_file = fopen (src->name, "r");
|
||||
|
408
gcc/libgcov.c
408
gcc/libgcov.c
@ -96,93 +96,91 @@ gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
|
||||
static void
|
||||
gcov_exit (void)
|
||||
{
|
||||
struct gcov_info *ptr;
|
||||
unsigned ix, jx;
|
||||
gcov_type program_max_one = 0;
|
||||
gcov_type program_sum = 0;
|
||||
unsigned program_arcs = 0;
|
||||
struct gcov_summary last_prg;
|
||||
|
||||
last_prg.runs = 0;
|
||||
struct gcov_info *gi_ptr;
|
||||
struct gcov_summary this_program;
|
||||
struct gcov_summary all;
|
||||
|
||||
for (ptr = gcov_list; ptr; ptr = ptr->next)
|
||||
memset (&all, 0, sizeof (all));
|
||||
/* Find the totals for this execution. */
|
||||
memset (&this_program, 0, sizeof (this_program));
|
||||
for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
unsigned arc_data_index;
|
||||
gcov_type *count_ptr;
|
||||
const struct gcov_ctr_info *ci_ptr;
|
||||
struct gcov_ctr_summary *cs_ptr;
|
||||
unsigned t_ix;
|
||||
|
||||
for (t_ix = 0, ci_ptr = gi_ptr->counts, cs_ptr = this_program.ctrs;
|
||||
t_ix != GCOV_COUNTERS; t_ix++, cs_ptr++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
const gcov_type *c_ptr;
|
||||
unsigned c_num;
|
||||
|
||||
if (!ptr->filename)
|
||||
continue;
|
||||
|
||||
for (arc_data_index = 0;
|
||||
arc_data_index < ptr->n_counter_sections
|
||||
&& ptr->counter_sections[arc_data_index].tag != GCOV_TAG_ARC_COUNTS;
|
||||
arc_data_index++)
|
||||
continue;
|
||||
|
||||
for (ix = ptr->counter_sections[arc_data_index].n_counters,
|
||||
count_ptr = ptr->counter_sections[arc_data_index].counters; ix--;)
|
||||
{
|
||||
gcov_type count = *count_ptr++;
|
||||
|
||||
if (count > program_max_one)
|
||||
program_max_one = count;
|
||||
program_sum += count;
|
||||
}
|
||||
program_arcs += ptr->counter_sections[arc_data_index].n_counters;
|
||||
cs_ptr->num += ci_ptr->num;
|
||||
for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
|
||||
{
|
||||
cs_ptr->sum_all += *c_ptr;
|
||||
if (cs_ptr->run_max < *c_ptr)
|
||||
cs_ptr->run_max = *c_ptr;
|
||||
}
|
||||
ci_ptr++;
|
||||
}
|
||||
}
|
||||
for (ptr = gcov_list; ptr; ptr = ptr->next)
|
||||
|
||||
/* Now write the data */
|
||||
for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
struct gcov_summary object;
|
||||
struct gcov_summary local_prg;
|
||||
struct gcov_summary this_object;
|
||||
struct gcov_summary object, program;
|
||||
gcov_type *values[GCOV_COUNTERS];
|
||||
const struct gcov_fn_info *fi_ptr;
|
||||
unsigned fi_stride;
|
||||
unsigned c_ix, t_ix, f_ix;
|
||||
const struct gcov_ctr_info *ci_ptr;
|
||||
struct gcov_ctr_summary *cs_ptr;
|
||||
struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all;
|
||||
int error;
|
||||
int merging;
|
||||
unsigned long base;
|
||||
const struct gcov_function_info *fn_info;
|
||||
gcov_type **counters;
|
||||
gcov_type *count_ptr;
|
||||
gcov_type object_max_one = 0;
|
||||
unsigned tag, length;
|
||||
unsigned arc_data_index, f_sect_index, sect_index;
|
||||
long summary_pos = 0;
|
||||
unsigned long summary_pos = 0;
|
||||
|
||||
if (!ptr->filename)
|
||||
continue;
|
||||
/* Totals for this object file. */
|
||||
memset (&this_object, 0, sizeof (this_object));
|
||||
for (t_ix = c_ix = 0,
|
||||
ci_ptr = gi_ptr->counts, cs_ptr = this_object.ctrs;
|
||||
t_ix != GCOV_COUNTERS; t_ix++, cs_ptr++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
const gcov_type *c_ptr;
|
||||
unsigned c_num;
|
||||
|
||||
counters = malloc (sizeof (gcov_type *) * ptr->n_counter_sections);
|
||||
for (ix = 0; ix < ptr->n_counter_sections; ix++)
|
||||
counters[ix] = ptr->counter_sections[ix].counters;
|
||||
cs_ptr->num += ci_ptr->num;
|
||||
values[c_ix] = ci_ptr->values;
|
||||
for (c_num = ci_ptr->num, c_ptr = ci_ptr->values; c_num--; c_ptr++)
|
||||
{
|
||||
cs_ptr->sum_all += *c_ptr;
|
||||
if (cs_ptr->run_max < *c_ptr)
|
||||
cs_ptr->run_max = *c_ptr;
|
||||
}
|
||||
c_ix++;
|
||||
ci_ptr++;
|
||||
}
|
||||
|
||||
for (arc_data_index = 0;
|
||||
arc_data_index < ptr->n_counter_sections
|
||||
&& ptr->counter_sections[arc_data_index].tag != GCOV_TAG_ARC_COUNTS;
|
||||
arc_data_index++)
|
||||
continue;
|
||||
|
||||
if (arc_data_index == ptr->n_counter_sections)
|
||||
/* Calculate the function_info stride. This depends on the
|
||||
number of counter types being measured. */
|
||||
fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned);
|
||||
if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned))
|
||||
{
|
||||
/* For now; later we may want to just measure other profiles,
|
||||
but now I am lazy to check for all consequences. */
|
||||
abort ();
|
||||
}
|
||||
for (ix = ptr->counter_sections[arc_data_index].n_counters,
|
||||
count_ptr = ptr->counter_sections[arc_data_index].counters; ix--;)
|
||||
{
|
||||
gcov_type count = *count_ptr++;
|
||||
|
||||
if (count > object_max_one)
|
||||
object_max_one = count;
|
||||
fi_stride += __alignof__ (struct gcov_fn_info) - 1;
|
||||
fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
|
||||
}
|
||||
|
||||
memset (&local_prg, 0, sizeof (local_prg));
|
||||
memset (&object, 0, sizeof (object));
|
||||
|
||||
/* Open for modification */
|
||||
merging = gcov_open (ptr->filename, 0);
|
||||
|
||||
/* Open for modification, if possible */
|
||||
merging = gcov_open (gi_ptr->filename, 0);
|
||||
if (!merging)
|
||||
{
|
||||
fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
|
||||
ptr->filename = 0;
|
||||
fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -192,22 +190,22 @@ gcov_exit (void)
|
||||
if (gcov_read_unsigned () != GCOV_DATA_MAGIC)
|
||||
{
|
||||
fprintf (stderr, "profiling:%s:Not a gcov data file\n",
|
||||
ptr->filename);
|
||||
gi_ptr->filename);
|
||||
read_fatal:;
|
||||
gcov_close ();
|
||||
ptr->filename = 0;
|
||||
continue;
|
||||
}
|
||||
length = gcov_read_unsigned ();
|
||||
if (length != GCOV_VERSION)
|
||||
{
|
||||
gcov_version_mismatch (ptr, length);
|
||||
gcov_version_mismatch (gi_ptr, length);
|
||||
goto read_fatal;
|
||||
}
|
||||
|
||||
/* Merge execution counts for each function. */
|
||||
for (ix = ptr->n_functions, fn_info = ptr->functions;
|
||||
ix--; fn_info++)
|
||||
for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
|
||||
fi_ptr = (const struct gcov_fn_info *)
|
||||
((const char *) fi_ptr + fi_stride))
|
||||
{
|
||||
tag = gcov_read_unsigned ();
|
||||
length = gcov_read_unsigned ();
|
||||
@ -216,42 +214,34 @@ gcov_exit (void)
|
||||
if (tag != GCOV_TAG_FUNCTION)
|
||||
{
|
||||
read_mismatch:;
|
||||
fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
|
||||
ptr->filename, fn_info->name);
|
||||
fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
|
||||
gi_ptr->filename,
|
||||
fi_ptr ? fi_ptr->name : "summaries");
|
||||
goto read_fatal;
|
||||
}
|
||||
|
||||
if (strcmp (gcov_read_string (), fn_info->name)
|
||||
|| gcov_read_unsigned () != fn_info->checksum)
|
||||
if (strcmp (gcov_read_string (), fi_ptr->name)
|
||||
|| gcov_read_unsigned () != fi_ptr->checksum)
|
||||
goto read_mismatch;
|
||||
|
||||
/* Counters. */
|
||||
for (f_sect_index = 0;
|
||||
f_sect_index < fn_info->n_counter_sections;
|
||||
f_sect_index++)
|
||||
{
|
||||
unsigned n_counters;
|
||||
for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
unsigned n_counts;
|
||||
gcov_type *c_ptr;
|
||||
|
||||
tag = gcov_read_unsigned ();
|
||||
length = gcov_read_unsigned ();
|
||||
|
||||
tag = gcov_read_unsigned ();
|
||||
length = gcov_read_unsigned ();
|
||||
|
||||
for (sect_index = 0;
|
||||
sect_index < ptr->n_counter_sections;
|
||||
sect_index++)
|
||||
if (ptr->counter_sections[sect_index].tag == tag)
|
||||
break;
|
||||
if (sect_index == ptr->n_counter_sections
|
||||
|| fn_info->counter_sections[f_sect_index].tag != tag)
|
||||
goto read_mismatch;
|
||||
|
||||
n_counters = fn_info->counter_sections[f_sect_index].n_counters;
|
||||
if (n_counters != length / 8)
|
||||
goto read_mismatch;
|
||||
|
||||
for (jx = 0; jx < n_counters; jx++)
|
||||
counters[sect_index][jx] += gcov_read_counter ();
|
||||
|
||||
counters[sect_index] += n_counters;
|
||||
if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
|
||||
|| fi_ptr->n_ctrs[c_ix] * 8 != length)
|
||||
goto read_mismatch;
|
||||
c_ptr = values[c_ix];
|
||||
for (n_counts = fi_ptr->n_ctrs[c_ix];
|
||||
n_counts--; c_ptr++)
|
||||
*c_ptr += gcov_read_counter ();
|
||||
values[c_ix] = c_ptr;
|
||||
c_ix++;
|
||||
}
|
||||
if ((error = gcov_is_error ()))
|
||||
goto read_error;
|
||||
@ -266,148 +256,134 @@ gcov_exit (void)
|
||||
/* Check program summary */
|
||||
while (!gcov_is_eof ())
|
||||
{
|
||||
unsigned long base = gcov_position ();
|
||||
|
||||
base = gcov_position ();
|
||||
tag = gcov_read_unsigned ();
|
||||
gcov_read_unsigned ();
|
||||
if (tag != GCOV_TAG_PROGRAM_SUMMARY)
|
||||
goto read_mismatch;
|
||||
gcov_read_summary (&local_prg);
|
||||
gcov_read_summary (&program);
|
||||
if ((error = gcov_is_error ()))
|
||||
{
|
||||
read_error:;
|
||||
fprintf (stderr, error < 0 ?
|
||||
"profiling:%s:Overflow merging\n" :
|
||||
"profiling:%s:Error merging\n",
|
||||
ptr->filename);
|
||||
gi_ptr->filename);
|
||||
goto read_fatal;
|
||||
}
|
||||
|
||||
if (local_prg.checksum != gcov_crc32)
|
||||
{
|
||||
memset (&local_prg, 0, sizeof (local_prg));
|
||||
continue;
|
||||
}
|
||||
merging = 0;
|
||||
if (tag != GCOV_TAG_PROGRAM_SUMMARY)
|
||||
break;
|
||||
|
||||
/* If everything done correctly, the summaries should be
|
||||
computed equal for each module. */
|
||||
if (last_prg.runs
|
||||
#ifdef TARGET_HAS_F_SETLKW
|
||||
&& last_prg.runs == local_prg.runs
|
||||
#endif
|
||||
&& memcmp (&last_prg, &local_prg, sizeof (last_prg)))
|
||||
{
|
||||
#ifdef TARGET_HAS_F_SETLKW
|
||||
fprintf (stderr, "profiling:%s:Invocation mismatch\n\
|
||||
Probably some files were removed\n",
|
||||
ptr->filename);
|
||||
#else
|
||||
fprintf (stderr, "profiling:%s:Invocation mismatch\n\
|
||||
Probably some files were removed or parallel race happent because libgcc\n\
|
||||
is compiled without file locking support.\n",
|
||||
ptr->filename);
|
||||
#endif
|
||||
local_prg.runs = 0;
|
||||
}
|
||||
else
|
||||
memcpy (&last_prg, &local_prg, sizeof (last_prg));
|
||||
if (program.checksum != gcov_crc32)
|
||||
continue;
|
||||
summary_pos = base;
|
||||
break;
|
||||
}
|
||||
gcov_seek (0, 0);
|
||||
}
|
||||
else
|
||||
memset (&object, 0, sizeof (object));
|
||||
if (!summary_pos)
|
||||
memset (&program, 0, sizeof (program));
|
||||
|
||||
object.runs++;
|
||||
object.arcs = ptr->counter_sections[arc_data_index].n_counters;
|
||||
object.arc_sum = 0;
|
||||
if (object.arc_max_one < object_max_one)
|
||||
object.arc_max_one = object_max_one;
|
||||
object.arc_sum_max += object_max_one;
|
||||
fi_ptr = 0;
|
||||
|
||||
/* Merge the summaries. */
|
||||
for (t_ix = c_ix = 0,
|
||||
cs_obj = object.ctrs, cs_tobj = this_object.ctrs,
|
||||
cs_prg = program.ctrs, cs_tprg = this_program.ctrs,
|
||||
cs_all = all.ctrs;
|
||||
t_ix != GCOV_COUNTERS;
|
||||
t_ix++, cs_obj++, cs_tobj++, cs_prg++, cs_tprg++, cs_all++)
|
||||
{
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
if (!cs_obj->runs++)
|
||||
cs_obj->num = cs_tobj->num;
|
||||
else if (cs_obj->num != cs_tobj->num)
|
||||
goto read_mismatch;
|
||||
cs_obj->sum_all += cs_tobj->sum_all;
|
||||
if (cs_obj->run_max < cs_tobj->run_max)
|
||||
cs_obj->run_max = cs_tobj->run_max;
|
||||
cs_obj->sum_max += cs_tobj->run_max;
|
||||
|
||||
if (!cs_prg->runs++)
|
||||
cs_prg->num = cs_tprg->num;
|
||||
else if (cs_prg->num != cs_tprg->num)
|
||||
goto read_mismatch;
|
||||
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;
|
||||
|
||||
values[c_ix] = gi_ptr->counts[c_ix].values;
|
||||
c_ix++;
|
||||
}
|
||||
else if (cs_obj->num || cs_prg->num)
|
||||
goto read_mismatch;
|
||||
|
||||
if (!cs_all->runs && cs_prg->runs)
|
||||
memcpy (cs_all, cs_prg, sizeof (*cs_all));
|
||||
else if (!all.checksum
|
||||
&& (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
|
||||
&& memcmp (cs_all, cs_prg, sizeof (*cs_all)))
|
||||
{
|
||||
fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
|
||||
gi_ptr->filename, GCOV_LOCKED
|
||||
? "" : " or concurrent update without locking support");
|
||||
all.checksum = ~0u;
|
||||
}
|
||||
}
|
||||
|
||||
program.checksum = gcov_crc32;
|
||||
|
||||
/* Write out the data. */
|
||||
gcov_write_unsigned (GCOV_DATA_MAGIC);
|
||||
gcov_write_unsigned (GCOV_VERSION);
|
||||
|
||||
/* Write execution counts for each function. */
|
||||
for (ix = 0; ix < ptr->n_counter_sections; ix++)
|
||||
counters[ix] = ptr->counter_sections[ix].counters;
|
||||
for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
|
||||
for (f_ix = gi_ptr->n_functions, fi_ptr = gi_ptr->functions; f_ix--;
|
||||
fi_ptr = (const struct gcov_fn_info *)
|
||||
((const char *) fi_ptr + fi_stride))
|
||||
{
|
||||
/* Announce function. */
|
||||
base = gcov_write_tag (GCOV_TAG_FUNCTION);
|
||||
gcov_write_string (fn_info->name);
|
||||
gcov_write_unsigned (fn_info->checksum);
|
||||
gcov_write_string (fi_ptr->name);
|
||||
gcov_write_unsigned (fi_ptr->checksum);
|
||||
gcov_write_length (base);
|
||||
|
||||
/* counters. */
|
||||
for (f_sect_index = 0;
|
||||
f_sect_index < fn_info->n_counter_sections;
|
||||
f_sect_index++)
|
||||
{
|
||||
tag = fn_info->counter_sections[f_sect_index].tag;
|
||||
for (sect_index = 0;
|
||||
sect_index < ptr->n_counter_sections;
|
||||
sect_index++)
|
||||
if (ptr->counter_sections[sect_index].tag == tag)
|
||||
break;
|
||||
if (sect_index == ptr->n_counter_sections)
|
||||
abort ();
|
||||
|
||||
base = gcov_write_tag (tag);
|
||||
for (jx = fn_info->counter_sections[f_sect_index].n_counters; jx--;)
|
||||
{
|
||||
gcov_type count = *counters[sect_index]++;
|
||||
|
||||
if (tag == GCOV_TAG_ARC_COUNTS)
|
||||
{
|
||||
object.arc_sum += count;
|
||||
}
|
||||
gcov_write_counter (count);
|
||||
}
|
||||
gcov_write_length (base);
|
||||
}
|
||||
for (c_ix = t_ix = 0; t_ix != GCOV_COUNTERS; t_ix++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
unsigned n_counts;
|
||||
gcov_type *c_ptr;
|
||||
|
||||
base = gcov_write_tag (GCOV_TAG_FOR_COUNTER (t_ix));
|
||||
c_ptr = values[c_ix];
|
||||
for (n_counts = fi_ptr->n_ctrs[c_ix]; n_counts--; c_ptr++)
|
||||
gcov_write_counter (*c_ptr);
|
||||
values[c_ix] = c_ptr;
|
||||
gcov_write_length (base);
|
||||
c_ix++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Object file summary. */
|
||||
gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object);
|
||||
|
||||
/* Generate whole program statistics. */
|
||||
local_prg.runs++;
|
||||
local_prg.checksum = gcov_crc32;
|
||||
local_prg.arcs = program_arcs;
|
||||
local_prg.arc_sum += program_sum;
|
||||
if (local_prg.arc_max_one < program_max_one)
|
||||
local_prg.arc_max_one = program_max_one;
|
||||
local_prg.arc_sum_max += program_max_one;
|
||||
|
||||
if (merging)
|
||||
if (summary_pos)
|
||||
gcov_seek (summary_pos, 0);
|
||||
else
|
||||
gcov_seek_end ();
|
||||
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program);
|
||||
if ((error = gcov_close ()))
|
||||
{
|
||||
gcov_seek_end ();
|
||||
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &local_prg);
|
||||
}
|
||||
else if (summary_pos)
|
||||
{
|
||||
/* Zap trailing program summary */
|
||||
gcov_seek (summary_pos, 0);
|
||||
if (!local_prg.runs)
|
||||
ptr->wkspc = 0;
|
||||
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &local_prg);
|
||||
}
|
||||
if (gcov_close ())
|
||||
{
|
||||
fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
|
||||
ptr->filename = 0;
|
||||
fprintf (stderr, error < 0 ?
|
||||
"profiling:%s:Overflow writing\n" :
|
||||
"profiling:%s:Error writing\n",
|
||||
gi_ptr->filename);
|
||||
gi_ptr->filename = 0;
|
||||
}
|
||||
}
|
||||
/* All statistic we gather can be done in one pass trought the file.
|
||||
Originally we did two - one for counts and other for the statistics. This
|
||||
brings problem with the file locking interface, but it is possible to
|
||||
implement so if need appears in the future - first pass updates local
|
||||
statistics and number of runs. Second pass then overwrite global
|
||||
statistics only when number of runs match. */
|
||||
}
|
||||
|
||||
/* Add a new object file onto the bb chain. Invoked automatically
|
||||
@ -459,16 +435,20 @@ __gcov_init (struct gcov_info *info)
|
||||
void
|
||||
__gcov_flush (void)
|
||||
{
|
||||
struct gcov_info *ptr;
|
||||
const struct gcov_info *gi_ptr;
|
||||
|
||||
gcov_exit ();
|
||||
for (ptr = gcov_list; ptr; ptr = ptr->next)
|
||||
for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
unsigned i, j;
|
||||
unsigned t_ix;
|
||||
const struct gcov_ctr_info *ci_ptr;
|
||||
|
||||
for (j = 0; j < ptr->n_counter_sections; j++)
|
||||
for (i = ptr->counter_sections[j].n_counters; i--;)
|
||||
ptr->counter_sections[j].counters[i] = 0;
|
||||
for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++)
|
||||
if ((1 << t_ix) & gi_ptr->ctr_mask)
|
||||
{
|
||||
memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num);
|
||||
ci_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ make_compile='$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
|
||||
libgcc2_c_dep='stmp-dirs $(srcdir)/libgcc2.c $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'" $LIB2ADDEHDEP"
|
||||
|
||||
# Dependencies for libgcov.c
|
||||
libgcov_c_dep='stmp-dirs $(srcdir)/libgcov.c $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h'
|
||||
libgcov_c_dep='stmp-dirs $(srcdir)/libgcov.c $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs tsystem.h gcov-io.h gcov-io.c gcov-iov.h'
|
||||
|
||||
# Dependencies for fp-bit.c
|
||||
fpbit_c_dep='stmp-dirs config.status tsystem.h'
|
||||
|
@ -120,11 +120,9 @@ bool
|
||||
maybe_hot_bb_p (bb)
|
||||
basic_block bb;
|
||||
{
|
||||
if (profile_info.count_profiles_merged
|
||||
&& flag_branch_probabilities
|
||||
if (profile_info && flag_branch_probabilities
|
||||
&& (bb->count
|
||||
< profile_info.max_counter_in_program
|
||||
/ PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
return false;
|
||||
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||
return false;
|
||||
@ -137,11 +135,9 @@ bool
|
||||
probably_cold_bb_p (bb)
|
||||
basic_block bb;
|
||||
{
|
||||
if (profile_info.count_profiles_merged
|
||||
&& flag_branch_probabilities
|
||||
if (profile_info && flag_branch_probabilities
|
||||
&& (bb->count
|
||||
< profile_info.max_counter_in_program
|
||||
/ PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
return true;
|
||||
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||
return true;
|
||||
@ -153,10 +149,8 @@ bool
|
||||
probably_never_executed_bb_p (bb)
|
||||
basic_block bb;
|
||||
{
|
||||
if (profile_info.count_profiles_merged
|
||||
&& flag_branch_probabilities)
|
||||
return ((bb->count + profile_info.count_profiles_merged / 2)
|
||||
/ profile_info.count_profiles_merged) == 0;
|
||||
if (profile_info && flag_branch_probabilities)
|
||||
return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1266,8 +1260,7 @@ compute_function_frequency ()
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
if (!profile_info.count_profiles_merged
|
||||
|| !flag_branch_probabilities)
|
||||
if (!profile_info || !flag_branch_probabilities)
|
||||
return;
|
||||
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
|
||||
FOR_EACH_BB (bb)
|
||||
|
@ -81,26 +81,6 @@ struct bb_info {
|
||||
gcov_type pred_count;
|
||||
};
|
||||
|
||||
/* Counts information for a function. */
|
||||
typedef struct counts_entry
|
||||
{
|
||||
/* We hash by */
|
||||
char *function_name;
|
||||
unsigned section;
|
||||
|
||||
/* Store */
|
||||
unsigned checksum;
|
||||
unsigned n_counts;
|
||||
gcov_type *counts;
|
||||
unsigned merged;
|
||||
gcov_type max_counter;
|
||||
gcov_type max_counter_sum;
|
||||
|
||||
/* Workspace */
|
||||
struct counts_entry *chain;
|
||||
|
||||
} counts_entry_t;
|
||||
|
||||
#define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
|
||||
#define BB_INFO(b) ((struct bb_info *) (b)->aux)
|
||||
|
||||
@ -110,6 +90,10 @@ typedef struct counts_entry
|
||||
: ((bb) == EXIT_BLOCK_PTR \
|
||||
? last_basic_block + 1 : (bb)->index + 1))
|
||||
|
||||
/* Counter summary from the last set of coverage counts read. */
|
||||
|
||||
const struct gcov_ctr_summary *profile_info;
|
||||
|
||||
/* Collect statistics on the performance of this pass for the entire source
|
||||
file. */
|
||||
|
||||
@ -195,16 +179,13 @@ get_exec_counts ()
|
||||
num_edges++;
|
||||
}
|
||||
|
||||
counts = get_coverage_counts (GCOV_TAG_ARC_COUNTS, num_edges);
|
||||
counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, &profile_info);
|
||||
if (!counts)
|
||||
return NULL;
|
||||
|
||||
if (rtl_dump_file)
|
||||
{
|
||||
fprintf(rtl_dump_file, "Merged %i profiles with maximal count %i.\n",
|
||||
profile_info.count_profiles_merged,
|
||||
(int)profile_info.max_counter_in_program);
|
||||
}
|
||||
if (rtl_dump_file && profile_info)
|
||||
fprintf(rtl_dump_file, "Merged %u profiles with maximal count %u.\n",
|
||||
profile_info->runs, (unsigned) profile_info->sum_max);
|
||||
|
||||
return counts;
|
||||
}
|
||||
@ -547,7 +528,6 @@ compute_branch_probabilities ()
|
||||
}
|
||||
|
||||
free_aux_for_blocks ();
|
||||
find_counters_section (GCOV_TAG_ARC_COUNTS)->present = 1;
|
||||
}
|
||||
|
||||
/* Instrument and/or analyze program behavior based on program flow graph.
|
||||
@ -1013,7 +993,7 @@ static rtx
|
||||
gen_edge_profiler (edgeno)
|
||||
int edgeno;
|
||||
{
|
||||
rtx ref = coverage_counter_ref (GCOV_TAG_ARC_COUNTS, edgeno);
|
||||
rtx ref = coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
|
||||
rtx tmp;
|
||||
enum machine_mode mode = GET_MODE (ref);
|
||||
rtx sequence;
|
||||
|
@ -211,7 +211,7 @@ tail_duplicate ()
|
||||
int max_dup_insns;
|
||||
basic_block bb;
|
||||
|
||||
if (profile_info.count_profiles_merged && flag_branch_probabilities)
|
||||
if (profile_info && flag_branch_probabilities)
|
||||
probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
|
||||
else
|
||||
probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
|
||||
@ -232,7 +232,7 @@ tail_duplicate ()
|
||||
weighted_insns += n * bb->frequency;
|
||||
}
|
||||
|
||||
if (profile_info.count_profiles_merged && flag_branch_probabilities)
|
||||
if (profile_info && flag_branch_probabilities)
|
||||
cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
|
||||
else
|
||||
cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
|
||||
|
Loading…
Reference in New Issue
Block a user