loop.h (struct iv): New.

* loop.h (struct iv): New.
	(REG_IV_TYPE, REG_IV_CLASS, REG_INFO): Modify to use 'struct iv'.
	(struct loop_ivs): Replace 'reg_iv_type', 'reg_iv_info',
	'reg_biv_class' fields with 'regs' and 'n_regs'.
	(struct ivs): Rename 'loop_iv_list' field to 'list'.
	* loop.c (loop_bivs_find, strength_reduce): Use ivs->regs array.
	* unroll.c (loop_iterations): Check array bounds with ivs->n_regs.

From-SVN: r38582
This commit is contained in:
Michael Hayes 2001-01-01 00:49:30 +00:00 committed by Michael Hayes
parent 1d2215feb9
commit 14be28e5f4
4 changed files with 85 additions and 74 deletions

View File

@ -1,3 +1,13 @@
2001-01-01 Michael Hayes <mhayes@redhat.com>
* loop.h (struct iv): New.
(REG_IV_TYPE, REG_IV_CLASS, REG_INFO): Modify to use 'struct iv'.
(struct loop_ivs): Replace 'reg_iv_type', 'reg_iv_info',
'reg_biv_class' fields with 'regs' and 'n_regs'.
(struct ivs): Rename 'loop_iv_list' field to 'list'.
* loop.c (loop_bivs_find, strength_reduce): Use ivs->regs array.
* unroll.c (loop_iterations): Check array bounds with ivs->n_regs.
2000-12-31 Alexandre Oliva <aoliva@redhat.com>
* resource.c (mark_referenced_resources): Abort() before

View File

