cse.c (cse_reg_info): Remove hash_next, next, regno.

* cse.c (cse_reg_info): Remove hash_next, next, regno.  Add
	timestamp.
	(cse_reg_info_list, cse_reg_info_list_free, REGHASH_SHIFT,
	REGHASH_SIZE, REGHASH_MASK, reg_hash, REGHASH_FN,
	cached_cse_reg_info, GET_CSE_REG_INFO): Remove.
	(cached_regno): Initialize to INVALID_REGNUM.
	(cse_reg_info_table_size,
	cse_reg_info_table_first_uninitialized,
	cse_reg_info_timestamp): New.
	(REG_TICK, REG_IN_TABLE, SUBREG_TICKED, REG_QTY): Use
	get_cse_reg_info.
	(init_cse_reg_info, get_cse_reg_info_1): New.
	(get_cse_reg_info): Cache the last look-up.
	(new_basic_block): Update the code to clear mappings from
	registers to cse_reg_info entries.
	(cse_main): Call init_cse_reg_info.

From-SVN: r94506
This commit is contained in:
Kazu Hirata 2005-02-01 00:14:47 +00:00 committed by Kazu Hirata
parent b4519d39bc
commit bc5e3b54eb
2 changed files with 116 additions and 87 deletions

View File

@ -1,3 +1,22 @@
2005-02-01 Kazu Hirata <kazu@cs.umass.edu>
* cse.c (cse_reg_info): Remove hash_next, next, regno. Add
timestamp.
(cse_reg_info_list, cse_reg_info_list_free, REGHASH_SHIFT,
REGHASH_SIZE, REGHASH_MASK, reg_hash, REGHASH_FN,
cached_cse_reg_info, GET_CSE_REG_INFO): Remove.
(cached_regno): Initialize to INVALID_REGNUM.
(cse_reg_info_table_size,
cse_reg_info_table_first_uninitialized,
cse_reg_info_timestamp): New.
(REG_TICK, REG_IN_TABLE, SUBREG_TICKED, REG_QTY): Use
get_cse_reg_info.
(init_cse_reg_info, get_cse_reg_info_1): New.
(get_cse_reg_info): Cache the last look-up.
(new_basic_block): Update the code to clear mappings from
registers to cse_reg_info entries.
(cse_main): Call init_cse_reg_info.
2005-01-31 Steven Bosscher <stevenb@suse.de>
PR c/19333

184
gcc/cse.c
View File

