Commit b2aec5c0 by Jan Hubicka Committed by Jan Hubicka

regs.h (struct reg_info_def): Add freq field.

	* regs.h (struct reg_info_def): Add freq field.
	(REG_N_REFS): Update comment.
	(REG_FREQ): New.
	* regclass.c (scan_one_insn): Update REG_FREQ.
	* flow.c (mark_set_1): Update REG_FREQ, make REG_N_SETS unweighted.
	(attempt_auto_inc): Likewise.
	(mark_used_reg): Likewise.
	(try_pre_increment_1): Likewise.
	* local-alloc.c (struct qty): Add freq field.
	(alloc_qty): Set freq.
	(update_equiv_regs): Set REG_FREQ.
	(QTY_CMP_PRI): Use freq.
	(combine_regs): Update qty->freq.
	* global.c (struct allocno): Update comment for n_refs;
	add freq field.
	(local_reg_freq): New array.
	(global_alloc): Update freq field;
	allocate and initialize local_reg_freq.
	(allocno_compare): Use freq field.
	(find_reg): Likewise.
	* reload1.c (count_pseudo): Use freq isntead of n_refs.
	(count_spilled_pseudo): Likewise.

	* tm.texi (GCOV_TYPE_SIZE): Document.
	* basic-block.h (gcov_type): Define.
	(struct edge_def): Use gcov_type for count field.
	(struct basic_block_def): Likewise.
	* defaults.h (GCOV_TYPE_SIZE): Define.
	* final.c (end_final): Use GCOV_TYPE_SIZE.
	* flow.c (dump_edge_info, dump_flow_info, dump_bb): Print count fields
	using HOST_WIDEST_INT_PRINT_DEC.
	* gcov-io.h (__fetch_gcov_type, __store_gcov_type, __read_gcov_type,
	__write_gcov_type): New.
	(store_long): Remove.
	* gcov.c (gcov_type): Set default.
	(struct adj_list): Use gcov_type for arc_count.
	(bb_info): Use gcov_type for succ_count, pred_count and exec_count.
	(create_program_flow_graph): Read arc_count properly.
	(solve_program_flow_graph): 'total' is gcov_type.
	(output_data): Line_counts is gcov_type, print it properly.
	* libgcc2.c (struct bb): Counts is gcov_type.
	(__bb_exit_func): Use __read_gcov_type and __write_gcov_type.
	* profile.c (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set default.
	(GCOV_TYPE_SIZE): Define.
	(struct bb_info): succ_count and pred_count is gcov_type.
	(compute_branch_probabilities): Use __read_gcov_type,
	print read edges to the dump file.
	(total): Is gcov_type.
	(gen_edge_profiler): Use GCOV_TYPE_SIZE.

From-SVN: r43505
parent 5154e79a
Fri Jun 22 19:11:28 CEST 2001 Jan Hubicka <jh@suse.cz>
* regs.h (struct reg_info_def): Add freq field.
(REG_N_REFS): Update comment.
(REG_FREQ): New.
* regclass.c (scan_one_insn): Update REG_FREQ.
* flow.c (mark_set_1): Update REG_FREQ, make REG_N_SETS unweighted.
(attempt_auto_inc): Likewise.
(mark_used_reg): Likewise.
(try_pre_increment_1): Likewise.
* local-alloc.c (struct qty): Add freq field.
(alloc_qty): Set freq.
(update_equiv_regs): Set REG_FREQ.
(QTY_CMP_PRI): Use freq.
(combine_regs): Update qty->freq.
* global.c (struct allocno): Update comment for n_refs;
add freq field.
(local_reg_freq): New array.
(global_alloc): Update freq field;
allocate and initialize local_reg_freq.
(allocno_compare): Use freq field.
(find_reg): Likewise.
* reload1.c (count_pseudo): Use freq isntead of n_refs.
(count_spilled_pseudo): Likewise.
* tm.texi (GCOV_TYPE_SIZE): Document.
* basic-block.h (gcov_type): Define.
(struct edge_def): Use gcov_type for count field.
(struct basic_block_def): Likewise.
* defaults.h (GCOV_TYPE_SIZE): Define.
* final.c (end_final): Use GCOV_TYPE_SIZE.
* flow.c (dump_edge_info, dump_flow_info, dump_bb): Print count fields
using HOST_WIDEST_INT_PRINT_DEC.
* gcov-io.h (__fetch_gcov_type, __store_gcov_type, __read_gcov_type,
__write_gcov_type): New.
(store_long): Remove.
* gcov.c (gcov_type): Set default.
(struct adj_list): Use gcov_type for arc_count.
(bb_info): Use gcov_type for succ_count, pred_count and exec_count.
(create_program_flow_graph): Read arc_count properly.
(solve_program_flow_graph): 'total' is gcov_type.
(output_data): Line_counts is gcov_type, print it properly.
* libgcc2.c (struct bb): Counts is gcov_type.
(__bb_exit_func): Use __read_gcov_type and __write_gcov_type.
* profile.c (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set default.
(GCOV_TYPE_SIZE): Define.
(struct bb_info): succ_count and pred_count is gcov_type.
(compute_branch_probabilities): Use __read_gcov_type,
print read edges to the dump file.
(total): Is gcov_type.
(gen_edge_profiler): Use GCOV_TYPE_SIZE.
2001-06-14 Andrew Haley <aph@cambridge.redhat.com> 2001-06-14 Andrew Haley <aph@cambridge.redhat.com>
* optabs.c (emit_libcall_block): When using non-call exceptions, * optabs.c (emit_libcall_block): When using non-call exceptions,
......
...@@ -111,6 +111,9 @@ do { \ ...@@ -111,6 +111,9 @@ do { \
be done, other than zero the statistics on the first allocation. */ be done, other than zero the statistics on the first allocation. */
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P) #define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
/* Type we use to hold basic block counters. Should be at least 64bit. */
typedef HOST_WIDEST_INT gcov_type;
/* Control flow edge information. */ /* Control flow edge information. */
typedef struct edge_def { typedef struct edge_def {
/* Links through the predecessor and successor lists. */ /* Links through the predecessor and successor lists. */
...@@ -127,7 +130,7 @@ typedef struct edge_def { ...@@ -127,7 +130,7 @@ typedef struct edge_def {
int flags; /* see EDGE_* below */ int flags; /* see EDGE_* below */
int probability; /* biased by REG_BR_PROB_BASE */ int probability; /* biased by REG_BR_PROB_BASE */
int count; /* Expected number of executions calculated gcov_type count; /* Expected number of executions calculated
in profile.c */ in profile.c */
} *edge; } *edge;
...@@ -201,7 +204,7 @@ typedef struct basic_block_def { ...@@ -201,7 +204,7 @@ typedef struct basic_block_def {
int loop_depth; int loop_depth;
/* Expected number of executions: calculated in profile.c. */ /* Expected number of executions: calculated in profile.c. */
int count; gcov_type count;
/* Expected frequency. Normalized to be in range 0 to BB_FREQ_MAX. */ /* Expected frequency. Normalized to be in range 0 to BB_FREQ_MAX. */
int frequency; int frequency;
......
...@@ -297,6 +297,15 @@ do { \ ...@@ -297,6 +297,15 @@ do { \
#define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM #define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
#endif #endif
/* Type used by GCOV counters. Use 64bit data type if target supports
it. */
#if LONG_TYPE_SIZE >= 64
#define GCOV_TYPE_SIZE LONG_TYPE_SIZE
#else
#define GCOV_TYPE_SIZE LONG_LONG_TYPE_SIZE
#endif
/* By default, the preprocessor should be invoked the same way in C++ /* By default, the preprocessor should be invoked the same way in C++
as in C. */ as in C. */
#ifndef CPLUSPLUS_CPP_SPEC #ifndef CPLUSPLUS_CPP_SPEC
......
...@@ -1426,6 +1426,14 @@ characters. If this is undefined, the default is ...@@ -1426,6 +1426,14 @@ characters. If this is undefined, the default is
largest value that @code{WCHAR_TYPE_SIZE} can have at run-time. This is largest value that @code{WCHAR_TYPE_SIZE} can have at run-time. This is
used in @code{cpp}. used in @code{cpp}.
@findex GCOV_TYPE_SIZE
@item GCOV_TYPE_SIZE
A C expression for the size in bits of the type used for gcov counters on the
target machine. If you don't define this, the default is one
@code{LONG_TYPE_SIZE} in case it is greater or equal to 64-bit and
@code{LONG_LONG_TYPE_SIZE} otherwise. You may want to re-define the type to
ensure atomicity for counters in multithreaded programs.
@findex WINT_TYPE @findex WINT_TYPE
@item WINT_TYPE @item WINT_TYPE
A C expression for a string describing the name of the data type to A C expression for a string describing the name of the data type to
......
...@@ -298,12 +298,13 @@ end_final (filename) ...@@ -298,12 +298,13 @@ end_final (filename)
struct bb_list *ptr; struct bb_list *ptr;
struct bb_str *sptr; struct bb_str *sptr;
int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT; int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT; int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
if (profile_block_flag) if (profile_block_flag)
size = long_bytes * count_basic_blocks; size = long_bytes * count_basic_blocks;
else else
size = long_bytes * count_instrumented_edges; size = gcov_type_bytes * count_instrumented_edges;
rounded = size; rounded = size;
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
......
...@@ -4856,8 +4856,8 @@ mark_set_1 (pbi, code, reg, cond, insn, flags) ...@@ -4856,8 +4856,8 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
/* Count (weighted) references, stores, etc. This counts a /* Count (weighted) references, stores, etc. This counts a
register twice if it is modified, but that is correct. */ register twice if it is modified, but that is correct. */
REG_N_SETS (i) += 1; REG_N_SETS (i) += 1;
REG_N_REFS (i) += (optimize_size ? 1 REG_N_REFS (i) += 1;
: pbi->bb->loop_depth + 1); REG_FREQ (i) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
/* The insns where a reg is live are normally counted /* The insns where a reg is live are normally counted
elsewhere, but we want the count to include the insn elsewhere, but we want the count to include the insn
...@@ -5524,7 +5524,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg) ...@@ -5524,7 +5524,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
/* Count an extra reference to the reg. When a reg is /* Count an extra reference to the reg. When a reg is
incremented, spilling it is worse, so we want to make incremented, spilling it is worse, so we want to make
that less likely. */ that less likely. */
REG_N_REFS (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1); REG_FREQ (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
/* Count the increment as a setting of the register, /* Count the increment as a setting of the register,
even though it isn't a SET in rtl. */ even though it isn't a SET in rtl. */
...@@ -5689,8 +5689,9 @@ mark_used_reg (pbi, reg, cond, insn) ...@@ -5689,8 +5689,9 @@ mark_used_reg (pbi, reg, cond, insn)
REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL; REG_BASIC_BLOCK (regno_first) = REG_BLOCK_GLOBAL;
/* Count (weighted) number of uses of each reg. */ /* Count (weighted) number of uses of each reg. */
REG_N_REFS (regno_first) REG_FREQ (regno_first)
+= (optimize_size ? 1 : pbi->bb->loop_depth + 1); += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
REG_N_REFS (regno_first)++;
} }
} }
...@@ -6111,8 +6112,7 @@ try_pre_increment_1 (pbi, insn) ...@@ -6111,8 +6112,7 @@ try_pre_increment_1 (pbi, insn)
so we want to make that less likely. */ so we want to make that less likely. */
if (regno >= FIRST_PSEUDO_REGISTER) if (regno >= FIRST_PSEUDO_REGISTER)
{ {
REG_N_REFS (regno) += (optimize_size ? 1 REG_FREQ (regno) += (optimize_size ? 1 : pbi->bb->loop_depth + 1);
: pbi->bb->loop_depth + 1);
REG_N_SETS (regno)++; REG_N_SETS (regno)++;
} }
...@@ -6359,9 +6359,10 @@ dump_flow_info (file) ...@@ -6359,9 +6359,10 @@ dump_flow_info (file)
register basic_block bb = BASIC_BLOCK (i); register basic_block bb = BASIC_BLOCK (i);
register edge e; register edge e;
fprintf (file, "\nBasic block %d: first insn %d, last %d, loop_depth %d, count %d, freq %d.\n", fprintf (file, "\nBasic block %d: first insn %d, last %d, loop_depth %d, count ",
i, INSN_UID (bb->head), INSN_UID (bb->end), bb->loop_depth, i, INSN_UID (bb->head), INSN_UID (bb->end), bb->loop_depth);
bb->count, bb->frequency); fprintf (file, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
fprintf (file, ", freq %i.\n", bb->frequency);
fprintf (file, "Predecessors: "); fprintf (file, "Predecessors: ");
for (e = bb->pred; e; e = e->pred_next) for (e = bb->pred; e; e = e->pred_next)
...@@ -6405,7 +6406,10 @@ dump_edge_info (file, e, do_succ) ...@@ -6405,7 +6406,10 @@ dump_edge_info (file, e, do_succ)
fprintf (file, " %d", side->index); fprintf (file, " %d", side->index);
if (e->count) if (e->count)
fprintf (file, " count:%d", e->count); {
fprintf (file, " count:");
fprintf (file, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) e->count);
}
if (e->flags) if (e->flags)
{ {
...@@ -6445,8 +6449,9 @@ dump_bb (bb, outf) ...@@ -6445,8 +6449,9 @@ dump_bb (bb, outf)
rtx last; rtx last;
edge e; edge e;
fprintf (outf, ";; Basic block %d, loop depth %d, count %d", fprintf (outf, ";; Basic block %d, loop depth %d, count ",
bb->index, bb->loop_depth, bb->count); bb->index, bb->loop_depth, bb->count);
fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
putc ('\n', outf); putc ('\n', outf);
fputs (";; Predecessors: ", outf); fputs (";; Predecessors: ", outf);
......
...@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA. */
#include "intl.h" #include "intl.h"
#undef abort #undef abort
typedef HOST_WIDEST_INT gcov_type;
#include "gcov-io.h" #include "gcov-io.h"
/* The .bb file format consists of several lists of 4-byte integers /* The .bb file format consists of several lists of 4-byte integers
...@@ -104,7 +105,7 @@ struct sourcefile *sources; ...@@ -104,7 +105,7 @@ struct sourcefile *sources;
struct adj_list { struct adj_list {
int source; int source;
int target; int target;
int arc_count; gcov_type arc_count;
unsigned int count_valid : 1; unsigned int count_valid : 1;
unsigned int on_tree : 1; unsigned int on_tree : 1;
unsigned int fake : 1; unsigned int fake : 1;
...@@ -123,9 +124,9 @@ struct adj_list { ...@@ -123,9 +124,9 @@ struct adj_list {
struct bb_info { struct bb_info {
struct adj_list *succ; struct adj_list *succ;
struct adj_list *pred; struct adj_list *pred;
int succ_count; gcov_type succ_count;
int pred_count; gcov_type pred_count;
int exec_count; gcov_type exec_count;
unsigned int count_valid : 1; unsigned int count_valid : 1;
unsigned int on_tree : 1; unsigned int on_tree : 1;
#if 0 #if 0
...@@ -579,8 +580,8 @@ create_program_flow_graph (bptr) ...@@ -579,8 +580,8 @@ create_program_flow_graph (bptr)
for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next) for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
if (! arcptr->on_tree) if (! arcptr->on_tree)
{ {
long tmp_count = 0; gcov_type tmp_count = 0;
if (da_file && __read_long (&tmp_count, da_file, 8)) if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
abort(); abort();
arcptr->arc_count = tmp_count; arcptr->arc_count = tmp_count;
...@@ -594,7 +595,8 @@ static void ...@@ -594,7 +595,8 @@ static void
solve_program_flow_graph (bptr) solve_program_flow_graph (bptr)
struct bb_info_list *bptr; struct bb_info_list *bptr;
{ {
int passes, changes, total; int passes, changes;
gcov_type total;
int i; int i;
struct adj_list *arcptr; struct adj_list *arcptr;
struct bb_info *bb_graph; struct bb_info *bb_graph;
...@@ -975,7 +977,7 @@ output_data () ...@@ -975,7 +977,7 @@ output_data ()
int this_file; int this_file;
/* An array indexed by line number which indicates how many times that line /* An array indexed by line number which indicates how many times that line
was executed. */ was executed. */
long *line_counts; gcov_type *line_counts;
/* An array indexed by line number which indicates whether the line was /* An array indexed by line number which indicates whether the line was
present in the bb file (i.e. whether it had code associate with it). present in the bb file (i.e. whether it had code associate with it).
Lines never executed are those which both exist, and have zero execution Lines never executed are those which both exist, and have zero execution
...@@ -1035,7 +1037,7 @@ output_data () ...@@ -1035,7 +1037,7 @@ output_data ()
else else
source_file_name = s_ptr->name; source_file_name = s_ptr->name;
line_counts = (long *) xcalloc (sizeof (long), s_ptr->maxlineno); line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
line_exists = xcalloc (1, s_ptr->maxlineno); line_exists = xcalloc (1, s_ptr->maxlineno);
if (output_branch_probs) if (output_branch_probs)
branch_probs = (struct arcdata **) branch_probs = (struct arcdata **)
...@@ -1324,8 +1326,12 @@ output_data () ...@@ -1324,8 +1326,12 @@ output_data ()
if (line_exists[count]) if (line_exists[count])
{ {
if (line_counts[count]) if (line_counts[count])
fprintf (gcov_file, "%12ld %s", line_counts[count], {
char c[20];
sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
fprintf (gcov_file, "%12s %s", c,
string); string);
}
else else
fprintf (gcov_file, " ###### %s", string); fprintf (gcov_file, " ###### %s", string);
} }
......
...@@ -94,9 +94,12 @@ struct allocno ...@@ -94,9 +94,12 @@ struct allocno
/* Number of calls crossed by each allocno. */ /* Number of calls crossed by each allocno. */
int calls_crossed; int calls_crossed;
/* Number of refs (weighted) to each allocno. */ /* Number of refs to each allocno. */
int n_refs; int n_refs;
/* Frequency of uses of each allocno. */
int freq;
/* Guess at live length of each allocno. /* Guess at live length of each allocno.
This is actually the max of the live lengths of the regs. */ This is actually the max of the live lengths of the regs. */
int live_length; int live_length;
...@@ -215,11 +218,14 @@ static HARD_REG_SET no_global_alloc_regs; ...@@ -215,11 +218,14 @@ static HARD_REG_SET no_global_alloc_regs;
static HARD_REG_SET regs_used_so_far; static HARD_REG_SET regs_used_so_far;
/* Number of refs (weighted) to each hard reg, as used by local alloc. /* Number of refs to each hard reg, as used by local alloc.
It is zero for a reg that contains global pseudos or is explicitly used. */ It is zero for a reg that contains global pseudos or is explicitly used. */
static int local_reg_n_refs[FIRST_PSEUDO_REGISTER]; static int local_reg_n_refs[FIRST_PSEUDO_REGISTER];
/* Frequency of uses of given hard reg. */
static int local_reg_freq[FIRST_PSEUDO_REGISTER];
/* Guess at live length of each hard reg, as used by local alloc. /* Guess at live length of each hard reg, as used by local alloc.
This is actually the sum of the live lengths of the specific regs. */ This is actually the sum of the live lengths of the specific regs. */
...@@ -447,6 +453,7 @@ global_alloc (file) ...@@ -447,6 +453,7 @@ global_alloc (file)
allocno[num].size = PSEUDO_REGNO_SIZE (i); allocno[num].size = PSEUDO_REGNO_SIZE (i);
allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i); allocno[num].calls_crossed += REG_N_CALLS_CROSSED (i);
allocno[num].n_refs += REG_N_REFS (i); allocno[num].n_refs += REG_N_REFS (i);
allocno[num].freq += REG_FREQ (i);
if (allocno[num].live_length < REG_LIVE_LENGTH (i)) if (allocno[num].live_length < REG_LIVE_LENGTH (i))
allocno[num].live_length = REG_LIVE_LENGTH (i); allocno[num].live_length = REG_LIVE_LENGTH (i);
} }
...@@ -456,6 +463,7 @@ global_alloc (file) ...@@ -456,6 +463,7 @@ global_alloc (file)
override it. */ override it. */
memset ((char *) local_reg_live_length, 0, sizeof local_reg_live_length); memset ((char *) local_reg_live_length, 0, sizeof local_reg_live_length);
memset ((char *) local_reg_n_refs, 0, sizeof local_reg_n_refs); memset ((char *) local_reg_n_refs, 0, sizeof local_reg_n_refs);
memset ((char *) local_reg_freq, 0, sizeof local_reg_freq);
for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++) for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++)
if (reg_renumber[i] >= 0) if (reg_renumber[i] >= 0)
{ {
...@@ -466,6 +474,7 @@ global_alloc (file) ...@@ -466,6 +474,7 @@ global_alloc (file)
for (j = regno; j < endregno; j++) for (j = regno; j < endregno; j++)
{ {
local_reg_n_refs[j] += REG_N_REFS (i); local_reg_n_refs[j] += REG_N_REFS (i);
local_reg_freq[j] += REG_FREQ (i);
local_reg_live_length[j] += REG_LIVE_LENGTH (i); local_reg_live_length[j] += REG_LIVE_LENGTH (i);
} }
} }
...@@ -473,7 +482,7 @@ global_alloc (file) ...@@ -473,7 +482,7 @@ global_alloc (file)
/* We can't override local-alloc for a reg used not just by local-alloc. */ /* We can't override local-alloc for a reg used not just by local-alloc. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i]) if (regs_ever_live[i])
local_reg_n_refs[i] = 0; local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS; allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
...@@ -605,11 +614,11 @@ allocno_compare (v1p, v2p) ...@@ -605,11 +614,11 @@ allocno_compare (v1p, v2p)
times a register can occur in one insn (surely less than 100). times a register can occur in one insn (surely less than 100).
Multiplying this by 10000 can't overflow. */ Multiplying this by 10000 can't overflow. */
register int pri1 register int pri1
= (((double) (floor_log2 (allocno[v1].n_refs) * allocno[v1].n_refs) = (((double) (floor_log2 (allocno[v1].n_refs) * allocno[v1].freq)
/ allocno[v1].live_length) / allocno[v1].live_length)
* 10000 * allocno[v1].size); * 10000 * allocno[v1].size);
register int pri2 register int pri2
= (((double) (floor_log2 (allocno[v2].n_refs) * allocno[v2].n_refs) = (((double) (floor_log2 (allocno[v2].n_refs) * allocno[v2].freq)
/ allocno[v2].live_length) / allocno[v2].live_length)
* 10000 * allocno[v2].size); * 10000 * allocno[v2].size);
if (pri2 - pri1) if (pri2 - pri1)
...@@ -1204,9 +1213,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying) ...@@ -1204,9 +1213,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
variables so as to avoid excess precision problems that occur variables so as to avoid excess precision problems that occur
on a i386-unknown-sysv4.2 (unixware) host. */ on a i386-unknown-sysv4.2 (unixware) host. */
double tmp1 = ((double) local_reg_n_refs[regno] double tmp1 = ((double) local_reg_freq[regno]
/ local_reg_live_length[regno]); / local_reg_live_length[regno]);
double tmp2 = ((double) allocno[num].n_refs double tmp2 = ((double) allocno[num].freq
/ allocno[num].live_length); / allocno[num].live_length);
if (tmp1 < tmp2) if (tmp1 < tmp2)
...@@ -1256,6 +1265,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying) ...@@ -1256,6 +1265,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
SET_HARD_REG_BIT (regs_used_so_far, j); SET_HARD_REG_BIT (regs_used_so_far, j);
/* This is no longer a reg used just by local regs. */ /* This is no longer a reg used just by local regs. */
local_reg_n_refs[j] = 0; local_reg_n_refs[j] = 0;
local_reg_freq[j] = 0;
} }
/* For each other pseudo-reg conflicting with this one, /* For each other pseudo-reg conflicting with this one,
mark it as conflicting with the hard regs this one occupies. */ mark it as conflicting with the hard regs this one occupies. */
......
...@@ -1263,12 +1263,19 @@ __eprintf (const char *string, const char *expression, ...@@ -1263,12 +1263,19 @@ __eprintf (const char *string, const char *expression,
#ifdef L_bb #ifdef L_bb
#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
typedef long gcov_type;
#else
typedef long long gcov_type;
#endif
/* Structure emitted by -a */ /* Structure emitted by -a */
struct bb struct bb
{ {
long zero_word; long zero_word;
const char *filename; const char *filename;
long *counts; gcov_type *counts;
long ncounts; long ncounts;
struct bb *next; struct bb *next;
const unsigned long *addresses; const unsigned long *addresses;
...@@ -1415,9 +1422,9 @@ __bb_exit_func (void) ...@@ -1415,9 +1422,9 @@ __bb_exit_func (void)
for (i = 0; i < n_counts; i++) for (i = 0; i < n_counts; i++)
{ {
long v = 0; gcov_type v = 0;
if (__read_long (&v, da_file, 8) != 0) if (__read_gcov_type (&v, da_file, 8) != 0)
{ {
fprintf (stderr, "arc profiling: Can't read output file %s.\n", fprintf (stderr, "arc profiling: Can't read output file %s.\n",
ptr->filename); ptr->filename);
...@@ -1439,7 +1446,7 @@ __bb_exit_func (void) ...@@ -1439,7 +1446,7 @@ __bb_exit_func (void)
That way we can easily verify that the proper source/executable/ That way we can easily verify that the proper source/executable/
data file combination is being used from gcov. */ data file combination is being used from gcov. */
if (__write_long (ptr->ncounts, da_file, 8) != 0) if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
{ {
fprintf (stderr, "arc profiling: Error writing output file %s.\n", fprintf (stderr, "arc profiling: Error writing output file %s.\n",
...@@ -1448,11 +1455,11 @@ __bb_exit_func (void) ...@@ -1448,11 +1455,11 @@ __bb_exit_func (void)
else else
{ {
int j; int j;
long *count_ptr = ptr->counts; gcov_type *count_ptr = ptr->counts;
int ret = 0; int ret = 0;
for (j = ptr->ncounts; j > 0; j--) for (j = ptr->ncounts; j > 0; j--)
{ {
if (__write_long (*count_ptr, da_file, 8) != 0) if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
{ {
ret=1; ret=1;
break; break;
......
...@@ -85,6 +85,10 @@ struct qty ...@@ -85,6 +85,10 @@ struct qty
int n_refs; int n_refs;
/* The frequency of uses of quantity Q. */
int freq;
/* Insn number (counting from head of basic block) /* Insn number (counting from head of basic block)
where quantity Q was born. -1 if birth has not been recorded. */ where quantity Q was born. -1 if birth has not been recorded. */
...@@ -321,6 +325,7 @@ alloc_qty (regno, mode, size, birth) ...@@ -321,6 +325,7 @@ alloc_qty (regno, mode, size, birth)
qty[qtyno].min_class = reg_preferred_class (regno); qty[qtyno].min_class = reg_preferred_class (regno);
qty[qtyno].alternate_class = reg_alternate_class (regno); qty[qtyno].alternate_class = reg_alternate_class (regno);
qty[qtyno].n_refs = REG_N_REFS (regno); qty[qtyno].n_refs = REG_N_REFS (regno);
qty[qtyno].freq = REG_FREQ (regno);
qty[qtyno].changes_mode = REG_CHANGES_MODE (regno); qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
} }
...@@ -1127,6 +1132,7 @@ update_equiv_regs () ...@@ -1127,6 +1132,7 @@ update_equiv_regs ()
remove_death (regno, insn); remove_death (regno, insn);
REG_N_REFS (regno) = 0; REG_N_REFS (regno) = 0;
REG_FREQ (regno) = 0;
PUT_CODE (equiv_insn, NOTE); PUT_CODE (equiv_insn, NOTE);
NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED; NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (equiv_insn) = 0; NOTE_SOURCE_FILE (equiv_insn) = 0;
...@@ -1697,7 +1703,7 @@ block_alloc (b) ...@@ -1697,7 +1703,7 @@ block_alloc (b)
QTY_CMP_PRI is also used by qty_sugg_compare. */ QTY_CMP_PRI is also used by qty_sugg_compare. */
#define QTY_CMP_PRI(q) \ #define QTY_CMP_PRI(q) \
((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].n_refs * qty[q].size) \ ((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].freq * qty[q].size) \
/ (qty[q].death - qty[q].birth)) * 10000)) / (qty[q].death - qty[q].birth)) * 10000))
static int static int
...@@ -1966,6 +1972,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead) ...@@ -1966,6 +1972,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
/* Update info about quantity SQTY. */ /* Update info about quantity SQTY. */
qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg); qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
qty[sqty].n_refs += REG_N_REFS (sreg); qty[sqty].n_refs += REG_N_REFS (sreg);
qty[sqty].freq += REG_FREQ (sreg);
if (usize < ssize) if (usize < ssize)
{ {
register int i; register int i;
......
...@@ -43,11 +43,11 @@ Boston, MA 02111-1307, USA. */ ...@@ -43,11 +43,11 @@ Boston, MA 02111-1307, USA. */
#include "regs.h" #include "regs.h"
#include "expr.h" #include "expr.h"
#include "function.h" #include "function.h"
#include "gcov-io.h"
#include "toplev.h" #include "toplev.h"
#include "ggc.h" #include "ggc.h"
#include "hard-reg-set.h" #include "hard-reg-set.h"
#include "basic-block.h" #include "basic-block.h"
#include "gcov-io.h"
/* Additional information about the edges we need. */ /* Additional information about the edges we need. */
struct edge_info struct edge_info
...@@ -59,8 +59,8 @@ struct edge_info ...@@ -59,8 +59,8 @@ struct edge_info
struct bb_info struct bb_info
{ {
unsigned int count_valid : 1; unsigned int count_valid : 1;
int succ_count; gcov_type succ_count;
int pred_count; gcov_type pred_count;
}; };
#define EDGE_INFO(e) ((struct edge_info *) (e)->aux) #define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
...@@ -256,8 +256,8 @@ compute_branch_probabilities () ...@@ -256,8 +256,8 @@ compute_branch_probabilities ()
num_edges++; num_edges++;
if (da_file) if (da_file)
{ {
long value; gcov_type value;
__read_long (&value, da_file, 8); __read_gcov_type (&value, da_file, 8);
e->count = value; e->count = value;
} }
else else
...@@ -265,11 +265,18 @@ compute_branch_probabilities () ...@@ -265,11 +265,18 @@ compute_branch_probabilities ()
EDGE_INFO (e)->count_valid = 1; EDGE_INFO (e)->count_valid = 1;
BB_INFO (bb)->succ_count--; BB_INFO (bb)->succ_count--;
BB_INFO (e->dest)->pred_count--; BB_INFO (e->dest)->pred_count--;
if (rtl_dump_file)
{
fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
bb->index, e->dest->index);
fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) e->count);
}
} }
} }
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "%d edge counts read\n", num_edges); fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
/* For every block in the file, /* For every block in the file,
- if every exit/entrance edge has a known count, then set the block count - if every exit/entrance edge has a known count, then set the block count
...@@ -303,7 +310,7 @@ compute_branch_probabilities () ...@@ -303,7 +310,7 @@ compute_branch_probabilities ()
if (bi->succ_count == 0) if (bi->succ_count == 0)
{ {
edge e; edge e;
int total = 0; gcov_type total = 0;
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
total += e->count; total += e->count;
...@@ -314,7 +321,7 @@ compute_branch_probabilities () ...@@ -314,7 +321,7 @@ compute_branch_probabilities ()
else if (bi->pred_count == 0) else if (bi->pred_count == 0)
{ {
edge e; edge e;
int total = 0; gcov_type total = 0;
for (e = bb->pred; e; e = e->pred_next) for (e = bb->pred; e; e = e->pred_next)
total += e->count; total += e->count;
...@@ -328,7 +335,7 @@ compute_branch_probabilities () ...@@ -328,7 +335,7 @@ compute_branch_probabilities ()
if (bi->succ_count == 1) if (bi->succ_count == 1)
{ {
edge e; edge e;
int total = 0; gcov_type total = 0;
/* One of the counts will be invalid, but it is zero, /* One of the counts will be invalid, but it is zero,
so adding it in also doesn't hurt. */ so adding it in also doesn't hurt. */
...@@ -355,7 +362,7 @@ compute_branch_probabilities () ...@@ -355,7 +362,7 @@ compute_branch_probabilities ()
if (bi->pred_count == 1) if (bi->pred_count == 1)
{ {
edge e; edge e;
int total = 0; gcov_type total = 0;
/* One of the counts will be invalid, but it is zero, /* One of the counts will be invalid, but it is zero,
so adding it in also doesn't hurt. */ so adding it in also doesn't hurt. */
...@@ -411,7 +418,7 @@ compute_branch_probabilities () ...@@ -411,7 +418,7 @@ compute_branch_probabilities ()
basic_block bb = BASIC_BLOCK (i); basic_block bb = BASIC_BLOCK (i);
edge e; edge e;
rtx insn; rtx insn;
int total; gcov_type total;
rtx note; rtx note;
total = bb->count; total = bb->count;
...@@ -1036,14 +1043,14 @@ static rtx ...@@ -1036,14 +1043,14 @@ static rtx
gen_edge_profiler (edgeno) gen_edge_profiler (edgeno)
int edgeno; int edgeno;
{ {
enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0); enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
rtx mem_ref, tmp; rtx mem_ref, tmp;
rtx sequence; rtx sequence;
start_sequence (); start_sequence ();
tmp = force_reg (Pmode, profiler_label); tmp = force_reg (Pmode, profiler_label);
tmp = plus_constant (tmp, LONG_TYPE_SIZE / BITS_PER_UNIT * edgeno); tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
mem_ref = validize_mem (gen_rtx_MEM (mode, tmp)); mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
tmp = expand_binop (mode, add_optab, mem_ref, const1_rtx, tmp = expand_binop (mode, add_optab, mem_ref, const1_rtx,
...@@ -1068,7 +1075,7 @@ output_func_start_profiler () ...@@ -1068,7 +1075,7 @@ output_func_start_profiler ()
char buf[20]; char buf[20];
const char *cfnname; const char *cfnname;
rtx table_address; rtx table_address;
enum machine_mode mode = mode_for_size (LONG_TYPE_SIZE, MODE_INT, 0); enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
int save_flag_inline_functions = flag_inline_functions; int save_flag_inline_functions = flag_inline_functions;
int save_flag_test_coverage = flag_test_coverage; int save_flag_test_coverage = flag_test_coverage;
int save_profile_arc_flag = profile_arc_flag; int save_profile_arc_flag = profile_arc_flag;
......
...@@ -1059,14 +1059,17 @@ scan_one_insn (insn, pass) ...@@ -1059,14 +1059,17 @@ scan_one_insn (insn, pass)
/* This makes one more setting of new insns's dest. */ /* This makes one more setting of new insns's dest. */
REG_N_SETS (REGNO (recog_data.operand[0]))++; REG_N_SETS (REGNO (recog_data.operand[0]))++;
REG_N_REFS (REGNO (recog_data.operand[0]))++; REG_N_REFS (REGNO (recog_data.operand[0]))++;
REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
*recog_data.operand_loc[1] = recog_data.operand[0]; *recog_data.operand_loc[1] = recog_data.operand[0];
REG_N_REFS (REGNO (recog_data.operand[0]))++; REG_N_REFS (REGNO (recog_data.operand[0]))++;
REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
for (i = recog_data.n_dups - 1; i >= 0; i--) for (i = recog_data.n_dups - 1; i >= 0; i--)
if (recog_data.dup_num[i] == 1) if (recog_data.dup_num[i] == 1)
{ {
*recog_data.dup_loc[i] = recog_data.operand[0]; *recog_data.dup_loc[i] = recog_data.operand[0];
REG_N_REFS (REGNO (recog_data.operand[0]))++; REG_N_REFS (REGNO (recog_data.operand[0]))++;
REG_FREQ (REGNO (recog_data.operand[0])) += loop_cost;
} }
return PREV_INSN (newinsn); return PREV_INSN (newinsn);
......
...@@ -67,6 +67,7 @@ typedef struct reg_info_def ...@@ -67,6 +67,7 @@ typedef struct reg_info_def
/* fields set by flow_analysis */ /* fields set by flow_analysis */
int refs; /* # of times (REG n) is used or set */ int refs; /* # of times (REG n) is used or set */
int freq; /* # estimated frequency (REG n) is used or set */
int deaths; /* # of times (REG n) dies */ int deaths; /* # of times (REG n) dies */
int live_length; /* # of instructions (REG n) is live */ int live_length; /* # of instructions (REG n) is live */
int calls_crossed; /* # of calls (REG n) is live across */ int calls_crossed; /* # of calls (REG n) is live across */
...@@ -77,11 +78,14 @@ typedef struct reg_info_def ...@@ -77,11 +78,14 @@ typedef struct reg_info_def
extern varray_type reg_n_info; extern varray_type reg_n_info;
/* Indexed by n, gives number of times (REG n) is used or set. /* Indexed by n, gives number of times (REG n) is used or set. */
References within loops may be counted more times. */
#define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs) #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
/* Estimate frequency of references to register N. */
#define REG_FREQ(N) (VARRAY_REG (reg_n_info, N)->freq)
/* Indexed by n, gives number of times (REG n) is set. /* Indexed by n, gives number of times (REG n) is set.
??? both regscan and flow allocate space for this. We should settle ??? both regscan and flow allocate space for this. We should settle
on just copy. */ on just copy. */
......
...@@ -1567,7 +1567,7 @@ static void ...@@ -1567,7 +1567,7 @@ static void
count_pseudo (reg) count_pseudo (reg)
int reg; int reg;
{ {
int n_refs = REG_N_REFS (reg); int freq = REG_FREQ (reg);
int r = reg_renumber[reg]; int r = reg_renumber[reg];
int nregs; int nregs;
...@@ -1580,11 +1580,11 @@ count_pseudo (reg) ...@@ -1580,11 +1580,11 @@ count_pseudo (reg)
if (r < 0) if (r < 0)
abort (); abort ();
spill_add_cost[r] += n_refs; spill_add_cost[r] += freq;
nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg)); nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
while (nregs-- > 0) while (nregs-- > 0)
spill_cost[r + nregs] += n_refs; spill_cost[r + nregs] += freq;
} }
/* Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the /* Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the
...@@ -1654,9 +1654,9 @@ count_spilled_pseudo (spilled, spilled_nregs, reg) ...@@ -1654,9 +1654,9 @@ count_spilled_pseudo (spilled, spilled_nregs, reg)
SET_REGNO_REG_SET (&spilled_pseudos, reg); SET_REGNO_REG_SET (&spilled_pseudos, reg);
spill_add_cost[r] -= REG_N_REFS (reg); spill_add_cost[r] -= REG_FREQ (reg);
while (nregs-- > 0) while (nregs-- > 0)
spill_cost[r + nregs] -= REG_N_REFS (reg); spill_cost[r + nregs] -= REG_FREQ (reg);
} }
/* Find reload register to use for reload number ORDER. */ /* Find reload register to use for reload number ORDER. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment