aboutsummaryrefslogtreecommitdiff
path: root/gcc/gcov.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2002-05-09 14:54:19 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2002-05-09 12:54:19 +0000
commitb7c9bf289f096dd5338f37a4656f13d7b982fd33 (patch)
treeda04474c0297ae3c91b3bdce0c519ca2f9d2e5a8 /gcc/gcov.c
parent786de7eb9aaaf39f96248b6d42316b2aa4e9bf63 (diff)
downloadgcc-b7c9bf289f096dd5338f37a4656f13d7b982fd33.zip
gcc-b7c9bf289f096dd5338f37a4656f13d7b982fd33.tar.gz
gcc-b7c9bf289f096dd5338f37a4656f13d7b982fd33.tar.bz2
final.c (end_final): Use C trees to output data structures for profiling.
* final.c (end_final): Use C trees to output data structures for profiling. * Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h (profile.o): New dependency profile.h (final.o): New dependency profile.h * profile.h: New file. New global structure profile_info. * final.h (count_edges_instrumented_now): Declare. (current_function_cfg_checksum): Declare. (function_list): New structure. (functions_head, functions_tail): New static variables. (end_final): Emits more data, removed some -ax stuff. (final): Stores function names and chcksums. * gcov-io.h (__write_gcov_string): New function. (__read_gcov_string): New function. * gcov.c (read_profile): New function. (create_program_flow_graph): Uses read_profile instead of reading da_file. (read_files): Removed da_file checking, it's done by read_profile now. * libgcc2.c (bb_function_info): New structure. (bb): New field in structure, removed some -ax stuff. (__bb_exit_func): Changed structure of da_file. * profile.c (count_edges_instrumented_now): New global variable. (current_function_cfg_checksum): New global variable. (max_counter_in_program): New global variable. (get_exec_counts): New function. (compute_checksum): New function. (instrument_edges): Sets count_edges_instrumented_now. (compute_branch_probabilities): Uses get_exec_counts instead of reading da_file. (branch_prob): Calls compute_checksum and writes extra data to bbg_file. (init_branch_prob): Removed da_file checking, done in get_exec_counts now. (end_branch_prob): Removed da_file checking, done in get_exec_counts now. * gcov.texi: Updated information about gcov file format. Co-Authored-By: Pavel Nejedly <bim@atrey.karlin.mff.cuni.cz> From-SVN: r53326
Diffstat (limited to 'gcc/gcov.c')
-rw-r--r--gcc/gcov.c182
1 files changed, 159 insertions, 23 deletions
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 3bb2ce1..fbc3d00 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -232,6 +232,7 @@ static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
+static gcov_type *read_profile PARAMS ((char *, long, int));
static void create_program_flow_graph PARAMS ((struct bb_info_list *));
static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
@@ -538,6 +539,130 @@ reverse_arcs (arcptr)
return prev;
}
+/* Reads profiles from the .da file and compute a hybrid profile. */
+
+static gcov_type *
+read_profile (function_name, cfg_checksum, instr_arcs)
+ char *function_name;
+ long cfg_checksum;
+ int instr_arcs;
+{
+ int i;
+ int okay = 1;
+ gcov_type *profile;
+ char *function_name_buffer;
+ int function_name_buffer_len;
+
+ profile = xmalloc (sizeof (gcov_type) * instr_arcs);
+ rewind (da_file);
+ function_name_buffer_len = strlen (function_name) + 1;
+ function_name_buffer = xmalloc (function_name_buffer_len + 1);
+
+ for (i = 0; i < instr_arcs; i++)
+ profile[i] = 0;
+
+ if (!da_file)
+ return profile;
+
+ while (1)
+ {
+ long magic, extra_bytes;
+ long func_count;
+ int i;
+
+ if (__read_long (&magic, da_file, 4) != 0)
+ break;
+
+ if (magic != -123)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&func_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&extra_bytes, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ /* skip extra data emited by __bb_exit_func. */
+ fseek (da_file, extra_bytes, SEEK_CUR);
+
+ for (i = 0; i < func_count; i++)
+ {
+ long arc_count;
+ long chksum;
+ int j;
+
+ if (__read_gcov_string
+ (function_name_buffer, function_name_buffer_len, da_file,
+ -1) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&chksum, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&arc_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (strcmp (function_name_buffer, function_name) != 0
+ || arc_count != instr_arcs || chksum != cfg_checksum)
+ {
+ /* skip */
+ if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
+ {
+ okay = 0;
+ break;
+ }
+ }
+ else
+ {
+ gcov_type tmp;
+
+ for (j = 0; j < arc_count; j++)
+ if (__read_gcov_type (&tmp, da_file, 8) != 0)
+ {
+ okay = 0;
+ break;
+ }
+ else
+ {
+ profile[j] += tmp;
+ }
+ }
+ }
+
+ if (!okay)
+ break;
+
+ }
+
+ free (function_name_buffer);
+
+ if (!okay)
+ {
+ fprintf (stderr, ".da file corrupted!\n");
+ free (profile);
+ abort ();
+ }
+
+ return profile;
+}
/* Construct the program flow graph from the .bbg file, and read in the data
in the .da file. */
@@ -550,6 +675,29 @@ create_program_flow_graph (bptr)
int i;
struct adj_list *arcptr;
struct bb_info *bb_graph;
+ long cfg_checksum;
+ long instr_arcs = 0;
+ gcov_type *profile;
+ int profile_pos = 0;
+ char *function_name;
+ long function_name_len, tmp;
+
+ /* Read function name. */
+ __read_long (&tmp, bbg_file, 4); /* ignore -1. */
+ __read_long (&function_name_len, bbg_file, 4);
+ function_name = xmalloc (function_name_len + 1);
+ fread (function_name, 1, function_name_len + 1, bbg_file);
+
+ /* Skip padding. */
+ tmp = (function_name_len + 1) % 4;
+
+ if (tmp)
+ fseek (bbg_file, 4 - tmp, SEEK_CUR);
+
+ __read_long (&tmp, bbg_file, 4); /* ignore -1. */
+
+ /* Read the cfg checksum. */
+ __read_long (&cfg_checksum, bbg_file, 4);
/* Read the number of blocks. */
__read_long (&num_blocks, bbg_file, 4);
@@ -579,7 +727,10 @@ create_program_flow_graph (bptr)
init_arc (arcptr, src, dest, bb_graph);
__read_long (&flag_bits, bbg_file, 4);
- arcptr->on_tree = flag_bits & 0x1;
+ if (flag_bits & 0x1)
+ arcptr->on_tree++;
+ else
+ instr_arcs++;
arcptr->fake = !! (flag_bits & 0x2);
arcptr->fall_through = !! (flag_bits & 0x4);
}
@@ -601,6 +752,10 @@ create_program_flow_graph (bptr)
if (bb_graph[i].succ)
bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
+ /* Read profile from the .da file. */
+
+ profile = read_profile (function_name, cfg_checksum, instr_arcs);
+
/* For each arc not on the spanning tree, set its execution count from
the .da file. */
@@ -613,15 +768,13 @@ create_program_flow_graph (bptr)
for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
if (! arcptr->on_tree)
{
- gcov_type tmp_count = 0;
- if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
- abort ();
-
- arcptr->arc_count = tmp_count;
+ arcptr->arc_count = profile[profile_pos++];
arcptr->count_valid = 1;
bb_graph[i].succ_count--;
bb_graph[arcptr->target].pred_count--;
}
+ free (profile);
+ free (function_name);
}
static void
@@ -755,12 +908,6 @@ read_files ()
struct stat buf;
struct bb_info_list *list_end = 0;
struct bb_info_list *b_ptr;
- long total;
-
- /* Read and ignore the first word of the .da file, which is the count of
- how many numbers follow. */
- if (da_file && __read_long (&total, da_file, 8))
- abort ();
while (! feof (bbg_file))
{
@@ -781,17 +928,6 @@ read_files ()
ungetc (getc (bbg_file), bbg_file);
}
- /* Check to make sure the .da file data is valid. */
-
- if (da_file)
- {
- if (feof (da_file))
- fnotice (stderr, ".da file contents exhausted too early\n");
- /* Should be at end of file now. */
- if (__read_long (&total, da_file, 8) == 0)
- fnotice (stderr, ".da file contents not exhausted\n");
- }
-
/* Calculate all of the basic block execution counts and branch
taken probabilities. */