Commit ed5bb68d by Michael Hayes Committed by Michael Hayes

loop.h (LOOP_IVS): New macro.

	* loop.h (LOOP_IVS): New macro.
	(REG_IV_TYPE, REG_IV_INFO): Add ivs argument.
	(struct loop_ivs): New.
	(struct loop_info): Add ivs field.
	(reg_iv_type, reg_iv_info): Delete prototype.
	(reg_biv_class, loop_iv_list): Likewise.
	* loop.c (record_biv, find_life_end): Pass loop argument.
	(reg_iv_type): Remove global array and use
	field in loop_regs structure within loop_ivs structure.
	(reg_iv_info, reg_biv_class, loop_iv_list): Likewise.
	(first_increment_giv, last_increment_giv): Use entry in
	loop_ivs structure.
	(record_initial): Pass ivs pointer.
	* unroll.c (copy_loop_body, remap_split_bivs): Add loop argument.

From-SVN: r36336
parent 1ecd860b
2000-09-12 Michael Hayes <mhayes@cygnus.com> 2000-09-12 Michael Hayes <mhayes@cygnus.com>
* loop.h (LOOP_IVS): New macro.
(REG_IV_TYPE, REG_IV_INFO): Add ivs argument.
(struct loop_ivs): New.
(struct loop_info): Add ivs field.
(reg_iv_type, reg_iv_info): Delete prototype.
(reg_biv_class, loop_iv_list): Likewise.
* loop.c (record_biv, find_life_end): Pass loop argument.
(reg_iv_type): Remove global array and use
field in loop_regs structure within loop_ivs structure.
(reg_iv_info, reg_biv_class, loop_iv_list): Likewise.
(first_increment_giv, last_increment_giv): Use entry in
loop_ivs structure.
(record_initial): Pass ivs pointer.
* unroll.c (copy_loop_body, remap_split_bivs): Add loop argument.
2000-09-12 Michael Hayes <mhayes@cygnus.com>
* loop.h (LOOP_REGS): New macro. * loop.h (LOOP_REGS): New macro.
(struct loop_regs): New. (struct loop_regs): New.
(struct loop_info): Add regs field. (struct loop_info): Add regs field.
......
...@@ -78,6 +78,9 @@ static int max_luid; ...@@ -78,6 +78,9 @@ static int max_luid;
static int max_loop_num; static int max_loop_num;
/* Bound on pseudo register number before loop optimization. /* Bound on pseudo register number before loop optimization.
A pseudo has valid regscan info if its number is < max_reg_before_loop. */ A pseudo has valid regscan info if its number is < max_reg_before_loop. */
unsigned int max_reg_before_loop; unsigned int max_reg_before_loop;
...@@ -190,13 +193,14 @@ static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movables *, ...@@ -190,13 +193,14 @@ static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movables *,
struct loop_regs *)); struct loop_regs *));
static void add_label_notes PARAMS ((rtx, rtx)); static void add_label_notes PARAMS ((rtx, rtx));
static void move_movables PARAMS ((struct loop *loop, struct movables *, static void move_movables PARAMS ((struct loop *loop, struct movables *,
int, int, int)); int, int));
static int count_nonfixed_reads PARAMS ((const struct loop *, rtx)); static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
static void strength_reduce PARAMS ((struct loop *, int, int)); static void strength_reduce PARAMS ((struct loop *, int, int));
static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type)); static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx)); static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int)); static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int));
static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *, static void record_biv PARAMS ((struct loop *, struct induction *,
rtx, rtx, rtx, rtx, rtx *,
int, int)); int, int));
static void check_final_value PARAMS ((const struct loop *, static void check_final_value PARAMS ((const struct loop *,
struct induction *)); struct induction *));
...@@ -220,7 +224,8 @@ static rtx express_from_1 PARAMS ((rtx, rtx, rtx)); ...@@ -220,7 +224,8 @@ static rtx express_from_1 PARAMS ((rtx, rtx, rtx));
static rtx combine_givs_p PARAMS ((struct induction *, struct induction *)); static rtx combine_givs_p PARAMS ((struct induction *, struct induction *));
static void combine_givs PARAMS ((struct loop_regs *, struct iv_class *)); static void combine_givs PARAMS ((struct loop_regs *, struct iv_class *));
struct recombine_givs_stats; struct recombine_givs_stats;
static int find_life_end PARAMS ((rtx, struct recombine_givs_stats *, static int find_life_end PARAMS ((const struct loop *, rtx,
struct recombine_givs_stats *,
rtx, rtx)); rtx, rtx));
static void recombine_givs PARAMS ((const struct loop *, struct iv_class *, static void recombine_givs PARAMS ((const struct loop *, struct iv_class *,
int)); int));
...@@ -1037,7 +1042,7 @@ scan_loop (loop, flags) ...@@ -1037,7 +1042,7 @@ scan_loop (loop, flags)
optimizing for code size. */ optimizing for code size. */
if (! optimize_size) if (! optimize_size)
move_movables (loop, movables, threshold, insn_count, nregs); move_movables (loop, movables, threshold, insn_count);
/* Now candidates that still are negative are those not moved. /* Now candidates that still are negative are those not moved.
Change regs->set_in_loop to indicate that those are not actually Change regs->set_in_loop to indicate that those are not actually
...@@ -1349,9 +1354,8 @@ combine_movables (movables, regs) ...@@ -1349,9 +1354,8 @@ combine_movables (movables, regs)
struct movables *movables; struct movables *movables;
struct loop_regs *regs; struct loop_regs *regs;
{ {
int nregs = regs->num;
register struct movable *m; register struct movable *m;
char *matched_regs = (char *) xmalloc (nregs); char *matched_regs = (char *) xmalloc (regs->num);
enum machine_mode mode; enum machine_mode mode;
/* Regs that are set more than once are not allowed to match /* Regs that are set more than once are not allowed to match
...@@ -1365,7 +1369,7 @@ combine_movables (movables, regs) ...@@ -1365,7 +1369,7 @@ combine_movables (movables, regs)
register struct movable *m1; register struct movable *m1;
int regno = m->regno; int regno = m->regno;
bzero (matched_regs, nregs); bzero (matched_regs, regs->num);
matched_regs[regno] = 1; matched_regs[regno] = 1;
/* We want later insns to match the first one. Don't make the first /* We want later insns to match the first one. Don't make the first
...@@ -1497,7 +1501,7 @@ static int ...@@ -1497,7 +1501,7 @@ static int
rtx_equal_for_loop_p (x, y, movables, regs) rtx_equal_for_loop_p (x, y, movables, regs)
rtx x, y; rtx x, y;
struct movables *movables; struct movables *movables;
struct loop_regs * regs; struct loop_regs *regs;
{ {
register int i; register int i;
register int j; register int j;
...@@ -1582,8 +1586,8 @@ rtx_equal_for_loop_p (x, y, movables, regs) ...@@ -1582,8 +1586,8 @@ rtx_equal_for_loop_p (x, y, movables, regs)
break; break;
case 'e': case 'e':
if (rtx_equal_for_loop_p (XEXP (x, i), XEXP (y, i), if (rtx_equal_for_loop_p (XEXP (x, i), XEXP (y, i), movables, regs)
movables, regs) == 0) == 0)
return 0; return 0;
break; break;
...@@ -1651,14 +1655,14 @@ add_label_notes (x, insns) ...@@ -1651,14 +1655,14 @@ add_label_notes (x, insns)
other throughout. */ other throughout. */
static void static void
move_movables (loop, movables, threshold, insn_count, nregs) move_movables (loop, movables, threshold, insn_count)
struct loop *loop; struct loop *loop;
struct movables *movables; struct movables *movables;
int threshold; int threshold;
int insn_count; int insn_count;
int nregs;
{ {
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
int nregs = regs->num;
rtx new_start = 0; rtx new_start = 0;
register struct movable *m; register struct movable *m;
register rtx p; register rtx p;
...@@ -3528,34 +3532,6 @@ loop_reg_used_before_p (loop, set, insn) ...@@ -3528,34 +3532,6 @@ loop_reg_used_before_p (loop, set, insn)
/* Bivs are recognized by `basic_induction_var'; /* Bivs are recognized by `basic_induction_var';
Givs by `general_induction_var'. */ Givs by `general_induction_var'. */
/* 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;
/* Givs made from biv increments are always splittable for loop unrolling.
Since there is no regscan info for them, we have to keep track of them
separately. */
unsigned int first_increment_giv, last_increment_giv;
/* Communication with routines called via `note_stores'. */ /* Communication with routines called via `note_stores'. */
static rtx note_insn; static rtx note_insn;
...@@ -3761,8 +3737,9 @@ strength_reduce (loop, insn_count, flags) ...@@ -3761,8 +3737,9 @@ strength_reduce (loop, insn_count, flags)
{ {
struct loop_info *loop_info = LOOP_INFO (loop); struct loop_info *loop_info = LOOP_INFO (loop);
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx p; rtx p;
/* Temporary list pointers for traversing loop_iv_list. */ /* Temporary list pointers for traversing ivs->loop_iv_list. */
struct iv_class *bl, **backbl; struct iv_class *bl, **backbl;
/* 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
...@@ -3783,12 +3760,12 @@ strength_reduce (loop, insn_count, flags) ...@@ -3783,12 +3760,12 @@ strength_reduce (loop, insn_count, flags)
rtx loop_scan_start = loop->scan_start; rtx loop_scan_start = loop->scan_start;
rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type"); VARRAY_INT_INIT (ivs->reg_iv_type, max_reg_before_loop, "reg_iv_type");
VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info"); VARRAY_GENERIC_PTR_INIT (ivs->reg_iv_info, max_reg_before_loop, "reg_iv_info");
reg_biv_class = (struct iv_class **) ivs->reg_biv_class = (struct iv_class **)
xcalloc (max_reg_before_loop, sizeof (struct iv_class *)); xcalloc (max_reg_before_loop, sizeof (struct iv_class *));
loop_iv_list = 0; ivs->loop_iv_list = 0;
addr_placeholder = gen_reg_rtx (Pmode); addr_placeholder = gen_reg_rtx (Pmode);
/* Save insn immediately after the loop_end. Insns inserted after loop_end /* Save insn immediately after the loop_end. Insns inserted after loop_end
...@@ -3805,11 +3782,11 @@ strength_reduce (loop, insn_count, flags) ...@@ -3805,11 +3782,11 @@ strength_reduce (loop, insn_count, flags)
for_each_insn_in_loop (loop, check_insn_for_bivs); for_each_insn_in_loop (loop, check_insn_for_bivs);
/* Scan loop_iv_list to remove all regs that proved not to be bivs. /* Scan ivs->loop_iv_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 = &loop_iv_list, bl = *backbl; bl; bl = bl->next) for (backbl = &ivs->loop_iv_list, bl = *backbl; bl; bl = bl->next)
{ {
if (REG_IV_TYPE (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. */
/* Make sure it is not recognized as a basic induction var: */ /* Make sure it is not recognized as a basic induction var: */
|| VARRAY_INT (regs->n_times_set, bl->regno) != bl->biv_count || VARRAY_INT (regs->n_times_set, bl->regno) != bl->biv_count
...@@ -3820,12 +3797,12 @@ strength_reduce (loop, insn_count, flags) ...@@ -3820,12 +3797,12 @@ strength_reduce (loop, insn_count, flags)
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n", fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
bl->regno, bl->regno,
(REG_IV_TYPE (bl->regno) != BASIC_INDUCT (REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
? "not induction variable" ? "not induction variable"
: (! bl->incremented ? "never incremented" : (! bl->incremented ? "never incremented"
: "count error"))); : "count error")));
REG_IV_TYPE (bl->regno) = NOT_BASIC_INDUCT; REG_IV_TYPE (ivs, bl->regno) = NOT_BASIC_INDUCT;
*backbl = bl->next; *backbl = bl->next;
} }
else else
...@@ -3838,7 +3815,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3838,7 +3815,7 @@ strength_reduce (loop, insn_count, flags)
} }
/* Exit if there are no bivs. */ /* Exit if there are no bivs. */
if (! loop_iv_list) if (! ivs->loop_iv_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. */
...@@ -3860,7 +3837,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3860,7 +3837,7 @@ strength_reduce (loop, insn_count, flags)
call_seen = 1; call_seen = 1;
if (INSN_P (p)) if (INSN_P (p))
note_stores (PATTERN (p), record_initial, NULL); note_stores (PATTERN (p), record_initial, ivs);
/* Record any test of a biv that branches around the loop if no store /* Record any test of a biv that branches around the loop if no store
between it and the start of loop. We only care about tests with between it and the start of loop. We only care about tests with
...@@ -3871,7 +3848,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3871,7 +3848,7 @@ strength_reduce (loop, insn_count, flags)
&& (test = get_condition_for_loop (loop, p)) != 0 && (test = get_condition_for_loop (loop, p)) != 0
&& GET_CODE (XEXP (test, 0)) == REG && GET_CODE (XEXP (test, 0)) == REG
&& REGNO (XEXP (test, 0)) < max_reg_before_loop && REGNO (XEXP (test, 0)) < max_reg_before_loop
&& (bl = reg_biv_class[REGNO (XEXP (test, 0))]) != 0 && (bl = ivs->reg_biv_class[REGNO (XEXP (test, 0))]) != 0
&& valid_initial_value_p (XEXP (test, 1), p, call_seen, loop_start) && valid_initial_value_p (XEXP (test, 1), p, call_seen, loop_start)
&& bl->init_insn == 0) && bl->init_insn == 0)
{ {
...@@ -3890,7 +3867,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3890,7 +3867,7 @@ strength_reduce (loop, insn_count, flags)
/* Look at the each biv and see if we can say anything better about its /* Look at the each biv and see if we can say anything better about its
initial value from any initializing insns set up above. (This is done initial value from any initializing insns set up above. (This is done
in two passes to avoid missing SETs in a PARALLEL.) */ in two passes to avoid missing SETs in a PARALLEL.) */
for (backbl = &loop_iv_list; (bl = *backbl); backbl = &bl->next) for (backbl = &ivs->loop_iv_list; (bl = *backbl); backbl = &bl->next)
{ {
rtx src; rtx src;
rtx note; rtx note;
...@@ -3953,7 +3930,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3953,7 +3930,7 @@ strength_reduce (loop, insn_count, flags)
{ {
unsigned int regno = REGNO (XEXP (src, 0)); unsigned int regno = REGNO (XEXP (src, 0));
for (bl2 = loop_iv_list; bl2; bl2 = bl2->next) for (bl2 = ivs->loop_iv_list; bl2; bl2 = bl2->next)
if (bl2->regno == regno) if (bl2->regno == regno)
break; break;
} }
...@@ -3989,8 +3966,8 @@ strength_reduce (loop, insn_count, flags) ...@@ -3989,8 +3966,8 @@ strength_reduce (loop, insn_count, flags)
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "is giv of biv %d\n", bl2->regno); fprintf (loop_dump_stream, "is giv of biv %d\n", bl2->regno);
/* Let this giv be discovered by the generic code. */ /* Let this giv be discovered by the generic code. */
REG_IV_TYPE (bl->regno) = UNKNOWN_INDUCT; REG_IV_TYPE (ivs, bl->regno) = UNKNOWN_INDUCT;
reg_biv_class[bl->regno] = (struct iv_class *) NULL_PTR; ivs->reg_biv_class[bl->regno] = (struct iv_class *) NULL_PTR;
/* We can get better optimization if we can move the giv setting /* We can get better optimization if we can move the giv setting
before the first giv use. */ before the first giv use. */
if (dominator if (dominator
...@@ -4054,8 +4031,8 @@ strength_reduce (loop, insn_count, flags) ...@@ -4054,8 +4031,8 @@ strength_reduce (loop, insn_count, flags)
/* Get an upper bound for the number of registers /* Get an upper bound for the number of registers
we might have after all bivs have been processed. */ we might have after all bivs have been processed. */
first_increment_giv = max_reg_num (); ivs->first_increment_giv = max_reg_num ();
for (n_extra_increment = 0, bl = loop_iv_list; bl; bl = bl->next) for (n_extra_increment = 0, bl = ivs->loop_iv_list; bl; bl = bl->next)
n_extra_increment += bl->biv_count - 1; n_extra_increment += bl->biv_count - 1;
/* If the loop contains volatile memory references do not allow any /* If the loop contains volatile memory references do not allow any
...@@ -4063,13 +4040,13 @@ strength_reduce (loop, insn_count, flags) ...@@ -4063,13 +4040,13 @@ strength_reduce (loop, insn_count, flags)
markers. */ markers. */
if (n_extra_increment && ! loop_info->has_volatile) if (n_extra_increment && ! loop_info->has_volatile)
{ {
unsigned int nregs = first_increment_giv + n_extra_increment; unsigned int nregs = ivs->first_increment_giv + n_extra_increment;
/* Reallocate reg_iv_type and reg_iv_info. */ /* Reallocate ivs->reg_iv_type and ivs->reg_iv_info. */
VARRAY_GROW (reg_iv_type, nregs); VARRAY_GROW (ivs->reg_iv_type, nregs);
VARRAY_GROW (reg_iv_info, nregs); VARRAY_GROW (ivs->reg_iv_info, nregs);
for (bl = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_list; bl; bl = bl->next)
{ {
struct induction **vp, *v, *next; struct induction **vp, *v, *next;
int biv_dead_after_loop = 0; int biv_dead_after_loop = 0;
...@@ -4135,10 +4112,11 @@ strength_reduce (loop, insn_count, flags) ...@@ -4135,10 +4112,11 @@ strength_reduce (loop, insn_count, flags)
old_reg = v->dest_reg; old_reg = v->dest_reg;
dest_reg = gen_reg_rtx (v->mode); dest_reg = gen_reg_rtx (v->mode);
/* Unlike reg_iv_type / reg_iv_info, the other three arrays /* Unlike ivs->reg_iv_type / ivs->reg_iv_info, the other
have been allocated with some slop space, so we may not three arrays have been allocated with some slop
actually need to reallocate them. If we do, the following space, so we may not actually need to reallocate
if statement will be executed just once in this loop. */ them. If we do, the following if statement will be
executed just once in this loop. */
if ((unsigned) max_reg_num () > regs->n_times_set->num_elements) if ((unsigned) max_reg_num () > regs->n_times_set->num_elements)
{ {
/* Grow all the remaining arrays. */ /* Grow all the remaining arrays. */
...@@ -4227,8 +4205,8 @@ strength_reduce (loop, insn_count, flags) ...@@ -4227,8 +4205,8 @@ strength_reduce (loop, insn_count, flags)
VARRAY_INT (regs->n_times_set, new_regno) = 1; VARRAY_INT (regs->n_times_set, new_regno) = 1;
VARRAY_CHAR (regs->may_not_optimize, new_regno) = 0; VARRAY_CHAR (regs->may_not_optimize, new_regno) = 0;
REG_IV_TYPE (new_regno) = GENERAL_INDUCT; REG_IV_TYPE (ivs, new_regno) = GENERAL_INDUCT;
REG_IV_INFO (new_regno) = v; REG_IV_INFO (ivs, new_regno) = v;
/* If next_insn has a REG_EQUAL note that mentiones OLD_REG, /* If next_insn has a REG_EQUAL note that mentiones OLD_REG,
it must be replaced. */ it must be replaced. */
...@@ -4286,7 +4264,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4286,7 +4264,7 @@ strength_reduce (loop, insn_count, flags)
} }
} }
} }
last_increment_giv = max_reg_num () - 1; ivs->last_increment_giv = max_reg_num () - 1;
/* Search the loop for general induction variables. */ /* Search the loop for general induction variables. */
...@@ -4304,7 +4282,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4304,7 +4282,7 @@ strength_reduce (loop, insn_count, flags)
can be calculated. This must be done after loop_iterations is called, can be calculated. This must be done after loop_iterations is called,
so that final_giv_value will work correctly. */ so that final_giv_value will work correctly. */
for (bl = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_list; bl; bl = bl->next)
{ {
struct induction *v; struct induction *v;
...@@ -4320,14 +4298,14 @@ strength_reduce (loop, insn_count, flags) ...@@ -4320,14 +4298,14 @@ 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
reg_iv_type for a suitable size. */ ivs->reg_iv_type for a suitable size. */
reg_map_size = reg_iv_type->num_elements; reg_map_size = ivs->reg_iv_type->num_elements;
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 = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_list; bl; bl = bl->next)
{ {
struct induction *v; struct induction *v;
int benefit; int benefit;
...@@ -4533,20 +4511,20 @@ strength_reduce (loop, insn_count, flags) ...@@ -4533,20 +4511,20 @@ strength_reduce (loop, insn_count, flags)
/* Now that we know which givs will be reduced, try to rearrange the /* Now that we know which givs will be reduced, try to rearrange the
combinations to reduce register pressure. combinations to reduce register pressure.
recombine_givs calls find_life_end, which needs reg_iv_type and recombine_givs calls find_life_end, which needs ivs->reg_iv_type and
reg_iv_info to be valid for all pseudos. We do the necessary ivs->reg_iv_info to be valid for all pseudos. We do the necessary
reallocation here since it allows to check if there are still reallocation here since it allows to check if there are still
more bivs to process. */ more bivs to process. */
nregs = max_reg_num (); nregs = max_reg_num ();
if (nregs > reg_iv_type->num_elements) if (nregs > ivs->reg_iv_type->num_elements)
{ {
/* If there are still more bivs to process, allocate some slack /* If there are still more bivs to process, allocate some slack
space so that we're not constantly reallocating these arrays. */ space so that we're not constantly reallocating these arrays. */
if (bl->next) if (bl->next)
nregs += nregs / 4; nregs += nregs / 4;
/* Reallocate reg_iv_type and reg_iv_info. */ /* Reallocate ivs->reg_iv_type and ivs->reg_iv_info. */
VARRAY_GROW (reg_iv_type, nregs); VARRAY_GROW (ivs->reg_iv_type, nregs);
VARRAY_GROW (reg_iv_info, nregs); VARRAY_GROW (ivs->reg_iv_info, nregs);
} }
recombine_givs (loop, bl, flags & LOOP_UNROLL); recombine_givs (loop, bl, flags & LOOP_UNROLL);
...@@ -4958,9 +4936,9 @@ strength_reduce (loop, insn_count, flags) ...@@ -4958,9 +4936,9 @@ strength_reduce (loop, insn_count, flags)
fprintf (loop_dump_stream, "\n"); fprintf (loop_dump_stream, "\n");
egress: egress:
VARRAY_FREE (reg_iv_type); VARRAY_FREE (ivs->reg_iv_type);
VARRAY_FREE (reg_iv_info); VARRAY_FREE (ivs->reg_iv_info);
free (reg_biv_class); free (ivs->reg_biv_class);
if (reg_map) if (reg_map)
free (reg_map); free (reg_map);
} }
...@@ -4973,6 +4951,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple) ...@@ -4973,6 +4951,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
int not_every_iteration; int not_every_iteration;
int maybe_multiple; int maybe_multiple;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx set; rtx set;
rtx dest_reg; rtx dest_reg;
rtx inc_val; rtx inc_val;
...@@ -4986,7 +4965,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple) ...@@ -4986,7 +4965,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
dest_reg = SET_DEST (set); dest_reg = SET_DEST (set);
if (REGNO (dest_reg) < max_reg_before_loop if (REGNO (dest_reg) < max_reg_before_loop
&& REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER && REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
&& REG_IV_TYPE (REGNO (dest_reg)) != NOT_BASIC_INDUCT) && REG_IV_TYPE (ivs, REGNO (dest_reg)) != NOT_BASIC_INDUCT)
{ {
if (basic_induction_var (loop, SET_SRC (set), if (basic_induction_var (loop, SET_SRC (set),
GET_MODE (SET_SRC (set)), GET_MODE (SET_SRC (set)),
...@@ -4999,12 +4978,12 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple) ...@@ -4999,12 +4978,12 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
struct induction *v struct induction *v
= (struct induction *) oballoc (sizeof (struct induction)); = (struct induction *) oballoc (sizeof (struct induction));
record_biv (v, p, dest_reg, inc_val, mult_val, location, record_biv (loop, v, p, dest_reg, inc_val, mult_val, location,
not_every_iteration, maybe_multiple); not_every_iteration, maybe_multiple);
REG_IV_TYPE (REGNO (dest_reg)) = BASIC_INDUCT; REG_IV_TYPE (ivs, REGNO (dest_reg)) = BASIC_INDUCT;
} }
else if (REGNO (dest_reg) < max_reg_before_loop) else if (REGNO (dest_reg) < max_reg_before_loop)
REG_IV_TYPE (REGNO (dest_reg)) = NOT_BASIC_INDUCT; REG_IV_TYPE (ivs, REGNO (dest_reg)) = NOT_BASIC_INDUCT;
} }
} }
return p; return p;
...@@ -5021,6 +5000,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple) ...@@ -5021,6 +5000,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
int maybe_multiple; int maybe_multiple;
{ {
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
rtx set; rtx set;
/* Look for a general induction variable in a register. */ /* Look for a general induction variable in a register. */
if (GET_CODE (p) == INSN if (GET_CODE (p) == INSN
...@@ -5237,8 +5217,9 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple) ...@@ -5237,8 +5217,9 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
executed exactly once per iteration. */ executed exactly once per iteration. */
static void static void
record_biv (v, insn, dest_reg, inc_val, mult_val, location, record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
not_every_iteration, maybe_multiple) not_every_iteration, maybe_multiple)
struct loop *loop;
struct induction *v; struct induction *v;
rtx insn; rtx insn;
rtx dest_reg; rtx dest_reg;
...@@ -5248,6 +5229,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location, ...@@ -5248,6 +5229,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
int not_every_iteration; int not_every_iteration;
int maybe_multiple; int maybe_multiple;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
v->insn = insn; v->insn = insn;
...@@ -5265,7 +5247,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location, ...@@ -5265,7 +5247,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
/* Add this to the reg's iv_class, creating a class /* Add this to the reg's iv_class, creating a class
if this is the first incrementation of the reg. */ if this is the first incrementation of the reg. */
bl = reg_biv_class[REGNO (dest_reg)]; bl = ivs->reg_biv_class[REGNO (dest_reg)];
if (bl == 0) if (bl == 0)
{ {
/* Create and initialize new iv_class. */ /* Create and initialize new iv_class. */
...@@ -5290,12 +5272,12 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location, ...@@ -5290,12 +5272,12 @@ record_biv (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 loop_iv_list. */ /* Add this class to ivs->loop_iv_list. */
bl->next = loop_iv_list; bl->next = ivs->loop_iv_list;
loop_iv_list = bl; ivs->loop_iv_list = bl;
/* Put it in the array of biv register classes. */ /* Put it in the array of biv register classes. */
reg_biv_class[REGNO (dest_reg)] = bl; ivs->reg_biv_class[REGNO (dest_reg)] = bl;
} }
/* Update IV_CLASS entry for this biv. */ /* Update IV_CLASS entry for this biv. */
...@@ -5352,6 +5334,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val, ...@@ -5352,6 +5334,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
int not_every_iteration, maybe_multiple; int not_every_iteration, maybe_multiple;
rtx *location; rtx *location;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct induction *b; struct induction *b;
struct iv_class *bl; struct iv_class *bl;
rtx set = single_set (insn); rtx set = single_set (insn);
...@@ -5420,13 +5403,13 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val, ...@@ -5420,13 +5403,13 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
if (v->lifetime == 0) if (v->lifetime == 0)
v->ignore = 1; v->ignore = 1;
REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT; REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
REG_IV_INFO (REGNO (dest_reg)) = v; REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
} }
/* Add the giv to the class of givs computed from one biv. */ /* Add the giv to the class of givs computed from one biv. */
bl = reg_biv_class[REGNO (src_reg)]; bl = ivs->reg_biv_class[REGNO (src_reg)];
if (bl) if (bl)
{ {
v->next_iv = bl->giv; v->next_iv = bl->giv;
...@@ -5614,10 +5597,11 @@ check_final_value (loop, v) ...@@ -5614,10 +5597,11 @@ check_final_value (loop, v)
const struct loop *loop; const struct loop *loop;
struct induction *v; struct induction *v;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
rtx final_value = 0; rtx final_value = 0;
bl = reg_biv_class[REGNO (v->src_reg)]; bl = ivs->reg_biv_class[REGNO (v->src_reg)];
/* DEST_ADDR givs will never reach here, because they are always marked /* DEST_ADDR givs will never reach here, because they are always marked
replaceable above in record_giv. */ replaceable above in record_giv. */
...@@ -5761,6 +5745,7 @@ update_giv_derive (loop, p) ...@@ -5761,6 +5745,7 @@ update_giv_derive (loop, p)
const struct loop *loop; const struct loop *loop;
rtx p; rtx p;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
struct induction *biv, *giv; struct induction *biv, *giv;
rtx tem; rtx tem;
...@@ -5793,7 +5778,7 @@ update_giv_derive (loop, p) ...@@ -5793,7 +5778,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 = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_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)
...@@ -6069,6 +6054,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val, ...@@ -6069,6 +6054,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
int *pbenefit; int *pbenefit;
enum machine_mode addr_mode; enum machine_mode addr_mode;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx orig_x = x; rtx orig_x = x;
char *storage; char *storage;
...@@ -6095,7 +6081,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val, ...@@ -6095,7 +6081,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 = loop_iv_list->biv->dest_reg; *src_reg = ivs->loop_iv_list->biv->dest_reg;
*mult_val = const0_rtx; *mult_val = const0_rtx;
*add_val = x; *add_val = x;
break; break;
...@@ -6184,6 +6170,7 @@ simplify_giv_expr (loop, x, ext_val, benefit) ...@@ -6184,6 +6170,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
rtx *ext_val; rtx *ext_val;
int *benefit; int *benefit;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
enum machine_mode mode = GET_MODE (x); enum machine_mode mode = GET_MODE (x);
rtx arg0, arg1; rtx arg0, arg1;
...@@ -6453,13 +6440,13 @@ simplify_giv_expr (loop, x, ext_val, benefit) ...@@ -6453,13 +6440,13 @@ simplify_giv_expr (loop, x, ext_val, benefit)
return 0; return 0;
/* Check for biv or giv. */ /* Check for biv or giv. */
switch (REG_IV_TYPE (REGNO (x))) switch (REG_IV_TYPE (ivs, REGNO (x)))
{ {
case BASIC_INDUCT: case BASIC_INDUCT:
return x; return x;
case GENERAL_INDUCT: case GENERAL_INDUCT:
{ {
struct induction *v = REG_IV_INFO (REGNO (x)); struct induction *v = REG_IV_INFO (ivs, REGNO (x));
/* Form expression from giv and add benefit. Ensure this giv /* Form expression from giv and add benefit. Ensure this giv
can derive another and subtract any needed adjustment if so. */ can derive another and subtract any needed adjustment if so. */
...@@ -6679,6 +6666,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg, ...@@ -6679,6 +6666,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
rtx *ext_val; rtx *ext_val;
rtx *last_consec_insn; rtx *last_consec_insn;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
int count; int count;
enum rtx_code code; enum rtx_code code;
...@@ -6703,8 +6691,8 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg, ...@@ -6703,8 +6691,8 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
v->derive_adjustment = 0; v->derive_adjustment = 0;
v->ext_dependant = NULL_RTX; v->ext_dependant = NULL_RTX;
REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT; REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
REG_IV_INFO (REGNO (dest_reg)) = v; REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
count = VARRAY_INT (regs->n_times_set, REGNO (dest_reg)) - 1; count = VARRAY_INT (regs->n_times_set, REGNO (dest_reg)) - 1;
...@@ -6750,7 +6738,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg, ...@@ -6750,7 +6738,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
&& CONSTANT_P (SET_SRC (set))) && CONSTANT_P (SET_SRC (set)))
continue; continue;
REG_IV_TYPE (REGNO (dest_reg)) = UNKNOWN_INDUCT; REG_IV_TYPE (ivs, REGNO (dest_reg)) = UNKNOWN_INDUCT;
return 0; return 0;
} }
} }
...@@ -7416,10 +7404,12 @@ cmp_recombine_givs_stats (xp, yp) ...@@ -7416,10 +7404,12 @@ cmp_recombine_givs_stats (xp, yp)
Only consider givs that belong to BIV. Only consider givs that belong to BIV.
Return the total number of lifetime ends that have been found. */ Return the total number of lifetime ends that have been found. */
static int static int
find_life_end (x, stats, insn, biv) find_life_end (loop, x, stats, insn, biv)
const struct loop *loop;
rtx x, insn, biv; rtx x, insn, biv;
struct recombine_givs_stats *stats; struct recombine_givs_stats *stats;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
enum rtx_code code; enum rtx_code code;
const char *fmt; const char *fmt;
int i, j; int i, j;
...@@ -7434,9 +7424,9 @@ find_life_end (x, stats, insn, biv) ...@@ -7434,9 +7424,9 @@ find_life_end (x, stats, insn, biv)
if (GET_CODE (reg) == REG) if (GET_CODE (reg) == REG)
{ {
int regno = REGNO (reg); int regno = REGNO (reg);
struct induction *v = REG_IV_INFO (regno); struct induction *v = REG_IV_INFO (ivs, regno);
if (REG_IV_TYPE (regno) == GENERAL_INDUCT if (REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
&& ! v->ignore && ! v->ignore
&& v->src_reg == biv && v->src_reg == biv
&& stats[v->ix].end_luid <= 0) && stats[v->ix].end_luid <= 0)
...@@ -7449,21 +7439,22 @@ find_life_end (x, stats, insn, biv) ...@@ -7449,21 +7439,22 @@ find_life_end (x, stats, insn, biv)
if (stats[v->ix].end_luid == 0) if (stats[v->ix].end_luid == 0)
{ {
stats[v->ix].end_luid = stats[v->ix].start_luid; stats[v->ix].end_luid = stats[v->ix].start_luid;
return 1 + find_life_end (SET_SRC (x), stats, insn, biv); return 1 + find_life_end (loop, SET_SRC (x), stats,
insn, biv);
} }
else if (stats[v->ix].start_luid == INSN_LUID (insn)) else if (stats[v->ix].start_luid == INSN_LUID (insn))
stats[v->ix].end_luid = 0; stats[v->ix].end_luid = 0;
} }
return find_life_end (SET_SRC (x), stats, insn, biv); return find_life_end (loop, SET_SRC (x), stats, insn, biv);
} }
break; break;
} }
case REG: case REG:
{ {
int regno = REGNO (x); int regno = REGNO (x);
struct induction *v = REG_IV_INFO (regno); struct induction *v = REG_IV_INFO (ivs, regno);
if (REG_IV_TYPE (regno) == GENERAL_INDUCT if (REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
&& ! v->ignore && ! v->ignore
&& v->src_reg == biv && v->src_reg == biv
&& stats[v->ix].end_luid == 0) && stats[v->ix].end_luid == 0)
...@@ -7488,11 +7479,11 @@ find_life_end (x, stats, insn, biv) ...@@ -7488,11 +7479,11 @@ find_life_end (x, stats, insn, biv)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
retval += find_life_end (XEXP (x, i), stats, insn, biv); retval += find_life_end (loop, XEXP (x, i), stats, insn, biv);
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
retval += find_life_end (XVECEXP (x, i, j), stats, insn, biv); retval += find_life_end (loop, XVECEXP (x, i, j), stats, insn, biv);
} }
return retval; return retval;
} }
...@@ -7682,7 +7673,8 @@ recombine_givs (loop, bl, unroll_p) ...@@ -7682,7 +7673,8 @@ recombine_givs (loop, bl, unroll_p)
p = PREV_INSN (p); p = PREV_INSN (p);
if (! INSN_P (p)) if (! INSN_P (p))
continue; continue;
ends_need_computing -= find_life_end (PATTERN (p), stats, p, biv); ends_need_computing -= find_life_end (loop, PATTERN (p),
stats, p, biv);
} }
while (ends_need_computing); while (ends_need_computing);
} }
...@@ -7993,6 +7985,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7993,6 +7985,7 @@ check_dbra_loop (loop, insn_count)
{ {
struct loop_info *loop_info = LOOP_INFO (loop); struct loop_info *loop_info = LOOP_INFO (loop);
struct loop_regs *regs = LOOP_REGS (loop); struct loop_regs *regs = LOOP_REGS (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
rtx reg; rtx reg;
rtx jump_label; rtx jump_label;
...@@ -8047,7 +8040,7 @@ check_dbra_loop (loop, insn_count) ...@@ -8047,7 +8040,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 = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_list; bl; bl = bl->next)
{ {
if (bl->biv_count == 1 if (bl->biv_count == 1
&& ! bl->biv->maybe_multiple && ! bl->biv->maybe_multiple
...@@ -8237,7 +8230,7 @@ check_dbra_loop (loop, insn_count) ...@@ -8237,7 +8230,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
+ the_movables.num + compare_and_branch == insn_count) + the_movables.num + compare_and_branch == insn_count)
&& (bl == loop_iv_list && bl->next == 0)) && (bl == ivs->loop_iv_list && bl->next == 0))
|| no_use_except_counting) || no_use_except_counting)
{ {
rtx tem; rtx tem;
...@@ -8536,9 +8529,9 @@ check_dbra_loop (loop, insn_count) ...@@ -8536,9 +8529,9 @@ 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)) >= reg_iv_type->num_elements || (size_t) REGNO (SET_DEST (set)) >= ivs->reg_iv_type->num_elements
|| REG_IV_TYPE (REGNO (SET_DEST (set))) != GENERAL_INDUCT || REG_IV_TYPE (ivs, REGNO (SET_DEST (set))) != GENERAL_INDUCT
|| REG_IV_INFO (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;)
{ {
if (REG_NOTE_KIND (*pnote) == REG_EQUAL if (REG_NOTE_KIND (*pnote) == REG_EQUAL
...@@ -8589,6 +8582,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count) ...@@ -8589,6 +8582,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
int eliminate_p; int eliminate_p;
int threshold, insn_count; int threshold, insn_count;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx reg = bl->biv->dest_reg; rtx reg = bl->biv->dest_reg;
rtx loop_start = loop->start; rtx loop_start = loop->start;
rtx loop_end = loop->end; rtx loop_end = loop->end;
...@@ -8617,8 +8611,8 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count) ...@@ -8617,8 +8611,8 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
unsigned int regno = REGNO (SET_DEST (set)); unsigned int regno = REGNO (SET_DEST (set));
if (regno < max_reg_before_loop if (regno < max_reg_before_loop
&& REG_IV_TYPE (regno) == GENERAL_INDUCT && REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
&& REG_IV_INFO (regno)->src_reg == bl->biv->src_reg) && REG_IV_INFO (ivs, regno)->src_reg == bl->biv->src_reg)
p = last; p = last;
} }
} }
...@@ -9004,7 +8998,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -9004,7 +8998,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
#if 0 #if 0
/* Otherwise the reg compared with had better be a biv. */ /* Otherwise the reg compared with had better be a biv. */
if (GET_CODE (arg) != REG if (GET_CODE (arg) != REG
|| REG_IV_TYPE (REGNO (arg)) != BASIC_INDUCT) || REG_IV_TYPE (ivs, REGNO (arg)) != BASIC_INDUCT)
return 0; return 0;
/* Look for a pair of givs, one for each biv, /* Look for a pair of givs, one for each biv,
...@@ -9016,7 +9010,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -9016,7 +9010,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
if (v->ignore || v->maybe_dead || v->mode != mode) if (v->ignore || v->maybe_dead || v->mode != mode)
continue; continue;
for (tv = reg_biv_class[REGNO (arg)]->giv; tv; tv = tv->next_iv) for (tv = ivs->reg_biv_class[REGNO (arg)]->giv; tv; tv = tv->next_iv)
if (! tv->ignore && ! tv->maybe_dead if (! tv->ignore && ! tv->maybe_dead
&& rtx_equal_p (tv->mult_val, v->mult_val) && rtx_equal_p (tv->mult_val, v->mult_val)
&& rtx_equal_p (tv->add_val, v->add_val) && rtx_equal_p (tv->add_val, v->add_val)
...@@ -9106,14 +9100,15 @@ record_initial (dest, set, data) ...@@ -9106,14 +9100,15 @@ record_initial (dest, set, data)
rtx set; rtx set;
void *data ATTRIBUTE_UNUSED; void *data ATTRIBUTE_UNUSED;
{ {
struct loop_ivs *ivs = (struct loop_ivs *) data;
struct iv_class *bl; struct iv_class *bl;
if (GET_CODE (dest) != REG if (GET_CODE (dest) != REG
|| REGNO (dest) >= max_reg_before_loop || REGNO (dest) >= max_reg_before_loop
|| REG_IV_TYPE (REGNO (dest)) != BASIC_INDUCT) || REG_IV_TYPE (ivs, REGNO (dest)) != BASIC_INDUCT)
return; return;
bl = reg_biv_class[REGNO (dest)]; bl = ivs->reg_biv_class[REGNO (dest)];
/* If this is the first set found, record it. */ /* If this is the first set found, record it. */
if (bl->init_insn == 0) if (bl->init_insn == 0)
...@@ -9614,8 +9609,7 @@ load_mems_and_recount_loop_regs_set (loop, insn_count) ...@@ -9614,8 +9609,7 @@ load_mems_and_recount_loop_regs_set (loop, insn_count)
bzero ((char *) &regs->may_not_optimize->data, nregs * sizeof (char)); bzero ((char *) &regs->may_not_optimize->data, nregs * sizeof (char));
bzero ((char *) &regs->single_usage->data, nregs * sizeof (rtx)); bzero ((char *) &regs->single_usage->data, nregs * sizeof (rtx));
count_loop_regs_set (loop, regs->may_not_optimize, count_loop_regs_set (loop, regs->may_not_optimize, regs->single_usage,
regs->single_usage,
insn_count, nregs); insn_count, nregs);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
......
...@@ -32,6 +32,9 @@ Boston, MA 02111-1307, USA. */ ...@@ -32,6 +32,9 @@ Boston, MA 02111-1307, USA. */
/* Get a pointer to the loop registers structure. */ /* Get a pointer to the loop registers structure. */
#define LOOP_REGS(LOOP) (&LOOP_INFO (loop)->regs) #define LOOP_REGS(LOOP) (&LOOP_INFO (loop)->regs)
/* Get a pointer to the loop induction variables structure. */
#define LOOP_IVS(LOOP) (&LOOP_INFO (loop)->ivs)
/* Get the luid of an insn. Catch the error of trying to reference the LUID /* Get the luid of an insn. Catch the error of trying to reference the LUID
of an insn added during loop, since these don't have LUIDs. */ of an insn added during loop, since these don't have LUIDs. */
...@@ -176,6 +179,34 @@ typedef struct loop_mem_info ...@@ -176,6 +179,34 @@ typedef struct loop_mem_info
} loop_mem_info; } 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;
/* Givs made from biv increments are always splittable for loop
unrolling. Since there is no regscan info for them, we have to
keep track of them separately. */
unsigned int first_increment_giv;
unsigned int last_increment_giv;
};
struct loop_regs struct loop_regs
{ {
...@@ -285,6 +316,8 @@ struct loop_info ...@@ -285,6 +316,8 @@ struct loop_info
rtx first_loop_store_insn; rtx first_loop_store_insn;
/* The registers used the in loop. */ /* The registers used the in loop. */
struct loop_regs regs; struct loop_regs regs;
/* The induction variable information in loop. */
struct loop_ivs ivs;
}; };
/* Definitions used by the basic induction variable discovery code. */ /* Definitions used by the basic induction variable discovery code. */
...@@ -299,18 +332,10 @@ extern unsigned int max_reg_before_loop; ...@@ -299,18 +332,10 @@ 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;
extern varray_type reg_iv_type; #define REG_IV_TYPE(ivs, n) \
extern varray_type reg_iv_info; (*(enum iv_mode *) &VARRAY_INT(ivs->reg_iv_type, (n)))
#define REG_IV_INFO(ivs, n) \
#define REG_IV_TYPE(n) \ (*(struct induction **) &VARRAY_GENERIC_PTR(ivs->reg_iv_info, (n)))
(*(enum iv_mode *) &VARRAY_INT(reg_iv_type, (n)))
#define REG_IV_INFO(n) \
(*(struct induction **) &VARRAY_GENERIC_PTR(reg_iv_info, (n)))
extern struct iv_class **reg_biv_class;
extern struct iv_class *loop_iv_list;
extern unsigned int first_increment_giv, last_increment_giv;
/* 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. */
......
...@@ -201,7 +201,8 @@ static void init_reg_map PARAMS ((struct inline_remap *, int)); ...@@ -201,7 +201,8 @@ static void init_reg_map PARAMS ((struct inline_remap *, int));
static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int)); static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *)); static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *)); static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int, static void copy_loop_body PARAMS ((struct loop *, rtx, rtx,
struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx)); enum unroll_types, rtx, rtx, rtx, rtx));
static int find_splittable_regs PARAMS ((const struct loop *, static int find_splittable_regs PARAMS ((const struct loop *,
enum unroll_types, rtx, int)); enum unroll_types, rtx, int));
...@@ -211,7 +212,7 @@ static int find_splittable_givs PARAMS ((const struct loop *, ...@@ -211,7 +212,7 @@ static int find_splittable_givs PARAMS ((const struct loop *,
static int reg_dead_after_loop PARAMS ((const struct loop *, rtx)); static int reg_dead_after_loop PARAMS ((const struct loop *, rtx));
static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode)); static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
static int verify_addresses PARAMS ((struct induction *, rtx, int)); static int verify_addresses PARAMS ((struct induction *, rtx, int));
static rtx remap_split_bivs PARAMS ((rtx)); static rtx remap_split_bivs PARAMS ((struct loop *, rtx));
static rtx find_common_reg_term PARAMS ((rtx, rtx)); static rtx find_common_reg_term PARAMS ((rtx, rtx));
static rtx subtract_reg_term PARAMS ((rtx, rtx)); static rtx subtract_reg_term PARAMS ((rtx, rtx));
static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx)); static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx));
...@@ -235,6 +236,8 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -235,6 +236,8 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
rtx end_insert_before; rtx end_insert_before;
int strength_reduce_p; int strength_reduce_p;
{ {
struct loop_info *loop_info = LOOP_INFO (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
int i, j; int i, j;
unsigned int r; unsigned int r;
unsigned HOST_WIDE_INT temp; unsigned HOST_WIDE_INT temp;
...@@ -261,7 +264,6 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -261,7 +264,6 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
rtx last_loop_insn; rtx last_loop_insn;
rtx loop_start = loop->start; rtx loop_start = loop->start;
rtx loop_end = loop->end; rtx loop_end = loop->end;
struct loop_info *loop_info = LOOP_INFO (loop);
/* Don't bother unrolling huge loops. Since the minimum factor is /* Don't bother unrolling huge loops. Since the minimum factor is
two, loops greater than one half of MAX_UNROLLED_INSNS will never two, loops greater than one half of MAX_UNROLLED_INSNS will never
...@@ -872,7 +874,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -872,7 +874,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
} }
/* Givs that have been created from multiple biv increments always have /* Givs that have been created from multiple biv increments always have
local registers. */ local registers. */
for (r = first_increment_giv; r <= last_increment_giv; r++) for (r = ivs->first_increment_giv; r <= ivs->last_increment_giv; r++)
{ {
local_regno[r] = 1; local_regno[r] = 1;
if (loop_dump_stream) if (loop_dump_stream)
...@@ -1115,7 +1117,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1115,7 +1117,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
/* None of the copies are the `last_iteration', so just /* None of the copies are the `last_iteration', so just
pass zero for that parameter. */ pass zero for that parameter. */
copy_loop_body (copy_start, copy_end, map, exit_label, 0, copy_loop_body (loop, copy_start, copy_end, map, exit_label, 0,
unroll_type, start_label, loop_end, unroll_type, start_label, loop_end,
loop_start, copy_end); loop_start, copy_end);
} }
...@@ -1193,7 +1195,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1193,7 +1195,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 = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_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;
...@@ -1219,7 +1221,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1219,7 +1221,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
{ {
insn = NEXT_INSN (copy_end); insn = NEXT_INSN (copy_end);
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
PATTERN (insn) = remap_split_bivs (PATTERN (insn)); PATTERN (insn) = remap_split_bivs (loop, PATTERN (insn));
} }
/* For unroll_number times, make a copy of each instruction /* For unroll_number times, make a copy of each instruction
...@@ -1263,7 +1265,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1263,7 +1265,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
LABEL_NUSES (tem)++; LABEL_NUSES (tem)++;
} }
copy_loop_body (copy_start, copy_end, map, exit_label, copy_loop_body (loop, copy_start, copy_end, map, exit_label,
i == unroll_number - 1, unroll_type, start_label, i == unroll_number - 1, unroll_type, start_label,
loop_end, insert_before, insert_before); loop_end, insert_before, insert_before);
} }
...@@ -1707,9 +1709,10 @@ final_reg_note_copy (notes, map) ...@@ -1707,9 +1709,10 @@ final_reg_note_copy (notes, map)
This is very similar to a loop in expand_inline_function. */ This is very similar to a loop in expand_inline_function. */
static void static void
copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
unroll_type, start_label, loop_end, insert_before, unroll_type, start_label, loop_end, insert_before,
copy_notes_from) copy_notes_from)
struct loop *loop;
rtx copy_start, copy_end; rtx copy_start, copy_end;
struct inline_remap *map; struct inline_remap *map;
rtx exit_label; rtx exit_label;
...@@ -1717,6 +1720,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, ...@@ -1717,6 +1720,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
enum unroll_types unroll_type; enum unroll_types unroll_type;
rtx start_label, loop_end, insert_before, copy_notes_from; rtx start_label, loop_end, insert_before, copy_notes_from;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx insn, pattern; rtx insn, pattern;
rtx set, tem, copy = NULL_RTX; rtx set, tem, copy = NULL_RTX;
int dest_reg_was_split, i; int dest_reg_was_split, i;
...@@ -1780,7 +1784,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, ...@@ -1780,7 +1784,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
unsigned int regno = REGNO (SET_DEST (set)); unsigned int regno = REGNO (SET_DEST (set));
v = addr_combined_regs[REGNO (SET_DEST (set))]; v = addr_combined_regs[REGNO (SET_DEST (set))];
bl = reg_biv_class[REGNO (v->src_reg)]; bl = ivs->reg_biv_class[REGNO (v->src_reg)];
/* Although the giv_inc amount is not needed here, we must call /* Although the giv_inc amount is not needed here, we must call
calculate_giv_inc here since it might try to delete the calculate_giv_inc here since it might try to delete the
...@@ -1935,9 +1939,9 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration, ...@@ -1935,9 +1939,9 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
induction entry by find_splittable_regs. */ induction entry by find_splittable_regs. */
if (regno < max_reg_before_loop if (regno < max_reg_before_loop
&& REG_IV_TYPE (regno) == BASIC_INDUCT) && REG_IV_TYPE (ivs, regno) == BASIC_INDUCT)
{ {
giv_src_reg = reg_biv_class[regno]->biv->src_reg; giv_src_reg = ivs->reg_biv_class[regno]->biv->src_reg;
giv_dest_reg = giv_src_reg; giv_dest_reg = giv_src_reg;
} }
...@@ -2458,6 +2462,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2458,6 +2462,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx end_insert_before; rtx end_insert_before;
int unroll_number; int unroll_number;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
struct induction *v; struct induction *v;
rtx increment, tem; rtx increment, tem;
...@@ -2467,7 +2472,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2467,7 +2472,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 = loop_iv_list; bl; bl = bl->next) for (bl = ivs->loop_iv_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. */
...@@ -2651,6 +2656,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2651,6 +2656,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
rtx increment; rtx increment;
int unroll_number; int unroll_number;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct induction *v, *v2; struct induction *v, *v2;
rtx final_value; rtx final_value;
rtx tem; rtx tem;
...@@ -2720,8 +2726,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2720,8 +2726,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
>= INSN_LUID (loop->end))) >= INSN_LUID (loop->end)))
/* Givs made from biv increments are missed by the above test, so /* Givs made from biv increments are missed by the above test, so
test explicitly for them. */ test explicitly for them. */
&& (REGNO (v->dest_reg) < first_increment_giv && (REGNO (v->dest_reg) < ivs->first_increment_giv
|| REGNO (v->dest_reg) > last_increment_giv) || REGNO (v->dest_reg) > ivs->last_increment_giv)
&& ! (final_value = v->final_value)) && ! (final_value = v->final_value))
continue; continue;
...@@ -3084,7 +3090,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -3084,7 +3090,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
{ {
int count = 1; int count = 1;
if (! v->ignore) if (! v->ignore)
count = reg_biv_class[REGNO (v->src_reg)]->biv_count; count = ivs->reg_biv_class[REGNO (v->src_reg)]->biv_count;
if (count > 1 && v->derived_from) if (count > 1 && v->derived_from)
/* In this case, there is one set where the giv insn was and one /* In this case, there is one set where the giv insn was and one
...@@ -3277,6 +3283,7 @@ final_giv_value (loop, v) ...@@ -3277,6 +3283,7 @@ final_giv_value (loop, v)
const struct loop *loop; const struct loop *loop;
struct induction *v; struct induction *v;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
struct iv_class *bl; struct iv_class *bl;
rtx insn; rtx insn;
rtx increment, tem; rtx increment, tem;
...@@ -3284,7 +3291,7 @@ final_giv_value (loop, v) ...@@ -3284,7 +3291,7 @@ final_giv_value (loop, v)
rtx loop_end = loop->end; rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations; unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
bl = reg_biv_class[REGNO (v->src_reg)]; bl = ivs->reg_biv_class[REGNO (v->src_reg)];
/* The final value for givs which depend on reversed bivs must be calculated /* The final value for givs which depend on reversed bivs must be calculated
differently than for ordinary givs. In this case, there is already an differently than for ordinary givs. In this case, there is already an
...@@ -3520,6 +3527,8 @@ unsigned HOST_WIDE_INT ...@@ -3520,6 +3527,8 @@ unsigned HOST_WIDE_INT
loop_iterations (loop) loop_iterations (loop)
struct loop *loop; struct loop *loop;
{ {
struct loop_info *loop_info = LOOP_INFO (loop);
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx comparison, comparison_value; rtx comparison, comparison_value;
rtx iteration_var, initial_value, increment, final_value; rtx iteration_var, initial_value, increment, final_value;
enum rtx_code comparison_code; enum rtx_code comparison_code;
...@@ -3530,7 +3539,6 @@ loop_iterations (loop) ...@@ -3530,7 +3539,6 @@ loop_iterations (loop)
int unsigned_p, compare_dir, final_larger; int unsigned_p, compare_dir, final_larger;
rtx last_loop_insn; rtx last_loop_insn;
rtx reg_term; rtx reg_term;
struct loop_info *loop_info = LOOP_INFO (loop);
struct iv_class *bl; struct iv_class *bl;
loop_info->n_iterations = 0; loop_info->n_iterations = 0;
...@@ -3605,7 +3613,7 @@ loop_iterations (loop) ...@@ -3605,7 +3613,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) >= reg_iv_type->num_elements if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements
&& ! REG_USERVAR_P (iteration_var)) && ! REG_USERVAR_P (iteration_var))
abort (); abort ();
...@@ -3623,7 +3631,7 @@ loop_iterations (loop) ...@@ -3623,7 +3631,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) >= reg_iv_type->num_elements) if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3649,7 +3657,7 @@ loop_iterations (loop) ...@@ -3649,7 +3657,7 @@ loop_iterations (loop)
"Loop iterations: Iteration var not an integer.\n"); "Loop iterations: Iteration var not an integer.\n");
return 0; return 0;
} }
else if (REG_IV_TYPE (REGNO (iteration_var)) == BASIC_INDUCT) else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
{ {
/* When reg_iv_type / reg_iv_info is resized for biv increments /* When reg_iv_type / reg_iv_info is resized for biv increments
that are turned into givs, reg_biv_class is not resized. that are turned into givs, reg_biv_class is not resized.
...@@ -3658,21 +3666,21 @@ loop_iterations (loop) ...@@ -3658,21 +3666,21 @@ loop_iterations (loop)
abort (); abort ();
/* Grab initial value, only useful if it is a constant. */ /* Grab initial value, only useful if it is a constant. */
bl = reg_biv_class[REGNO (iteration_var)]; bl = ivs->reg_biv_class[REGNO (iteration_var)];
initial_value = bl->initial_value; initial_value = bl->initial_value;
increment = biv_total_increment (bl); increment = biv_total_increment (bl);
} }
else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT) else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == GENERAL_INDUCT)
{ {
HOST_WIDE_INT offset = 0; HOST_WIDE_INT offset = 0;
struct induction *v = REG_IV_INFO (REGNO (iteration_var)); struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
rtx biv_initial_value; rtx biv_initial_value;
if (REGNO (v->src_reg) >= max_reg_before_loop) if (REGNO (v->src_reg) >= max_reg_before_loop)
abort (); abort ();
bl = reg_biv_class[REGNO (v->src_reg)]; bl = ivs->reg_biv_class[REGNO (v->src_reg)];
/* Increment value is mult_val times the increment value of the biv. */ /* Increment value is mult_val times the increment value of the biv. */
...@@ -4044,9 +4052,11 @@ loop_iterations (loop) ...@@ -4044,9 +4052,11 @@ loop_iterations (loop)
copying. */ copying. */
static rtx static rtx
remap_split_bivs (x) remap_split_bivs (loop, x)
struct loop *loop;
rtx x; rtx x;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop);
register enum rtx_code code; register enum rtx_code code;
register int i; register int i;
register const char *fmt; register const char *fmt;
...@@ -4073,8 +4083,8 @@ remap_split_bivs (x) ...@@ -4073,8 +4083,8 @@ remap_split_bivs (x)
have to remap those givs also. */ have to remap those givs also. */
#endif #endif
if (REGNO (x) < max_reg_before_loop if (REGNO (x) < max_reg_before_loop
&& REG_IV_TYPE (REGNO (x)) == BASIC_INDUCT) && REG_IV_TYPE (ivs, REGNO (x)) == BASIC_INDUCT)
return reg_biv_class[REGNO (x)]->biv->src_reg; return ivs->reg_biv_class[REGNO (x)]->biv->src_reg;
break; break;
default: default:
...@@ -4085,12 +4095,12 @@ remap_split_bivs (x) ...@@ -4085,12 +4095,12 @@ remap_split_bivs (x)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
XEXP (x, i) = remap_split_bivs (XEXP (x, i)); XEXP (x, i) = remap_split_bivs (loop, XEXP (x, i));
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
{ {
register int j; register int j;
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j) = remap_split_bivs (XVECEXP (x, i, j)); XVECEXP (x, i, j) = remap_split_bivs (loop, XVECEXP (x, i, j));
} }
} }
return x; return x;
......
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