@ -302,14 +302,8 @@ static struct reg_eqv_elem *reg_eqv_table;
struct cse_reg_info
{
/* Next in hash chain. */
struct cse_reg_info *hash_next;
/* The next cse_reg_info structure in the free or used list. */
struct cse_reg_info *next;
/* Search key */
unsigned int regno;
/* The timestamp at which this register is initialized. */
unsigned int timestamp;
/* The quantity number of the register's current contents. */
int reg_qty;
@ -329,39 +323,22 @@ struct cse_reg_info
unsigned int subreg_ticked;
};
/* We maintain a linked list of cse_reg_info instances, which is
partitioned into two pieces. The first part, pointed to by
cse_reg_info_list, is a list of those entries that are in use. The
second part, pointed to by cse_reg_info_list_free, is a list of
those entries that are not in use.
/* A table of cse_reg_info indexed by register numbers. */
struct cse_reg_info *cse_reg_info_table;
We combine these two parts into one linked list for efficiency.
Specifically, when we take an element from the second part and want
to move it to the first part, all we have to do is move the pointer
cse_reg_info_list_free to the next element. Also, if we wish to
move all elements into the second part, we just have to move the
pointer to the first element of the list. */
/* The size of the above table. */
static unsigned int cse_reg_info_table_size;
/* A linked list of cse_reg_info entries that have been allocated so
far. */
static struct cse_reg_info *cse_reg_info_list;
/* The index of the first entry that has not been initialized. */
static unsigned int cse_reg_info_table_first_uninitialized;
/* A pointer to the first unused entry in the above linked list. */
static struct cse_reg_info *cse_reg_info_list_free;
/* A mapping from registers to cse_reg_info data structures. */
#define REGHASH_SHIFT 7
#define REGHASH_SIZE (1 << REGHASH_SHIFT)
#define REGHASH_MASK (REGHASH_SIZE - 1)
static struct cse_reg_info *reg_hash[REGHASH_SIZE];
#define REGHASH_FN(REGNO) \
(((REGNO) ^ ((REGNO) >> REGHASH_SHIFT)) & REGHASH_MASK)
/* The last lookup we did into the cse_reg_info_tree. This allows us
to cache repeated lookups. */
static unsigned int cached_regno;
static struct cse_reg_info *cached_cse_reg_info;
/* The timestamp at the beginning of the current run of
cse_basic_block. We increment this variable at at the beginning of
the current run of cse_basic_block. The timestamp field of a
cse_reg_info entry matches the value of this variable if and only
if the entry has been initialized during the current run of
cse_basic_block. */
static unsigned int cse_reg_info_timestamp;
/* A HARD_REG_SET containing all the hard registers for which there is
currently a REG expression in the hash table. Note the difference
@ -523,29 +500,23 @@ struct table_elt
#define COST(X) (REG_P (X) ? 0 : notreg_cost (X, SET))
#define COST_IN(X,OUTER) (REG_P (X) ? 0 : notreg_cost (X, OUTER))
/* Get the info associated with register N. */
#define GET_CSE_REG_INFO(N) \
(((N) == cached_regno && cached_cse_reg_info) \
? cached_cse_reg_info : get_cse_reg_info ((N)))
/* Get the number of times this register has been updated in this
basic block. */
#define REG_TICK(N) ((GET_CSE_REG_INFO (N))->reg_tick)
#define REG_TICK(N) (get_cse_reg_info (N)->reg_tick)
/* Get the point at which REG was recorded in the table. */
#define REG_IN_TABLE(N) ((GET_CSE_REG_INFO (N))->reg_in_table)
#define REG_IN_TABLE(N) (get_cse_reg_info (N)->reg_in_table)
/* Get the SUBREG set at the last increment to REG_TICK (-1 if not a
SUBREG). */
#define SUBREG_TICKED(N) ((GET_CSE_REG_INFO (N))->subreg_ticked)
#define SUBREG_TICKED(N) (get_cse_reg_info (N)->subreg_ticked)
/* Get the quantity number for REG. */
#define REG_QTY(N) ((GET_CSE_REG_INFO (N))->reg_qty)
#define REG_QTY(N) (get_cse_reg_info (N)->reg_qty)
/* Determine if the quantity number for register X represents a valid index
into the qty_table. */
@ -647,7 +618,8 @@ static rtx cse_basic_block (rtx, rtx, struct branch_path *);
static void count_reg_usage (rtx, int *, int);
static int check_for_label_ref (rtx *, void *);
extern void dump_class (struct table_elt*);
static struct cse_reg_info * get_cse_reg_info (unsigned int);
static void get_cse_reg_info_1 (unsigned int regno);
static struct cse_reg_info * get_cse_reg_info (unsigned int regno);
static int check_dependence (rtx *, void *);
static void flush_hash_table (void);
@ -862,47 +834,87 @@ notreg_cost (rtx x, enum rtx_code outer)
}
static struct cse_reg_info *
get_cse_reg_info (unsigned int regno)
/* Initialize CSE_REG_INFO_TABLE. */
static void
init_cse_reg_info (unsigned int nregs)
{
struct cse_reg_info **hash_head = &reg_hash[REGHASH_FN (regno)];
struct cse_reg_info *p;
for (p = *hash_head; p != NULL; p = p->hash_next)
if (p->regno == regno)
break;
if (p == NULL)
/* Do we need to grow the table? */
if (nregs > cse_reg_info_table_size)
{
/* Get a new cse_reg_info structure. */
if (cse_reg_info_list_free)
unsigned int new_size;
if (cse_reg_info_table_size < 2048)
{
p = cse_reg_info_list_free;
cse_reg_info_list_free = p->next;
/* Compute a new size that is a power of 2 and no smaller
than the large of NREGS and 64. */
new_size = (cse_reg_info_table_size
? cse_reg_info_table_size : 64);
while (new_size < nregs)
new_size *= 2;
}
else
{
p = xmalloc (sizeof (struct cse_reg_info));
p->next = cse_reg_info_list;
cse_reg_info_list = p;
/* If we need a big table, allocate just enough to hold
NREGS registers. */
new_size = nregs;
}
/* Insert into hash table. */
p->hash_next = *hash_head;
*hash_head = p;
/* Initialize it. */
p->reg_tick = 1;
p->reg_in_table = -1;
p->subreg_ticked = -1;
p->reg_qty = -regno - 1;
p->regno = regno;
/* Reallocate the table with NEW_SIZE entries. */
cse_reg_info_table = xrealloc (cse_reg_info_table,
(sizeof (struct cse_reg_info)
* new_size));
cse_reg_info_table_size = new_size;
}
/* Cache this lookup; we tend to be looking up information about the
same register several times in a row. */
cached_regno = regno;
cached_cse_reg_info = p;
/* Do we have all of the first NREGS entries initialized? */
if (cse_reg_info_table_first_uninitialized < nregs)
{
unsigned int old_timestamp = cse_reg_info_timestamp - 1;
unsigned int i;
/* Put the old timestamp on newly allocated entries so that they
will all be considered out of date. We do not touch those
entries beyond the first NREGS entries to be nice to the
virtual memory. */
for (i = cse_reg_info_table_first_uninitialized; i < nregs; i++)
cse_reg_info_table[i].timestamp = old_timestamp;
cse_reg_info_table_first_uninitialized = nregs;
}
}
/* Given REGNO, ensure that a cse_reg_info entry exists for REGNO by
growing the cse_reg_info_table and/or initializing the entry for
REGNO. */
static void
get_cse_reg_info_1 (unsigned int regno)
{
/* Set TIMESTAMP field to CSE_REG_INFO_TIMESTAMP so that this
entry will be considered to have been initialized. */
cse_reg_info_table[regno].timestamp = cse_reg_info_timestamp;
/* Initialize the rest of the entry. */
cse_reg_info_table[regno].reg_tick = 1;
cse_reg_info_table[regno].reg_in_table = -1;
cse_reg_info_table[regno].subreg_ticked = -1;
cse_reg_info_table[regno].reg_qty = -regno - 1;
}
/* Find a cse_reg_info entry for REGNO. */
static inline struct cse_reg_info *
get_cse_reg_info (unsigned int regno)
{
struct cse_reg_info *p = &cse_reg_info_table[regno];
/* If we are looking for REGNO that is different from the last
look-up, make sure the entry for REGNO exists and has been
initialized. */
if (p->timestamp != cse_reg_info_timestamp)
get_cse_reg_info_1 (regno);
return p;
}
@ -917,14 +929,10 @@ new_basic_block (void)
next_qty = 0;
/* Invalidate cse_reg_info_table and its cache. */
cse_reg_info_timestamp++;
/* Clear out hash table state for this pass. */
memset (reg_hash, 0, sizeof reg_hash);
cse_reg_info_list_free = cse_reg_info_list;
cached_cse_reg_info = 0;
CLEAR_HARD_REG_SET (hard_regs_in_table);
/* The per-quantity values used to be initialized here, but it is
@ -6698,6 +6706,8 @@ cse_main (rtx f, int nregs, FILE *file)
rtx insn = f;
int i;
init_cse_reg_info (nregs);
val.path = xmalloc (sizeof (struct branch_path)
* PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));