Commit 14be28e5 by Michael Hayes Committed by Michael Hayes

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
parent 1d2215fe
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> 2000-12-31 Alexandre Oliva <aoliva@redhat.com>
* resource.c (mark_referenced_resources): Abort() before * resource.c (mark_referenced_resources): Abort() before
......
...@@ -3652,27 +3652,16 @@ loop_bivs_find (loop) ...@@ -3652,27 +3652,16 @@ loop_bivs_find (loop)
{ {
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (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; 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"); ivs->list = 0;
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 *));
for_each_insn_in_loop (loop, check_insn_for_bivs); 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. */ 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 if (REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
/* Above happens if register modified by subreg, etc. */ /* Above happens if register modified by subreg, etc. */
...@@ -3711,7 +3700,7 @@ loop_bivs_init_find (loop) ...@@ -3711,7 +3700,7 @@ loop_bivs_init_find (loop)
struct loop *loop; struct loop *loop;
{ {
struct loop_ivs *ivs = LOOP_IVS (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 *bl;
int call_seen; int call_seen;
rtx p; rtx p;
...@@ -3767,11 +3756,11 @@ loop_bivs_check (loop) ...@@ -3767,11 +3756,11 @@ loop_bivs_check (loop)
struct loop *loop; struct loop *loop;
{ {
struct loop_ivs *ivs = LOOP_IVS (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 *bl;
struct iv_class **backbl; 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 src;
rtx note; rtx note;
...@@ -3846,7 +3835,7 @@ loop_givs_check (loop) ...@@ -3846,7 +3835,7 @@ loop_givs_check (loop)
struct loop_ivs *ivs = LOOP_IVS (loop); struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; 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; struct induction *v;
...@@ -4280,7 +4269,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4280,7 +4269,7 @@ strength_reduce (loop, insn_count, flags)
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (loop); struct loop_ivs *ivs = LOOP_IVS (loop);
rtx p; rtx p;
/* Temporary list pointer for traversing ivs->loop_iv_list. */ /* Temporary list pointer for traversing ivs->list. */
struct iv_class *bl; struct iv_class *bl;
/* Ratio of extra register life span we can justify /* Ratio of extra register life span we can justify
for saving an instruction. More if loop doesn't call subroutines for saving an instruction. More if loop doesn't call subroutines
...@@ -4309,12 +4298,14 @@ strength_reduce (loop, insn_count, flags) ...@@ -4309,12 +4298,14 @@ strength_reduce (loop, insn_count, flags)
else else
end_insert_before = emit_note_after (NOTE_INSN_DELETED, loop->end); 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. */ /* Find all BIVs in loop. */
loop_bivs_find (loop); loop_bivs_find (loop);
/* Exit if there are no bivs. */ /* 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 /* Can still unroll the loop anyways, but indicate that there is no
strength reduction info available. */ strength reduction info available. */
...@@ -4355,13 +4346,13 @@ strength_reduce (loop, insn_count, flags) ...@@ -4355,13 +4346,13 @@ strength_reduce (loop, insn_count, flags)
/* Create reg_map to hold substitutions for replaceable giv regs. /* Create reg_map to hold substitutions for replaceable giv regs.
Some givs might have been made from biv increments, so look at Some givs might have been made from biv increments, so look at
ivs->reg_iv_type for a suitable size. */ 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)); reg_map = (rtx *) xcalloc (reg_map_size, sizeof (rtx));
/* Examine each iv class for feasibility of strength reduction/induction /* Examine each iv class for feasibility of strength reduction/induction
variable elimination. */ variable elimination. */
for (bl = ivs->loop_iv_list; bl; bl = bl->next) for (bl = ivs->list; bl; bl = bl->next)
{ {
struct induction *v; struct induction *v;
int benefit; int benefit;
...@@ -4581,11 +4572,9 @@ strength_reduce (loop, insn_count, flags) ...@@ -4581,11 +4572,9 @@ strength_reduce (loop, insn_count, flags)
fprintf (loop_dump_stream, "\n"); fprintf (loop_dump_stream, "\n");
egress: egress:
VARRAY_FREE (ivs->reg_iv_type); free (ivs->regs);
VARRAY_FREE (ivs->reg_iv_info);
free (ivs->reg_biv_class);
{ {
struct iv_class *iv = ivs->loop_iv_list; struct iv_class *iv = ivs->list;
while (iv) { while (iv) {
struct iv_class *next = iv->next; struct iv_class *next = iv->next;
...@@ -4941,9 +4930,9 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location, ...@@ -4941,9 +4930,9 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
bl->reversed = 0; bl->reversed = 0;
bl->total_benefit = 0; bl->total_benefit = 0;
/* Add this class to ivs->loop_iv_list. */ /* Add this class to ivs->list. */
bl->next = ivs->loop_iv_list; bl->next = ivs->list;
ivs->loop_iv_list = bl; ivs->list = bl;
/* Put it in the array of biv register classes. */ /* Put it in the array of biv register classes. */
REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl; REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl;
...@@ -5448,7 +5437,7 @@ update_giv_derive (loop, p) ...@@ -5448,7 +5437,7 @@ update_giv_derive (loop, p)
subsequent biv update was performed. If this adjustment cannot be done, subsequent biv update was performed. If this adjustment cannot be done,
the giv cannot derive further givs. */ 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) for (biv = bl->biv; biv; biv = biv->next_iv)
if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
|| biv->insn == p) || biv->insn == p)
...@@ -5750,7 +5739,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val, ...@@ -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 /* 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 MULT_VAL == 0. It doesn't matter which BIV we associate this
with. */ with. */
*src_reg = ivs->loop_iv_list->biv->dest_reg; *src_reg = ivs->list->biv->dest_reg;
*mult_val = const0_rtx; *mult_val = const0_rtx;
*add_val = x; *add_val = x;
break; break;
...@@ -7271,7 +7260,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7271,7 +7260,7 @@ check_dbra_loop (loop, insn_count)
it will be zero on the last iteration. Also skip if the biv is it will be zero on the last iteration. Also skip if the biv is
used between its update and the test insn. */ 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 if (bl->biv_count == 1
&& ! bl->biv->maybe_multiple && ! bl->biv->maybe_multiple
...@@ -7461,7 +7450,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7461,7 +7450,7 @@ check_dbra_loop (loop, insn_count)
&& reversible_mem_store && reversible_mem_store
&& (bl->giv_count + bl->biv_count + loop_info->num_mem_sets && (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
+ LOOP_MOVABLES (loop)->num + compare_and_branch == insn_count) + 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) || no_use_except_counting)
{ {
rtx tem; rtx tem;
...@@ -7760,7 +7749,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7760,7 +7749,7 @@ check_dbra_loop (loop, insn_count)
REG_EQUAL notes should still be correct. */ REG_EQUAL notes should still be correct. */
if (! set if (! set
|| GET_CODE (SET_DEST (set)) != REG || 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_TYPE (ivs, REGNO (SET_DEST (set))) != GENERAL_INDUCT
|| REG_IV_INFO (ivs, REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg) || REG_IV_INFO (ivs, REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
for (pnote = &REG_NOTES (p); *pnote;) for (pnote = &REG_NOTES (p); *pnote;)
......
...@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
value is a linear function of a biv. */ value is a linear function of a biv. */
/* Bivs are recognized by `basic_induction_var'; /* 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 /* An enum for the two different types of givs, those that are used
as memory addresses and those that are calculated into registers. */ as memory addresses and those that are calculated into registers. */
...@@ -64,6 +64,7 @@ enum g_types ...@@ -64,6 +64,7 @@ enum g_types
DEST_REG DEST_REG
}; };
/* A `struct induction' is created for every instruction that sets /* A `struct induction' is created for every instruction that sets
an induction variable (either a biv or a giv). */ an induction variable (either a biv or a giv). */
...@@ -152,6 +153,7 @@ struct induction ...@@ -152,6 +153,7 @@ struct induction
a substitute for the lifetime information. */ a substitute for the lifetime information. */
}; };
/* A `struct iv_class' is created for each biv. */ /* A `struct iv_class' is created for each biv. */
struct iv_class struct iv_class
...@@ -182,35 +184,58 @@ struct iv_class ...@@ -182,35 +184,58 @@ struct iv_class
been reduced. */ been reduced. */
}; };
typedef struct loop_mem_info
/* Definitions used by the basic induction variable discovery code. */
enum iv_mode
{ {
rtx mem; /* The MEM itself. */ UNKNOWN_INDUCT,
rtx reg; /* Corresponding pseudo, if any. */ BASIC_INDUCT,
int optimize; /* Nonzero if we can optimize access to this MEM. */ NOT_BASIC_INDUCT,
} loop_mem_info; GENERAL_INDUCT
};
struct loop_ivs
/* A `struct iv' is created for every register. */
struct iv
{ {
/* Indexed by register number, indicates whether or not register is enum iv_mode type;
an induction variable, and if so what type. */ union
varray_type reg_iv_type; {
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 /* Indexed by register number, contains pointer to `struct
induction' if register is an induction variable. This holds iv' if register is an induction variable. */
general info for all induction variables. */ struct iv *regs;
varray_type reg_iv_info;
/* Indexed by register number, contains pointer to `struct iv_class' /* Size of regs array. */
if register is a basic induction variable. This holds info unsigned int n_regs;
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) /* The head of a list which links together (via the next field)
every iv class for the current loop. */ every iv class for the current loop. */
struct iv_class *loop_iv_list; struct iv_class *list;
}; };
typedef struct loop_mem_info
{
rtx mem; /* The MEM itself. */
rtx reg; /* Corresponding pseudo, if any. */
int optimize; /* Nonzero if we can optimize access to this MEM. */
} loop_mem_info;
struct loop_regs struct loop_regs
{ {
int num; int num;
...@@ -342,14 +367,6 @@ struct loop_info ...@@ -342,14 +367,6 @@ struct loop_info
int pre_header_has_call; 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. */ /* Variables declared in loop.c, but also needed in unroll.c. */
...@@ -359,11 +376,6 @@ extern unsigned int max_reg_before_loop; ...@@ -359,11 +376,6 @@ extern unsigned int max_reg_before_loop;
extern struct loop **uid_loop; extern struct loop **uid_loop;
extern FILE *loop_dump_stream; 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 /* Forward declarations for non-static functions declared in loop.c and
unroll.c. */ unroll.c. */
......
...@@ -1184,7 +1184,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -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 /* Search the list of bivs and givs to find ones which need to be remapped
when split, and set their reg_map entry appropriately. */ 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) if (REGNO (bl->biv->src_reg) != bl->regno)
map->reg_map[bl->regno] = bl->biv->src_reg; map->reg_map[bl->regno] = bl->biv->src_reg;
...@@ -2447,7 +2447,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2447,7 +2447,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx loop_start = loop->start; rtx loop_start = loop->start;
rtx loop_end = loop->end; 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, /* Biv_total_increment must return a constant value,
otherwise we can not calculate the split values. */ otherwise we can not calculate the split values. */
...@@ -3545,7 +3545,7 @@ loop_iterations (loop) ...@@ -3545,7 +3545,7 @@ loop_iterations (loop)
will propagate a new pseudo into the old iteration register but will propagate a new pseudo into the old iteration register but
this will be marked by having the REG_USERVAR_P bit set. */ 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)) && ! REG_USERVAR_P (iteration_var))
abort (); abort ();
...@@ -3563,7 +3563,7 @@ loop_iterations (loop) ...@@ -3563,7 +3563,7 @@ loop_iterations (loop)
/* If this is a new register, can't handle it since we don't have any /* If this is a new register, can't handle it since we don't have any
reg_iv_type entry for it. */ 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) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
......
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