@ -3652,27 +3652,16 @@ loop_bivs_find (loop)
{
struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
/* Temporary list pointers for traversing ivs->loop_iv_list. */
/* Temporary list pointers for traversing ivs->list. */
struct iv_class *bl, **backbl;
/* Ratio of extra register life span we can justify
for saving an instruction. More if loop doesn't call subroutines
since in that case saving an insn makes more difference
and more registers are available. */
/* ??? could set this to last value of threshold in move_movables */
ivs->loop_iv_list = 0;
VARRAY_INT_INIT (ivs->reg_iv_type, max_reg_before_loop, "reg_iv_type");
VARRAY_GENERIC_PTR_INIT (ivs->reg_iv_info, max_reg_before_loop,
"reg_iv_info");
ivs->reg_biv_class = (struct iv_class **)
xcalloc (max_reg_before_loop, sizeof (struct iv_class *));
ivs->list = 0;
for_each_insn_in_loop (loop, check_insn_for_bivs);
/* Scan ivs->loop_iv_list to remove all regs that proved not to be bivs.
/* Scan ivs->list to remove all regs that proved not to be bivs.
Make a sanity check against regs->n_times_set. */
for (backbl = &ivs->loop_iv_list, bl = *backbl; bl; bl = bl->next)
for (backbl = &ivs->list, bl = *backbl; bl; bl = bl->next)
{
if (REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
/* Above happens if register modified by subreg, etc. */
@ -3711,7 +3700,7 @@ loop_bivs_init_find (loop)
struct loop *loop;
{
struct loop_ivs *ivs = LOOP_IVS (loop);
/* Temporary list pointers for traversing ivs->loop_iv_list. */
/* Temporary list pointers for traversing ivs->list. */
struct iv_class *bl;
int call_seen;
rtx p;
@ -3767,11 +3756,11 @@ loop_bivs_check (loop)
struct loop *loop;
{
struct loop_ivs *ivs = LOOP_IVS (loop);
/* Temporary list pointers for traversing ivs->loop_iv_list. */
/* Temporary list pointers for traversing ivs->list. */
struct iv_class *bl;
struct iv_class **backbl;
for (backbl = &ivs->loop_iv_list; (bl = *backbl); backbl = &bl->next)
for (backbl = &ivs->list; (bl = *backbl); backbl = &bl->next)
{
rtx src;
rtx note;
@ -3846,7 +3835,7 @@ loop_givs_check (loop)
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl;
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
{
struct induction *v;
@ -4280,7 +4269,7 @@ strength_reduce (loop, insn_count, flags)
struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx p;
/* Temporary list pointer for traversing ivs->loop_iv_list. */
/* Temporary list pointer for traversing ivs->list. */
struct iv_class *bl;
/* Ratio of extra register life span we can justify
for saving an instruction. More if loop doesn't call subroutines
@ -4309,12 +4298,14 @@ strength_reduce (loop, insn_count, flags)
else
end_insert_before = emit_note_after (NOTE_INSN_DELETED, loop->end);
ivs->n_regs = max_reg_before_loop;
ivs->regs = (struct iv *) xcalloc (ivs->n_regs, sizeof (struct iv));
/* Find all BIVs in loop. */
loop_bivs_find (loop);
/* Exit if there are no bivs. */
if (! ivs->loop_iv_list)
if (! ivs->list)
{
/* Can still unroll the loop anyways, but indicate that there is no
strength reduction info available. */
@ -4355,13 +4346,13 @@ strength_reduce (loop, insn_count, flags)
/* Create reg_map to hold substitutions for replaceable giv regs.
Some givs might have been made from biv increments, so look at
ivs->reg_iv_type for a suitable size. */
reg_map_size = ivs->reg_iv_type->num_elements;
reg_map_size = ivs->n_regs;
reg_map = (rtx *) xcalloc (reg_map_size, sizeof (rtx));
/* Examine each iv class for feasibility of strength reduction/induction
variable elimination. */
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
{
struct induction *v;
int benefit;
@ -4581,11 +4572,9 @@ strength_reduce (loop, insn_count, flags)
fprintf (loop_dump_stream, "\n");
egress:
VARRAY_FREE (ivs->reg_iv_type);
VARRAY_FREE (ivs->reg_iv_info);
free (ivs->reg_biv_class);
free (ivs->regs);
{
struct iv_class *iv = ivs->loop_iv_list;
struct iv_class *iv = ivs->list;
while (iv) {
struct iv_class *next = iv->next;
@ -4941,9 +4930,9 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
bl->reversed = 0;
bl->total_benefit = 0;
/* Add this class to ivs->loop_iv_list. */
bl->next = ivs->loop_iv_list;
ivs->loop_iv_list = bl;
/* Add this class to ivs->list. */
bl->next = ivs->list;
ivs->list = bl;
/* Put it in the array of biv register classes. */
REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl;
@ -5448,7 +5437,7 @@ update_giv_derive (loop, p)
subsequent biv update was performed. If this adjustment cannot be done,
the giv cannot derive further givs. */
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
for (biv = bl->biv; biv; biv = biv->next_iv)
if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
|| biv->insn == p)
@ -5750,7 +5739,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
/* Since this is now an invariant and wasn't before, it must be a giv
with MULT_VAL == 0. It doesn't matter which BIV we associate this
with. */
*src_reg = ivs->loop_iv_list->biv->dest_reg;
*src_reg = ivs->list->biv->dest_reg;
*mult_val = const0_rtx;
*add_val = x;
break;
@ -7271,7 +7260,7 @@ check_dbra_loop (loop, insn_count)
it will be zero on the last iteration. Also skip if the biv is
used between its update and the test insn. */
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
{
if (bl->biv_count == 1
&& ! bl->biv->maybe_multiple
@ -7461,7 +7450,7 @@ check_dbra_loop (loop, insn_count)
&& reversible_mem_store
&& (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
+ LOOP_MOVABLES (loop)->num + compare_and_branch == insn_count)
&& (bl == ivs->loop_iv_list && bl->next == 0))
&& (bl == ivs->list && bl->next == 0))
|| no_use_except_counting)
{
rtx tem;
@ -7760,7 +7749,7 @@ check_dbra_loop (loop, insn_count)
REG_EQUAL notes should still be correct. */
if (! set
|| GET_CODE (SET_DEST (set)) != REG
|| (size_t) REGNO (SET_DEST (set)) >= ivs->reg_iv_type->num_elements
|| (size_t) REGNO (SET_DEST (set)) >= ivs->n_regs
|| REG_IV_TYPE (ivs, REGNO (SET_DEST (set))) != GENERAL_INDUCT
|| REG_IV_INFO (ivs, REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
for (pnote = &REG_NOTES (p); *pnote;)

View File

@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
value is a linear function of a biv. */
/* Bivs are recognized by `basic_induction_var';
Givs by `general_induct_var'. */
Givs by `general_induction_var'. */
/* An enum for the two different types of givs, those that are used
as memory addresses and those that are calculated into registers. */
@ -64,6 +64,7 @@ enum g_types
DEST_REG
};
/* A `struct induction' is created for every instruction that sets
an induction variable (either a biv or a giv). */
@ -152,6 +153,7 @@ struct induction
a substitute for the lifetime information. */
};
/* A `struct iv_class' is created for each biv. */
struct iv_class
@ -182,6 +184,50 @@ struct iv_class
been reduced. */
};
/* Definitions used by the basic induction variable discovery code. */
enum iv_mode
{
UNKNOWN_INDUCT,
BASIC_INDUCT,
NOT_BASIC_INDUCT,
GENERAL_INDUCT
};
/* A `struct iv' is created for every register. */
struct iv
{
enum iv_mode type;
union
{
struct iv_class *class;
struct induction *info;
} iv;
};
#define REG_IV_TYPE(ivs, n) ivs->regs[n].type
#define REG_IV_INFO(ivs, n) ivs->regs[n].iv.info
#define REG_IV_CLASS(ivs, n) ivs->regs[n].iv.class
struct loop_ivs
{
/* Indexed by register number, contains pointer to `struct
iv' if register is an induction variable. */
struct iv *regs;
/* Size of regs array. */
unsigned int n_regs;
/* The head of a list which links together (via the next field)
every iv class for the current loop. */
struct iv_class *list;
};
typedef struct loop_mem_info
{
rtx mem; /* The MEM itself. */
@ -189,27 +235,6 @@ typedef struct loop_mem_info
int optimize; /* Nonzero if we can optimize access to this MEM. */
} loop_mem_info;
struct loop_ivs
{
/* Indexed by register number, indicates whether or not register is
an induction variable, and if so what type. */
varray_type reg_iv_type;
/* Indexed by register number, contains pointer to `struct
induction' if register is an induction variable. This holds
general info for all induction variables. */
varray_type reg_iv_info;
/* Indexed by register number, contains pointer to `struct iv_class'
if register is a basic induction variable. This holds info
describing the class (a related group) of induction variables
that the biv belongs to. */
struct iv_class **reg_biv_class;
/* The head of a list which links together (via the next field)
every iv class for the current loop. */
struct iv_class *loop_iv_list;
};
struct loop_regs
{
@ -342,14 +367,6 @@ struct loop_info
int pre_header_has_call;
};
/* Definitions used by the basic induction variable discovery code. */
enum iv_mode
{
UNKNOWN_INDUCT,
BASIC_INDUCT,
NOT_BASIC_INDUCT,
GENERAL_INDUCT
};
/* Variables declared in loop.c, but also needed in unroll.c. */
@ -359,11 +376,6 @@ extern unsigned int max_reg_before_loop;
extern struct loop **uid_loop;
extern FILE *loop_dump_stream;
#define REG_IV_TYPE(ivs, n) \
(*(enum iv_mode *) &VARRAY_INT(ivs->reg_iv_type, (n)))
#define REG_IV_INFO(ivs, n) \
(*(struct induction **) &VARRAY_GENERIC_PTR(ivs->reg_iv_info, (n)))
#define REG_IV_CLASS(ivs, n) ivs->reg_biv_class[n]
/* Forward declarations for non-static functions declared in loop.c and
unroll.c. */

View File

@ -1184,7 +1184,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
/* Search the list of bivs and givs to find ones which need to be remapped
when split, and set their reg_map entry appropriately. */
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
{
if (REGNO (bl->biv->src_reg) != bl->regno)
map->reg_map[bl->regno] = bl->biv->src_reg;
@ -2447,7 +2447,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx loop_start = loop->start;
rtx loop_end = loop->end;
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
for (bl = ivs->list; bl; bl = bl->next)
{
/* Biv_total_increment must return a constant value,
otherwise we can not calculate the split values. */
@ -3545,7 +3545,7 @@ loop_iterations (loop)
will propagate a new pseudo into the old iteration register but
this will be marked by having the REG_USERVAR_P bit set. */
if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements
if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
&& ! REG_USERVAR_P (iteration_var))
abort ();
@ -3563,7 +3563,7 @@ loop_iterations (loop)
/* If this is a new register, can't handle it since we don't have any
reg_iv_type entry for it. */
if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements)
if ((unsigned) REGNO (iteration_var) >= ivs->n_regs)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,