{
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. */
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;
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;
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;
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
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. */
/* 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;
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;
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;
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)
/* 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;
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
&& 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;
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 = ®_NOTES (p); *pnote;)
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. */
DEST_REG
};
+
/* A `struct induction' is created for every instruction that sets
an induction variable (either a biv or a giv). */
a substitute for the lifetime information. */
};
+
/* A `struct iv_class' is created for each biv. */
struct iv_class
been reduced. */
};
-typedef struct loop_mem_info
+
+/* Definitions used by the basic induction variable discovery code. */
+enum iv_mode
{
- 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;
+ UNKNOWN_INDUCT,
+ BASIC_INDUCT,
+ NOT_BASIC_INDUCT,
+ 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
- an induction variable, and if so what type. */
- varray_type reg_iv_type;
+ 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
- induction' if register is an induction variable. This holds
- general info for all induction variables. */
- varray_type reg_iv_info;
+ iv' if register is an induction variable. */
+ struct iv *regs;
- /* 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;
+ /* 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 *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
{
int num;
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. */
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. */
/* 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;
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. */
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 ();
/* 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,