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
This commit is contained in:
parent
1ecd860b28
commit
ed5bb68db3
@ -1,3 +1,20 @@
|
||||
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.
|
||||
|
250
gcc/loop.c
250
gcc/loop.c
@ -78,6 +78,9 @@ static int max_luid;
|
||||
|
||||
static int max_loop_num;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Bound on pseudo register number before loop optimization.
|
||||
A pseudo has valid regscan info if its number is < 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 *,
|
||||
struct loop_regs *));
|
||||
static void add_label_notes PARAMS ((rtx, rtx));
|
||||
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 void strength_reduce PARAMS ((struct loop *, int, int));
|
||||
static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
|
||||
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 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));
|
||||
static void check_final_value PARAMS ((const struct loop *,
|
||||
struct induction *));
|
||||
@ -220,7 +224,8 @@ static rtx express_from_1 PARAMS ((rtx, rtx, rtx));
|
||||
static rtx combine_givs_p PARAMS ((struct induction *, struct induction *));
|
||||
static void combine_givs PARAMS ((struct loop_regs *, struct iv_class *));
|
||||
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));
|
||||
static void recombine_givs PARAMS ((const struct loop *, struct iv_class *,
|
||||
int));
|
||||
@ -1037,7 +1042,7 @@ scan_loop (loop, flags)
|
||||
optimizing for code 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.
|
||||
Change regs->set_in_loop to indicate that those are not actually
|
||||
@ -1349,9 +1354,8 @@ combine_movables (movables, regs)
|
||||
struct movables *movables;
|
||||
struct loop_regs *regs;
|
||||
{
|
||||
int nregs = regs->num;
|
||||
register struct movable *m;
|
||||
char *matched_regs = (char *) xmalloc (nregs);
|
||||
char *matched_regs = (char *) xmalloc (regs->num);
|
||||
enum machine_mode mode;
|
||||
|
||||
/* Regs that are set more than once are not allowed to match
|
||||
@ -1365,7 +1369,7 @@ combine_movables (movables, regs)
|
||||
register struct movable *m1;
|
||||
int regno = m->regno;
|
||||
|
||||
bzero (matched_regs, nregs);
|
||||
bzero (matched_regs, regs->num);
|
||||
matched_regs[regno] = 1;
|
||||
|
||||
/* We want later insns to match the first one. Don't make the first
|
||||
@ -1497,7 +1501,7 @@ static int
|
||||
rtx_equal_for_loop_p (x, y, movables, regs)
|
||||
rtx x, y;
|
||||
struct movables *movables;
|
||||
struct loop_regs * regs;
|
||||
struct loop_regs *regs;
|
||||
{
|
||||
register int i;
|
||||
register int j;
|
||||
@ -1582,8 +1586,8 @@ rtx_equal_for_loop_p (x, y, movables, regs)
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
if (rtx_equal_for_loop_p (XEXP (x, i), XEXP (y, i),
|
||||
movables, regs) == 0)
|
||||
if (rtx_equal_for_loop_p (XEXP (x, i), XEXP (y, i), movables, regs)
|
||||
== 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
@ -1651,14 +1655,14 @@ add_label_notes (x, insns)
|
||||
other throughout. */
|
||||
|
||||
static void
|
||||
move_movables (loop, movables, threshold, insn_count, nregs)
|
||||
move_movables (loop, movables, threshold, insn_count)
|
||||
struct loop *loop;
|
||||
struct movables *movables;
|
||||
int threshold;
|
||||
int insn_count;
|
||||
int nregs;
|
||||
{
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
int nregs = regs->num;
|
||||
rtx new_start = 0;
|
||||
register struct movable *m;
|
||||
register rtx p;
|
||||
@ -3528,34 +3532,6 @@ loop_reg_used_before_p (loop, set, insn)
|
||||
/* Bivs are recognized by `basic_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'. */
|
||||
|
||||
static rtx note_insn;
|
||||
@ -3761,8 +3737,9 @@ strength_reduce (loop, insn_count, flags)
|
||||
{
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx p;
|
||||
/* Temporary list pointers for traversing loop_iv_list. */
|
||||
/* Temporary list pointers for traversing ivs->loop_iv_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
|
||||
@ -3783,12 +3760,12 @@ strength_reduce (loop, insn_count, flags)
|
||||
rtx loop_scan_start = loop->scan_start;
|
||||
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_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info");
|
||||
reg_biv_class = (struct iv_class **)
|
||||
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 *));
|
||||
|
||||
loop_iv_list = 0;
|
||||
ivs->loop_iv_list = 0;
|
||||
addr_placeholder = gen_reg_rtx (Pmode);
|
||||
|
||||
/* Save insn immediately after the loop_end. Insns inserted after loop_end
|
||||
@ -3805,11 +3782,11 @@ strength_reduce (loop, insn_count, flags)
|
||||
|
||||
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. */
|
||||
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. */
|
||||
/* Make sure it is not recognized as a basic induction var: */
|
||||
|| VARRAY_INT (regs->n_times_set, bl->regno) != bl->biv_count
|
||||
@ -3820,12 +3797,12 @@ strength_reduce (loop, insn_count, flags)
|
||||
if (loop_dump_stream)
|
||||
fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
|
||||
bl->regno,
|
||||
(REG_IV_TYPE (bl->regno) != BASIC_INDUCT
|
||||
(REG_IV_TYPE (ivs, bl->regno) != BASIC_INDUCT
|
||||
? "not induction variable"
|
||||
: (! bl->incremented ? "never incremented"
|
||||
: "count error")));
|
||||
|
||||
REG_IV_TYPE (bl->regno) = NOT_BASIC_INDUCT;
|
||||
REG_IV_TYPE (ivs, bl->regno) = NOT_BASIC_INDUCT;
|
||||
*backbl = bl->next;
|
||||
}
|
||||
else
|
||||
@ -3838,7 +3815,7 @@ strength_reduce (loop, insn_count, flags)
|
||||
}
|
||||
|
||||
/* 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
|
||||
strength reduction info available. */
|
||||
@ -3860,7 +3837,7 @@ strength_reduce (loop, insn_count, flags)
|
||||
call_seen = 1;
|
||||
|
||||
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
|
||||
between it and the start of loop. We only care about tests with
|
||||
@ -3871,7 +3848,7 @@ strength_reduce (loop, insn_count, flags)
|
||||
&& (test = get_condition_for_loop (loop, p)) != 0
|
||||
&& GET_CODE (XEXP (test, 0)) == REG
|
||||
&& 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)
|
||||
&& bl->init_insn == 0)
|
||||
{
|
||||
@ -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
|
||||
initial value from any initializing insns set up above. (This is done
|
||||
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 note;
|
||||
@ -3953,7 +3930,7 @@ strength_reduce (loop, insn_count, flags)
|
||||
{
|
||||
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)
|
||||
break;
|
||||
}
|
||||
@ -3989,8 +3966,8 @@ strength_reduce (loop, insn_count, flags)
|
||||
if (loop_dump_stream)
|
||||
fprintf (loop_dump_stream, "is giv of biv %d\n", bl2->regno);
|
||||
/* Let this giv be discovered by the generic code. */
|
||||
REG_IV_TYPE (bl->regno) = UNKNOWN_INDUCT;
|
||||
reg_biv_class[bl->regno] = (struct iv_class *) NULL_PTR;
|
||||
REG_IV_TYPE (ivs, bl->regno) = UNKNOWN_INDUCT;
|
||||
ivs->reg_biv_class[bl->regno] = (struct iv_class *) NULL_PTR;
|
||||
/* We can get better optimization if we can move the giv setting
|
||||
before the first giv use. */
|
||||
if (dominator
|
||||
@ -4054,8 +4031,8 @@ strength_reduce (loop, insn_count, flags)
|
||||
|
||||
/* Get an upper bound for the number of registers
|
||||
we might have after all bivs have been processed. */
|
||||
first_increment_giv = max_reg_num ();
|
||||
for (n_extra_increment = 0, bl = loop_iv_list; bl; bl = bl->next)
|
||||
ivs->first_increment_giv = max_reg_num ();
|
||||
for (n_extra_increment = 0, bl = ivs->loop_iv_list; bl; bl = bl->next)
|
||||
n_extra_increment += bl->biv_count - 1;
|
||||
|
||||
/* If the loop contains volatile memory references do not allow any
|
||||
@ -4063,13 +4040,13 @@ strength_reduce (loop, insn_count, flags)
|
||||
markers. */
|
||||
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. */
|
||||
VARRAY_GROW (reg_iv_type, nregs);
|
||||
VARRAY_GROW (reg_iv_info, nregs);
|
||||
/* Reallocate ivs->reg_iv_type and ivs->reg_iv_info. */
|
||||
VARRAY_GROW (ivs->reg_iv_type, 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;
|
||||
int biv_dead_after_loop = 0;
|
||||
@ -4135,10 +4112,11 @@ strength_reduce (loop, insn_count, flags)
|
||||
old_reg = v->dest_reg;
|
||||
dest_reg = gen_reg_rtx (v->mode);
|
||||
|
||||
/* Unlike reg_iv_type / reg_iv_info, the other three arrays
|
||||
have been allocated with some slop space, so we may not
|
||||
actually need to reallocate them. If we do, the following
|
||||
if statement will be executed just once in this loop. */
|
||||
/* Unlike ivs->reg_iv_type / ivs->reg_iv_info, the other
|
||||
three arrays have been allocated with some slop
|
||||
space, so we may not actually need to reallocate
|
||||
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)
|
||||
{
|
||||
/* Grow all the remaining arrays. */
|
||||
@ -4227,8 +4205,8 @@ strength_reduce (loop, insn_count, flags)
|
||||
VARRAY_INT (regs->n_times_set, new_regno) = 1;
|
||||
VARRAY_CHAR (regs->may_not_optimize, new_regno) = 0;
|
||||
|
||||
REG_IV_TYPE (new_regno) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (new_regno) = v;
|
||||
REG_IV_TYPE (ivs, new_regno) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (ivs, new_regno) = v;
|
||||
|
||||
/* If next_insn has a REG_EQUAL note that mentiones OLD_REG,
|
||||
it must be replaced. */
|
||||
@ -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. */
|
||||
|
||||
@ -4304,7 +4282,7 @@ strength_reduce (loop, insn_count, flags)
|
||||
can be calculated. This must be done after loop_iterations is called,
|
||||
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;
|
||||
|
||||
@ -4320,14 +4298,14 @@ strength_reduce (loop, insn_count, flags)
|
||||
|
||||
/* Create reg_map to hold substitutions for replaceable giv regs.
|
||||
Some givs might have been made from biv increments, so look at
|
||||
reg_iv_type for a suitable size. */
|
||||
reg_map_size = reg_iv_type->num_elements;
|
||||
ivs->reg_iv_type for a suitable size. */
|
||||
reg_map_size = ivs->reg_iv_type->num_elements;
|
||||
reg_map = (rtx *) xcalloc (reg_map_size, sizeof (rtx));
|
||||
|
||||
/* Examine each iv class for feasibility of strength reduction/induction
|
||||
variable elimination. */
|
||||
|
||||
for (bl = loop_iv_list; bl; bl = bl->next)
|
||||
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
|
||||
{
|
||||
struct induction *v;
|
||||
int benefit;
|
||||
@ -4533,20 +4511,20 @@ strength_reduce (loop, insn_count, flags)
|
||||
|
||||
/* Now that we know which givs will be reduced, try to rearrange the
|
||||
combinations to reduce register pressure.
|
||||
recombine_givs calls find_life_end, which needs reg_iv_type and
|
||||
reg_iv_info to be valid for all pseudos. We do the necessary
|
||||
recombine_givs calls find_life_end, which needs ivs->reg_iv_type and
|
||||
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
|
||||
more bivs to process. */
|
||||
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
|
||||
space so that we're not constantly reallocating these arrays. */
|
||||
if (bl->next)
|
||||
nregs += nregs / 4;
|
||||
/* Reallocate reg_iv_type and reg_iv_info. */
|
||||
VARRAY_GROW (reg_iv_type, nregs);
|
||||
VARRAY_GROW (reg_iv_info, nregs);
|
||||
/* Reallocate ivs->reg_iv_type and ivs->reg_iv_info. */
|
||||
VARRAY_GROW (ivs->reg_iv_type, nregs);
|
||||
VARRAY_GROW (ivs->reg_iv_info, nregs);
|
||||
}
|
||||
recombine_givs (loop, bl, flags & LOOP_UNROLL);
|
||||
|
||||
@ -4958,9 +4936,9 @@ strength_reduce (loop, insn_count, flags)
|
||||
fprintf (loop_dump_stream, "\n");
|
||||
|
||||
egress:
|
||||
VARRAY_FREE (reg_iv_type);
|
||||
VARRAY_FREE (reg_iv_info);
|
||||
free (reg_biv_class);
|
||||
VARRAY_FREE (ivs->reg_iv_type);
|
||||
VARRAY_FREE (ivs->reg_iv_info);
|
||||
free (ivs->reg_biv_class);
|
||||
if (reg_map)
|
||||
free (reg_map);
|
||||
}
|
||||
@ -4973,6 +4951,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
|
||||
int not_every_iteration;
|
||||
int maybe_multiple;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx set;
|
||||
rtx dest_reg;
|
||||
rtx inc_val;
|
||||
@ -4986,7 +4965,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
|
||||
dest_reg = SET_DEST (set);
|
||||
if (REGNO (dest_reg) < max_reg_before_loop
|
||||
&& 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),
|
||||
GET_MODE (SET_SRC (set)),
|
||||
@ -4999,12 +4978,12 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
|
||||
struct induction *v
|
||||
= (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);
|
||||
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)
|
||||
REG_IV_TYPE (REGNO (dest_reg)) = NOT_BASIC_INDUCT;
|
||||
REG_IV_TYPE (ivs, REGNO (dest_reg)) = NOT_BASIC_INDUCT;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
@ -5021,6 +5000,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
|
||||
int maybe_multiple;
|
||||
{
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
|
||||
rtx set;
|
||||
/* Look for a general induction variable in a register. */
|
||||
if (GET_CODE (p) == INSN
|
||||
@ -5237,8 +5217,9 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
|
||||
executed exactly once per iteration. */
|
||||
|
||||
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)
|
||||
struct loop *loop;
|
||||
struct induction *v;
|
||||
rtx insn;
|
||||
rtx dest_reg;
|
||||
@ -5248,6 +5229,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
|
||||
int not_every_iteration;
|
||||
int maybe_multiple;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
|
||||
v->insn = insn;
|
||||
@ -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
|
||||
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)
|
||||
{
|
||||
/* Create and initialize new iv_class. */
|
||||
@ -5290,12 +5272,12 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
|
||||
bl->reversed = 0;
|
||||
bl->total_benefit = 0;
|
||||
|
||||
/* Add this class to loop_iv_list. */
|
||||
bl->next = loop_iv_list;
|
||||
loop_iv_list = bl;
|
||||
/* Add this class to ivs->loop_iv_list. */
|
||||
bl->next = ivs->loop_iv_list;
|
||||
ivs->loop_iv_list = bl;
|
||||
|
||||
/* 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. */
|
||||
@ -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;
|
||||
rtx *location;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct induction *b;
|
||||
struct iv_class *bl;
|
||||
rtx set = single_set (insn);
|
||||
@ -5420,13 +5403,13 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
|
||||
if (v->lifetime == 0)
|
||||
v->ignore = 1;
|
||||
|
||||
REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (REGNO (dest_reg)) = v;
|
||||
REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
v->next_iv = bl->giv;
|
||||
@ -5614,10 +5597,11 @@ check_final_value (loop, v)
|
||||
const struct loop *loop;
|
||||
struct induction *v;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
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
|
||||
replaceable above in record_giv. */
|
||||
@ -5761,6 +5745,7 @@ update_giv_derive (loop, p)
|
||||
const struct loop *loop;
|
||||
rtx p;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
struct induction *biv, *giv;
|
||||
rtx tem;
|
||||
@ -5793,7 +5778,7 @@ update_giv_derive (loop, p)
|
||||
subsequent biv update was performed. If this adjustment cannot be done,
|
||||
the giv cannot derive further givs. */
|
||||
|
||||
for (bl = 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)
|
||||
if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
|
||||
|| biv->insn == p)
|
||||
@ -6069,6 +6054,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
|
||||
int *pbenefit;
|
||||
enum machine_mode addr_mode;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx orig_x = x;
|
||||
char *storage;
|
||||
|
||||
@ -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
|
||||
with MULT_VAL == 0. It doesn't matter which BIV we associate this
|
||||
with. */
|
||||
*src_reg = loop_iv_list->biv->dest_reg;
|
||||
*src_reg = ivs->loop_iv_list->biv->dest_reg;
|
||||
*mult_val = const0_rtx;
|
||||
*add_val = x;
|
||||
break;
|
||||
@ -6184,6 +6170,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
|
||||
rtx *ext_val;
|
||||
int *benefit;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
rtx arg0, arg1;
|
||||
@ -6453,13 +6440,13 @@ simplify_giv_expr (loop, x, ext_val, benefit)
|
||||
return 0;
|
||||
|
||||
/* Check for biv or giv. */
|
||||
switch (REG_IV_TYPE (REGNO (x)))
|
||||
switch (REG_IV_TYPE (ivs, REGNO (x)))
|
||||
{
|
||||
case BASIC_INDUCT:
|
||||
return x;
|
||||
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
|
||||
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,
|
||||
rtx *ext_val;
|
||||
rtx *last_consec_insn;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
int count;
|
||||
enum rtx_code code;
|
||||
@ -6703,8 +6691,8 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
|
||||
v->derive_adjustment = 0;
|
||||
v->ext_dependant = NULL_RTX;
|
||||
|
||||
REG_IV_TYPE (REGNO (dest_reg)) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (REGNO (dest_reg)) = v;
|
||||
REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
|
||||
REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
|
||||
|
||||
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,
|
||||
&& CONSTANT_P (SET_SRC (set)))
|
||||
continue;
|
||||
|
||||
REG_IV_TYPE (REGNO (dest_reg)) = UNKNOWN_INDUCT;
|
||||
REG_IV_TYPE (ivs, REGNO (dest_reg)) = UNKNOWN_INDUCT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -7416,10 +7404,12 @@ cmp_recombine_givs_stats (xp, yp)
|
||||
Only consider givs that belong to BIV.
|
||||
Return the total number of lifetime ends that have been found. */
|
||||
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;
|
||||
struct recombine_givs_stats *stats;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
enum rtx_code code;
|
||||
const char *fmt;
|
||||
int i, j;
|
||||
@ -7434,9 +7424,9 @@ find_life_end (x, stats, insn, biv)
|
||||
if (GET_CODE (reg) == 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->src_reg == biv
|
||||
&& stats[v->ix].end_luid <= 0)
|
||||
@ -7449,21 +7439,22 @@ find_life_end (x, stats, insn, biv)
|
||||
if (stats[v->ix].end_luid == 0)
|
||||
{
|
||||
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))
|
||||
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;
|
||||
}
|
||||
case REG:
|
||||
{
|
||||
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->src_reg == biv
|
||||
&& stats[v->ix].end_luid == 0)
|
||||
@ -7488,11 +7479,11 @@ find_life_end (x, stats, insn, biv)
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
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')
|
||||
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;
|
||||
}
|
||||
@ -7682,7 +7673,8 @@ recombine_givs (loop, bl, unroll_p)
|
||||
p = PREV_INSN (p);
|
||||
if (! INSN_P (p))
|
||||
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);
|
||||
}
|
||||
@ -7993,6 +7985,7 @@ check_dbra_loop (loop, insn_count)
|
||||
{
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
struct loop_regs *regs = LOOP_REGS (loop);
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
rtx reg;
|
||||
rtx jump_label;
|
||||
@ -8047,7 +8040,7 @@ check_dbra_loop (loop, insn_count)
|
||||
it will be zero on the last iteration. Also skip if the biv is
|
||||
used between its update and the test insn. */
|
||||
|
||||
for (bl = loop_iv_list; bl; bl = bl->next)
|
||||
for (bl = ivs->loop_iv_list; bl; bl = bl->next)
|
||||
{
|
||||
if (bl->biv_count == 1
|
||||
&& ! bl->biv->maybe_multiple
|
||||
@ -8237,7 +8230,7 @@ check_dbra_loop (loop, insn_count)
|
||||
&& reversible_mem_store
|
||||
&& (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
|
||||
+ 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)
|
||||
{
|
||||
rtx tem;
|
||||
@ -8536,9 +8529,9 @@ check_dbra_loop (loop, insn_count)
|
||||
REG_EQUAL notes should still be correct. */
|
||||
if (! set
|
||||
|| GET_CODE (SET_DEST (set)) != REG
|
||||
|| (size_t) REGNO (SET_DEST (set)) >= reg_iv_type->num_elements
|
||||
|| REG_IV_TYPE (REGNO (SET_DEST (set))) != GENERAL_INDUCT
|
||||
|| REG_IV_INFO (REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
|
||||
|| (size_t) REGNO (SET_DEST (set)) >= ivs->reg_iv_type->num_elements
|
||||
|| 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;)
|
||||
{
|
||||
if (REG_NOTE_KIND (*pnote) == REG_EQUAL
|
||||
@ -8589,6 +8582,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
|
||||
int eliminate_p;
|
||||
int threshold, insn_count;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx reg = bl->biv->dest_reg;
|
||||
rtx loop_start = loop->start;
|
||||
rtx loop_end = loop->end;
|
||||
@ -8617,8 +8611,8 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
|
||||
unsigned int regno = REGNO (SET_DEST (set));
|
||||
|
||||
if (regno < max_reg_before_loop
|
||||
&& REG_IV_TYPE (regno) == GENERAL_INDUCT
|
||||
&& REG_IV_INFO (regno)->src_reg == bl->biv->src_reg)
|
||||
&& REG_IV_TYPE (ivs, regno) == GENERAL_INDUCT
|
||||
&& REG_IV_INFO (ivs, regno)->src_reg == bl->biv->src_reg)
|
||||
p = last;
|
||||
}
|
||||
}
|
||||
@ -9004,7 +8998,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
|
||||
#if 0
|
||||
/* Otherwise the reg compared with had better be a biv. */
|
||||
if (GET_CODE (arg) != REG
|
||||
|| REG_IV_TYPE (REGNO (arg)) != BASIC_INDUCT)
|
||||
|| REG_IV_TYPE (ivs, REGNO (arg)) != BASIC_INDUCT)
|
||||
return 0;
|
||||
|
||||
/* 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)
|
||||
if (v->ignore || v->maybe_dead || v->mode != mode)
|
||||
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
|
||||
&& rtx_equal_p (tv->mult_val, v->mult_val)
|
||||
&& rtx_equal_p (tv->add_val, v->add_val)
|
||||
@ -9106,14 +9100,15 @@ record_initial (dest, set, data)
|
||||
rtx set;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
struct loop_ivs *ivs = (struct loop_ivs *) data;
|
||||
struct iv_class *bl;
|
||||
|
||||
if (GET_CODE (dest) != REG
|
||||
|| REGNO (dest) >= max_reg_before_loop
|
||||
|| REG_IV_TYPE (REGNO (dest)) != BASIC_INDUCT)
|
||||
|| REG_IV_TYPE (ivs, REGNO (dest)) != BASIC_INDUCT)
|
||||
return;
|
||||
|
||||
bl = reg_biv_class[REGNO (dest)];
|
||||
bl = ivs->reg_biv_class[REGNO (dest)];
|
||||
|
||||
/* If this is the first set found, record it. */
|
||||
if (bl->init_insn == 0)
|
||||
@ -9614,8 +9609,7 @@ load_mems_and_recount_loop_regs_set (loop, insn_count)
|
||||
bzero ((char *) ®s->may_not_optimize->data, nregs * sizeof (char));
|
||||
bzero ((char *) ®s->single_usage->data, nregs * sizeof (rtx));
|
||||
|
||||
count_loop_regs_set (loop, regs->may_not_optimize,
|
||||
regs->single_usage,
|
||||
count_loop_regs_set (loop, regs->may_not_optimize, regs->single_usage,
|
||||
insn_count, nregs);
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
|
49
gcc/loop.h
49
gcc/loop.h
@ -32,6 +32,9 @@ Boston, MA 02111-1307, USA. */
|
||||
/* Get a pointer to the loop registers structure. */
|
||||
#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
|
||||
of an insn added during loop, since these don't have LUIDs. */
|
||||
|
||||
@ -176,6 +179,34 @@ typedef struct 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
|
||||
{
|
||||
@ -285,6 +316,8 @@ struct loop_info
|
||||
rtx first_loop_store_insn;
|
||||
/* The registers used the in loop. */
|
||||
struct loop_regs regs;
|
||||
/* The induction variable information in loop. */
|
||||
struct loop_ivs ivs;
|
||||
};
|
||||
|
||||
/* Definitions used by the basic induction variable discovery code. */
|
||||
@ -299,18 +332,10 @@ extern unsigned int max_reg_before_loop;
|
||||
extern struct loop **uid_loop;
|
||||
extern FILE *loop_dump_stream;
|
||||
|
||||
extern varray_type reg_iv_type;
|
||||
extern varray_type reg_iv_info;
|
||||
|
||||
#define REG_IV_TYPE(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;
|
||||
#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)))
|
||||
|
||||
/* Forward declarations for non-static functions declared in loop.c and
|
||||
unroll.c. */
|
||||
|
72
gcc/unroll.c
72
gcc/unroll.c
@ -201,8 +201,9 @@ static void init_reg_map PARAMS ((struct inline_remap *, int));
|
||||
static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
|
||||
static rtx initial_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,
|
||||
enum unroll_types, rtx, rtx, rtx, rtx));
|
||||
static void copy_loop_body PARAMS ((struct loop *, rtx, rtx,
|
||||
struct inline_remap *, rtx, int,
|
||||
enum unroll_types, rtx, rtx, rtx, rtx));
|
||||
static int find_splittable_regs PARAMS ((const struct loop *,
|
||||
enum unroll_types, rtx, int));
|
||||
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 rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
|
||||
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 subtract_reg_term PARAMS ((rtx, 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)
|
||||
rtx end_insert_before;
|
||||
int strength_reduce_p;
|
||||
{
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
int i, j;
|
||||
unsigned int r;
|
||||
unsigned HOST_WIDE_INT temp;
|
||||
@ -261,7 +264,6 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
|
||||
rtx last_loop_insn;
|
||||
rtx loop_start = loop->start;
|
||||
rtx loop_end = loop->end;
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
|
||||
/* Don't bother unrolling huge loops. Since the minimum factor is
|
||||
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)
|
||||
}
|
||||
/* Givs that have been created from multiple biv increments always have
|
||||
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;
|
||||
if (loop_dump_stream)
|
||||
@ -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
|
||||
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,
|
||||
loop_start, copy_end);
|
||||
}
|
||||
@ -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
|
||||
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)
|
||||
map->reg_map[bl->regno] = bl->biv->src_reg;
|
||||
@ -1219,7 +1221,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
|
||||
{
|
||||
insn = NEXT_INSN (copy_end);
|
||||
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
|
||||
@ -1263,7 +1265,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
|
||||
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,
|
||||
loop_end, insert_before, insert_before);
|
||||
}
|
||||
@ -1707,9 +1709,10 @@ final_reg_note_copy (notes, map)
|
||||
This is very similar to a loop in expand_inline_function. */
|
||||
|
||||
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,
|
||||
copy_notes_from)
|
||||
struct loop *loop;
|
||||
rtx copy_start, copy_end;
|
||||
struct inline_remap *map;
|
||||
rtx exit_label;
|
||||
@ -1717,6 +1720,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
|
||||
enum unroll_types unroll_type;
|
||||
rtx start_label, loop_end, insert_before, copy_notes_from;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx insn, pattern;
|
||||
rtx set, tem, copy = NULL_RTX;
|
||||
int dest_reg_was_split, i;
|
||||
@ -1780,7 +1784,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
|
||||
unsigned int regno = 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
|
||||
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,
|
||||
induction entry by find_splittable_regs. */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2458,6 +2462,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
|
||||
rtx end_insert_before;
|
||||
int unroll_number;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
struct induction *v;
|
||||
rtx increment, tem;
|
||||
@ -2467,7 +2472,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
|
||||
rtx loop_start = loop->start;
|
||||
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,
|
||||
otherwise we can not calculate the split values. */
|
||||
@ -2651,6 +2656,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
rtx increment;
|
||||
int unroll_number;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct induction *v, *v2;
|
||||
rtx final_value;
|
||||
rtx tem;
|
||||
@ -2720,8 +2726,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
>= INSN_LUID (loop->end)))
|
||||
/* Givs made from biv increments are missed by the above test, so
|
||||
test explicitly for them. */
|
||||
&& (REGNO (v->dest_reg) < first_increment_giv
|
||||
|| REGNO (v->dest_reg) > last_increment_giv)
|
||||
&& (REGNO (v->dest_reg) < ivs->first_increment_giv
|
||||
|| REGNO (v->dest_reg) > ivs->last_increment_giv)
|
||||
&& ! (final_value = v->final_value))
|
||||
continue;
|
||||
|
||||
@ -3084,7 +3090,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
|
||||
{
|
||||
int count = 1;
|
||||
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)
|
||||
/* In this case, there is one set where the giv insn was and one
|
||||
@ -3277,6 +3283,7 @@ final_giv_value (loop, v)
|
||||
const struct loop *loop;
|
||||
struct induction *v;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
struct iv_class *bl;
|
||||
rtx insn;
|
||||
rtx increment, tem;
|
||||
@ -3284,7 +3291,7 @@ final_giv_value (loop, v)
|
||||
rtx loop_end = loop->end;
|
||||
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
|
||||
differently than for ordinary givs. In this case, there is already an
|
||||
@ -3520,6 +3527,8 @@ unsigned HOST_WIDE_INT
|
||||
loop_iterations (loop)
|
||||
struct loop *loop;
|
||||
{
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
rtx comparison, comparison_value;
|
||||
rtx iteration_var, initial_value, increment, final_value;
|
||||
enum rtx_code comparison_code;
|
||||
@ -3530,7 +3539,6 @@ loop_iterations (loop)
|
||||
int unsigned_p, compare_dir, final_larger;
|
||||
rtx last_loop_insn;
|
||||
rtx reg_term;
|
||||
struct loop_info *loop_info = LOOP_INFO (loop);
|
||||
struct iv_class *bl;
|
||||
|
||||
loop_info->n_iterations = 0;
|
||||
@ -3605,7 +3613,7 @@ loop_iterations (loop)
|
||||
will propagate a new pseudo into the old iteration register but
|
||||
this will be marked by having the REG_USERVAR_P bit set. */
|
||||
|
||||
if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements
|
||||
if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements
|
||||
&& ! REG_USERVAR_P (iteration_var))
|
||||
abort ();
|
||||
|
||||
@ -3623,7 +3631,7 @@ loop_iterations (loop)
|
||||
|
||||
/* If this is a new register, can't handle it since we don't have any
|
||||
reg_iv_type entry for it. */
|
||||
if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
|
||||
if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements)
|
||||
{
|
||||
if (loop_dump_stream)
|
||||
fprintf (loop_dump_stream,
|
||||
@ -3649,7 +3657,7 @@ loop_iterations (loop)
|
||||
"Loop iterations: Iteration var not an integer.\n");
|
||||
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
|
||||
that are turned into givs, reg_biv_class is not resized.
|
||||
@ -3658,21 +3666,21 @@ loop_iterations (loop)
|
||||
abort ();
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
struct induction *v = REG_IV_INFO (REGNO (iteration_var));
|
||||
struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
|
||||
rtx biv_initial_value;
|
||||
|
||||
if (REGNO (v->src_reg) >= max_reg_before_loop)
|
||||
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. */
|
||||
|
||||
@ -4044,9 +4052,11 @@ loop_iterations (loop)
|
||||
copying. */
|
||||
|
||||
static rtx
|
||||
remap_split_bivs (x)
|
||||
remap_split_bivs (loop, x)
|
||||
struct loop *loop;
|
||||
rtx x;
|
||||
{
|
||||
struct loop_ivs *ivs = LOOP_IVS (loop);
|
||||
register enum rtx_code code;
|
||||
register int i;
|
||||
register const char *fmt;
|
||||
@ -4073,8 +4083,8 @@ remap_split_bivs (x)
|
||||
have to remap those givs also. */
|
||||
#endif
|
||||
if (REGNO (x) < max_reg_before_loop
|
||||
&& REG_IV_TYPE (REGNO (x)) == BASIC_INDUCT)
|
||||
return reg_biv_class[REGNO (x)]->biv->src_reg;
|
||||
&& REG_IV_TYPE (ivs, REGNO (x)) == BASIC_INDUCT)
|
||||
return ivs->reg_biv_class[REGNO (x)]->biv->src_reg;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4085,12 +4095,12 @@ remap_split_bivs (x)
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
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')
|
||||
{
|
||||
register int 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;
|
||||
|
Loading…
Reference in New Issue
Block a user