diff options
author | Jan Hubicka <jh@suse.cz> | 2002-05-09 14:54:19 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2002-05-09 12:54:19 +0000 |
commit | b7c9bf289f096dd5338f37a4656f13d7b982fd33 (patch) | |
tree | da04474c0297ae3c91b3bdce0c519ca2f9d2e5a8 /gcc/gcov.c | |
parent | 786de7eb9aaaf39f96248b6d42316b2aa4e9bf63 (diff) | |
download | gcc-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.c | 182 |
1 files changed, 159 insertions, 23 deletions
@@ -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. */ |