loop.c (n_times_set, [...]): Convert to varrays.
* loop.c (n_times_set, n_times_used, may_not_optimize, reg_single_usage): Convert to varrays. All uses changed. (insert_loop_mem): Return a value. (scan_loop): Tweak AVOID_CC_MODE_COPIES code. (load_mems_and_recount_loop_regs_set): Likewise. Grow the arrays, if necessary. From-SVN: r21986
This commit is contained in:
parent
6e1488073b
commit
8deb8e2ccc
2 changed files with 136 additions and 97 deletions
|
@ -1,3 +1,12 @@
|
|||
Tue Aug 25 10:57:41 1998 Mark Mitchell <mark@markmitchell.com>
|
||||
|
||||
* loop.c (n_times_set, n_times_used, may_not_optimize,
|
||||
reg_single_usage): Convert to varrays. All uses changed.
|
||||
(insert_loop_mem): Return a value.
|
||||
(scan_loop): Tweak AVOID_CC_MODE_COPIES code.
|
||||
(load_mems_and_recount_loop_regs_set): Likewise. Grow the arrays, if
|
||||
necessary.
|
||||
|
||||
Tue Aug 25 23:57:12 1998 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* From Alexandre:
|
||||
|
|
224
gcc/loop.c
224
gcc/loop.c
|
@ -168,18 +168,18 @@ static rtx loop_continue;
|
|||
Therefore, at all times, == 0 indicates an invariant register;
|
||||
< 0 a conditionally invariant one. */
|
||||
|
||||
static int *n_times_set;
|
||||
static varray_type n_times_set;
|
||||
|
||||
/* Original value of n_times_set; same except that this value
|
||||
is not set negative for a reg whose sets have been made candidates
|
||||
and not set to 0 for a reg that is moved. */
|
||||
|
||||
static int *n_times_used;
|
||||
static varray_type n_times_used;
|
||||
|
||||
/* Index by register number, 1 indicates that the register
|
||||
cannot be moved or strength reduced. */
|
||||
|
||||
static char *may_not_optimize;
|
||||
static varray_type may_not_optimize;
|
||||
|
||||
/* Nonzero means reg N has already been moved out of one loop.
|
||||
This reduces the desire to move it out of another. */
|
||||
|
@ -306,7 +306,8 @@ static int reg_in_basic_block_p PROTO((rtx, rtx));
|
|||
static int consec_sets_invariant_p PROTO((rtx, int, rtx));
|
||||
static rtx libcall_other_reg PROTO((rtx, rtx));
|
||||
static int labels_in_range_p PROTO((rtx, int));
|
||||
static void count_loop_regs_set PROTO((rtx, rtx, char *, rtx *, int *, int));
|
||||
static void count_loop_regs_set PROTO((rtx, rtx, varray_type, varray_type,
|
||||
int *, int));
|
||||
static void note_addr_stored PROTO((rtx, rtx));
|
||||
static int loop_reg_used_before_p PROTO((rtx, rtx, rtx, rtx, rtx));
|
||||
static void scan_loop PROTO((rtx, rtx, int));
|
||||
|
@ -324,7 +325,7 @@ static void add_label_notes PROTO((rtx, rtx));
|
|||
static void move_movables PROTO((struct movable *, int, int, rtx, rtx, int));
|
||||
static int count_nonfixed_reads PROTO((rtx));
|
||||
static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx, int));
|
||||
static void find_single_use_in_loop PROTO((rtx, rtx, rtx *));
|
||||
static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
|
||||
static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
|
||||
static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx));
|
||||
static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, int, int));
|
||||
|
@ -348,7 +349,8 @@ static void record_initial PROTO((rtx, rtx));
|
|||
static void update_reg_last_use PROTO((rtx, rtx));
|
||||
static rtx next_insn_in_loop PROTO((rtx, rtx, rtx, rtx));
|
||||
static void load_mems_and_recount_loop_regs_set PROTO((rtx, rtx, rtx,
|
||||
rtx, rtx *, int *));
|
||||
rtx, varray_type,
|
||||
int *));
|
||||
static void load_mems PROTO((rtx, rtx, rtx, rtx));
|
||||
static int insert_loop_mem PROTO((rtx *, void *));
|
||||
static int replace_loop_mem PROTO((rtx *, void *));
|
||||
|
@ -678,7 +680,7 @@ scan_loop (loop_start, end, unroll_p)
|
|||
/* If we have calls, contains the insn in which a register was used
|
||||
if it was used exactly once; contains const0_rtx if it was used more
|
||||
than once. */
|
||||
rtx *reg_single_usage = 0;
|
||||
varray_type reg_single_usage = 0;
|
||||
/* Nonzero if we are scanning instructions in a sub-loop. */
|
||||
int loop_depth = 0;
|
||||
int nregs;
|
||||
|
@ -757,40 +759,42 @@ scan_loop (loop_start, end, unroll_p)
|
|||
}
|
||||
|
||||
/* Count number of times each reg is set during this loop.
|
||||
Set may_not_optimize[I] if it is not safe to move out
|
||||
Set VARRAY_CHAR (may_not_optimize, I) if it is not safe to move out
|
||||
the setting of register I. If this loop has calls, set
|
||||
reg_single_usage[I]. */
|
||||
VARRAY_RTX (reg_single_usage, I). */
|
||||
|
||||
/* Allocate extra space for REGS that might be created by
|
||||
load_mems and move_movables. */
|
||||
nregs = max_reg_num () + loop_mems_idx + 100;
|
||||
n_times_set = (int *) alloca (nregs * sizeof (int));
|
||||
n_times_used = (int *) alloca (nregs * sizeof (int));
|
||||
may_not_optimize = (char *) alloca (nregs);
|
||||
bzero ((char *) n_times_set, nregs * sizeof (int));
|
||||
bzero (may_not_optimize, nregs);
|
||||
load_mems. We allocate a little extra slop as well, in the hopes
|
||||
that even after the moving of movables creates some new registers
|
||||
we won't have to reallocate these arrays. However, we do grow
|
||||
the arrays, if necessary, in load_mems_recount_loop_regs_set. */
|
||||
nregs = max_reg_num () + loop_mems_idx + 16;
|
||||
VARRAY_INT_INIT (n_times_set, nregs, "n_times_set");
|
||||
VARRAY_INT_INIT (n_times_used, nregs, "n_times_used");
|
||||
VARRAY_CHAR_INIT (may_not_optimize, nregs, "may_not_optimize");
|
||||
|
||||
if (loop_has_call)
|
||||
{
|
||||
reg_single_usage = (rtx *) alloca (nregs * sizeof (rtx));
|
||||
bzero ((char *) reg_single_usage, nregs * sizeof (rtx));
|
||||
}
|
||||
VARRAY_RTX_INIT (reg_single_usage, nregs, "reg_single_usage");
|
||||
|
||||
count_loop_regs_set (loop_top ? loop_top : loop_start, end,
|
||||
may_not_optimize, reg_single_usage, &insn_count, nregs);
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
may_not_optimize[i] = 1, n_times_set[i] = 1;
|
||||
{
|
||||
VARRAY_CHAR (may_not_optimize, i) = 1;
|
||||
VARRAY_INT (n_times_set, i) = 1;
|
||||
}
|
||||
|
||||
#ifdef AVOID_CCMODE_COPIES
|
||||
/* Don't try to move insns which set CC registers if we should not
|
||||
create CCmode register copies. */
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < nregs - loop_mems_idx; i++)
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
|
||||
if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
|
||||
may_not_optimize[i] = 1;
|
||||
VARRAY_CHAR (may_not_optimize, i) = 1;
|
||||
#endif
|
||||
|
||||
bcopy ((char *) n_times_set, (char *) n_times_used, nregs * sizeof (int));
|
||||
bcopy ((char *) &n_times_set->data,
|
||||
(char *) &n_times_used->data, nregs * sizeof (int));
|
||||
|
||||
if (loop_dump_stream)
|
||||
{
|
||||
|
@ -828,7 +832,7 @@ scan_loop (loop_start, end, unroll_p)
|
|||
if (GET_CODE (p) == INSN
|
||||
&& (set = single_set (p))
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
&& ! may_not_optimize[REGNO (SET_DEST (set))])
|
||||
&& ! VARRAY_CHAR (may_not_optimize, REGNO (SET_DEST (set))))
|
||||
{
|
||||
int tem1 = 0;
|
||||
int tem2 = 0;
|
||||
|
@ -884,11 +888,13 @@ scan_loop (loop_start, end, unroll_p)
|
|||
else if ((tem = invariant_p (src))
|
||||
&& (dependencies == 0
|
||||
|| (tem2 = invariant_p (dependencies)) != 0)
|
||||
&& (n_times_set[REGNO (SET_DEST (set))] == 1
|
||||
&& (VARRAY_INT (n_times_set,
|
||||
REGNO (SET_DEST (set))) == 1
|
||||
|| (tem1
|
||||
= consec_sets_invariant_p (SET_DEST (set),
|
||||
n_times_set[REGNO (SET_DEST (set))],
|
||||
p)))
|
||||
= consec_sets_invariant_p
|
||||
(SET_DEST (set),
|
||||
VARRAY_INT (n_times_set, REGNO (SET_DEST (set))),
|
||||
p)))
|
||||
/* If the insn can cause a trap (such as divide by zero),
|
||||
can't move it unless it's guaranteed to be executed
|
||||
once loop is entered. Even a function call might
|
||||
|
@ -914,12 +920,12 @@ scan_loop (loop_start, end, unroll_p)
|
|||
Don't do this if P has a REG_RETVAL note or if we have
|
||||
SMALL_REGISTER_CLASSES and SET_SRC is a hard register. */
|
||||
|
||||
if (reg_single_usage && reg_single_usage[regno] != 0
|
||||
&& reg_single_usage[regno] != const0_rtx
|
||||
if (reg_single_usage && VARRAY_RTX (reg_single_usage, regno) != 0
|
||||
&& VARRAY_RTX (reg_single_usage, regno) != const0_rtx
|
||||
&& REGNO_FIRST_UID (regno) == INSN_UID (p)
|
||||
&& (REGNO_LAST_UID (regno)
|
||||
== INSN_UID (reg_single_usage[regno]))
|
||||
&& n_times_set[REGNO (SET_DEST (set))] == 1
|
||||
== INSN_UID (VARRAY_RTX (reg_single_usage, regno)))
|
||||
&& VARRAY_INT (n_times_set, regno) == 1
|
||||
&& ! side_effects_p (SET_SRC (set))
|
||||
&& ! find_reg_note (p, REG_RETVAL, NULL_RTX)
|
||||
&& (! SMALL_REGISTER_CLASSES
|
||||
|
@ -929,22 +935,25 @@ scan_loop (loop_start, end, unroll_p)
|
|||
a call-clobbered register and the life of REGNO
|
||||
might span a call. */
|
||||
&& ! modified_between_p (SET_SRC (set), p,
|
||||
reg_single_usage[regno])
|
||||
&& no_labels_between_p (p, reg_single_usage[regno])
|
||||
VARRAY_RTX
|
||||
(reg_single_usage, regno))
|
||||
&& no_labels_between_p (p, VARRAY_RTX (reg_single_usage, regno))
|
||||
&& validate_replace_rtx (SET_DEST (set), SET_SRC (set),
|
||||
reg_single_usage[regno]))
|
||||
VARRAY_RTX
|
||||
(reg_single_usage, regno)))
|
||||
{
|
||||
/* Replace any usage in a REG_EQUAL note. Must copy the
|
||||
new source, so that we don't get rtx sharing between the
|
||||
SET_SOURCE and REG_NOTES of insn p. */
|
||||
REG_NOTES (reg_single_usage[regno])
|
||||
= replace_rtx (REG_NOTES (reg_single_usage[regno]),
|
||||
REG_NOTES (VARRAY_RTX (reg_single_usage, regno))
|
||||
= replace_rtx (REG_NOTES (VARRAY_RTX
|
||||
(reg_single_usage, regno)),
|
||||
SET_DEST (set), copy_rtx (SET_SRC (set)));
|
||||
|
||||
PUT_CODE (p, NOTE);
|
||||
NOTE_LINE_NUMBER (p) = NOTE_INSN_DELETED;
|
||||
NOTE_SOURCE_FILE (p) = 0;
|
||||
n_times_set[regno] = 0;
|
||||
VARRAY_INT (n_times_set, regno) = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -955,7 +964,8 @@ scan_loop (loop_start, end, unroll_p)
|
|||
m->dependencies = dependencies;
|
||||
m->set_dest = SET_DEST (set);
|
||||
m->force = 0;
|
||||
m->consec = n_times_set[REGNO (SET_DEST (set))] - 1;
|
||||
m->consec = VARRAY_INT (n_times_set,
|
||||
REGNO (SET_DEST (set))) - 1;
|
||||
m->done = 0;
|
||||
m->forces = 0;
|
||||
m->partial = 0;
|
||||
|
@ -972,10 +982,10 @@ scan_loop (loop_start, end, unroll_p)
|
|||
m->match = 0;
|
||||
m->lifetime = (uid_luid[REGNO_LAST_UID (regno)]
|
||||
- uid_luid[REGNO_FIRST_UID (regno)]);
|
||||
m->savings = n_times_used[regno];
|
||||
m->savings = VARRAY_INT (n_times_used, regno);
|
||||
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
m->savings += libcall_benefit (p);
|
||||
n_times_set[regno] = move_insn ? -2 : -1;
|
||||
VARRAY_INT (n_times_set, regno) = move_insn ? -2 : -1;
|
||||
/* Add M to the end of the chain MOVABLES. */
|
||||
if (movables == 0)
|
||||
movables = m;
|
||||
|
@ -1034,7 +1044,7 @@ scan_loop (loop_start, end, unroll_p)
|
|||
&& !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
|
||||
{
|
||||
register int regno = REGNO (SET_DEST (set));
|
||||
if (n_times_set[regno] == 2)
|
||||
if (VARRAY_INT (n_times_set, regno) == 2)
|
||||
{
|
||||
register struct movable *m;
|
||||
m = (struct movable *) alloca (sizeof (struct movable));
|
||||
|
@ -1084,7 +1094,7 @@ scan_loop (loop_start, end, unroll_p)
|
|||
m->lifetime = (uid_luid[REGNO_LAST_UID (regno)]
|
||||
- uid_luid[REGNO_FIRST_UID (regno)]);
|
||||
m->savings = 1;
|
||||
n_times_set[regno] = -1;
|
||||
VARRAY_INT (n_times_set, regno) = -1;
|
||||
/* Add M to the end of the chain MOVABLES. */
|
||||
if (movables == 0)
|
||||
movables = m;
|
||||
|
@ -1161,8 +1171,8 @@ scan_loop (loop_start, end, unroll_p)
|
|||
/* Now candidates that still are negative are those not moved.
|
||||
Change n_times_set to indicate that those are not actually invariant. */
|
||||
for (i = 0; i < nregs; i++)
|
||||
if (n_times_set[i] < 0)
|
||||
n_times_set[i] = n_times_used[i];
|
||||
if (VARRAY_INT (n_times_set, i) < 0)
|
||||
VARRAY_INT (n_times_set, i) = VARRAY_INT (n_times_used, i);
|
||||
|
||||
/* Now that we've moved some things out of the loop, we able to
|
||||
hoist even more memory references. There's no need to pass
|
||||
|
@ -1177,6 +1187,11 @@ scan_loop (loop_start, end, unroll_p)
|
|||
strength_reduce (scan_start, end, loop_top,
|
||||
insn_count, loop_start, end, unroll_p);
|
||||
}
|
||||
|
||||
VARRAY_FREE (n_times_set);
|
||||
VARRAY_FREE (n_times_used);
|
||||
VARRAY_FREE (may_not_optimize);
|
||||
VARRAY_FREE (reg_single_usage);
|
||||
}
|
||||
|
||||
/* Add elements to *OUTPUT to record all the pseudo-regs
|
||||
|
@ -1450,7 +1465,7 @@ combine_movables (movables, nregs)
|
|||
/* Perhaps testing m->consec_sets would be more appropriate here? */
|
||||
|
||||
for (m = movables; m; m = m->next)
|
||||
if (m->match == 0 && n_times_used[m->regno] == 1 && !m->partial)
|
||||
if (m->match == 0 && VARRAY_INT (n_times_used, m->regno) == 1 && !m->partial)
|
||||
{
|
||||
register struct movable *m1;
|
||||
int regno = m->regno;
|
||||
|
@ -1461,7 +1476,7 @@ combine_movables (movables, nregs)
|
|||
/* We want later insns to match the first one. Don't make the first
|
||||
one match any later ones. So start this loop at m->next. */
|
||||
for (m1 = m->next; m1; m1 = m1->next)
|
||||
if (m != m1 && m1->match == 0 && n_times_used[m1->regno] == 1
|
||||
if (m != m1 && m1->match == 0 && VARRAY_INT (n_times_used, m1->regno) == 1
|
||||
/* A reg used outside the loop mustn't be eliminated. */
|
||||
&& !m1->global
|
||||
/* A reg used for zero-extending mustn't be eliminated. */
|
||||
|
@ -1598,7 +1613,7 @@ rtx_equal_for_loop_p (x, y, movables)
|
|||
|
||||
/* If we have a register and a constant, they may sometimes be
|
||||
equal. */
|
||||
if (GET_CODE (x) == REG && n_times_set[REGNO (x)] == -2
|
||||
if (GET_CODE (x) == REG && VARRAY_INT (n_times_set, REGNO (x)) == -2
|
||||
&& CONSTANT_P (y))
|
||||
{
|
||||
for (m = movables; m; m = m->next)
|
||||
|
@ -1606,7 +1621,7 @@ rtx_equal_for_loop_p (x, y, movables)
|
|||
&& rtx_equal_p (m->set_src, y))
|
||||
return 1;
|
||||
}
|
||||
else if (GET_CODE (y) == REG && n_times_set[REGNO (y)] == -2
|
||||
else if (GET_CODE (y) == REG && VARRAY_INT (n_times_set, REGNO (y)) == -2
|
||||
&& CONSTANT_P (x))
|
||||
{
|
||||
for (m = movables; m; m = m->next)
|
||||
|
@ -1837,7 +1852,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
|
|||
|| flag_move_all_movables
|
||||
|| (threshold * savings * m->lifetime) >= insn_count
|
||||
|| (m->forces && m->forces->done
|
||||
&& n_times_used[m->forces->regno] == 1))
|
||||
&& VARRAY_INT (n_times_used, m->forces->regno) == 1))
|
||||
{
|
||||
int count;
|
||||
register struct movable *m1;
|
||||
|
@ -2128,7 +2143,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
|
|||
|
||||
/* The reg set here is now invariant. */
|
||||
if (! m->partial)
|
||||
n_times_set[regno] = 0;
|
||||
VARRAY_INT (n_times_set, regno) = 0;
|
||||
|
||||
m->done = 1;
|
||||
|
||||
|
@ -2185,7 +2200,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
|
|||
/* The reg merged here is now invariant,
|
||||
if the reg it matches is invariant. */
|
||||
if (! m->partial)
|
||||
n_times_set[m1->regno] = 0;
|
||||
VARRAY_INT (n_times_set, m1->regno) = 0;
|
||||
}
|
||||
}
|
||||
else if (loop_dump_stream)
|
||||
|
@ -3087,10 +3102,10 @@ invariant_p (x)
|
|||
&& REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
|
||||
return 0;
|
||||
|
||||
if (n_times_set[REGNO (x)] < 0)
|
||||
if (VARRAY_INT (n_times_set, REGNO (x)) < 0)
|
||||
return 2;
|
||||
|
||||
return n_times_set[REGNO (x)] == 0;
|
||||
return VARRAY_INT (n_times_set, REGNO (x)) == 0;
|
||||
|
||||
case MEM:
|
||||
/* Volatile memory references must be rejected. Do this before
|
||||
|
@ -3178,7 +3193,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
|
|||
rtx temp;
|
||||
/* Number of sets we have to insist on finding after INSN. */
|
||||
int count = n_sets - 1;
|
||||
int old = n_times_set[regno];
|
||||
int old = VARRAY_INT (n_times_set, regno);
|
||||
int value = 0;
|
||||
int this;
|
||||
|
||||
|
@ -3186,7 +3201,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
|
|||
if (n_sets == 127)
|
||||
return 0;
|
||||
|
||||
n_times_set[regno] = 0;
|
||||
VARRAY_INT (n_times_set, regno) = 0;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
|
@ -3225,12 +3240,12 @@ consec_sets_invariant_p (reg, n_sets, insn)
|
|||
count--;
|
||||
else if (code != NOTE)
|
||||
{
|
||||
n_times_set[regno] = old;
|
||||
VARRAY_INT (n_times_set, regno) = old;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
n_times_set[regno] = old;
|
||||
VARRAY_INT (n_times_set, regno) = old;
|
||||
/* If invariant_p ever returned 2, we return 2. */
|
||||
return 1 + (value & 2);
|
||||
}
|
||||
|
@ -3276,15 +3291,16 @@ static void
|
|||
find_single_use_in_loop (insn, x, usage)
|
||||
rtx insn;
|
||||
rtx x;
|
||||
rtx *usage;
|
||||
varray_type usage;
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
char *fmt = GET_RTX_FORMAT (code);
|
||||
int i, j;
|
||||
|
||||
if (code == REG)
|
||||
usage[REGNO (x)]
|
||||
= (usage[REGNO (x)] != 0 && usage[REGNO (x)] != insn)
|
||||
VARRAY_RTX (usage, REGNO (x))
|
||||
= (VARRAY_RTX (usage, REGNO (x)) != 0
|
||||
&& VARRAY_RTX (usage, REGNO (x)) != insn)
|
||||
? const0_rtx : insn;
|
||||
|
||||
else if (code == SET)
|
||||
|
@ -3327,8 +3343,8 @@ find_single_use_in_loop (insn, x, usage)
|
|||
static void
|
||||
count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
||||
register rtx from, to;
|
||||
char *may_not_move;
|
||||
rtx *single_usage;
|
||||
varray_type may_not_move;
|
||||
varray_type single_usage;
|
||||
int *count_ptr;
|
||||
int nregs;
|
||||
{
|
||||
|
@ -3358,7 +3374,7 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
|||
&& GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
|
||||
/* Don't move a reg that has an explicit clobber.
|
||||
We might do so sometimes, but it's not worth the pain. */
|
||||
may_not_move[REGNO (XEXP (PATTERN (insn), 0))] = 1;
|
||||
VARRAY_CHAR (may_not_move, REGNO (XEXP (PATTERN (insn), 0))) = 1;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET
|
||||
|| GET_CODE (PATTERN (insn)) == CLOBBER)
|
||||
|
@ -3376,16 +3392,17 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
|||
in current basic block, and it was set before,
|
||||
it must be set in two basic blocks, so it cannot
|
||||
be moved out of the loop. */
|
||||
if (n_times_set[regno] > 0 && last_set[regno] == 0)
|
||||
may_not_move[regno] = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) > 0
|
||||
&& last_set[regno] == 0)
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
/* If this is not first setting in current basic block,
|
||||
see if reg was used in between previous one and this.
|
||||
If so, neither one can be moved. */
|
||||
if (last_set[regno] != 0
|
||||
&& reg_used_between_p (dest, last_set[regno], insn))
|
||||
may_not_move[regno] = 1;
|
||||
if (n_times_set[regno] < 127)
|
||||
++n_times_set[regno];
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) < 127)
|
||||
++VARRAY_INT (n_times_set, regno);
|
||||
last_set[regno] = insn;
|
||||
}
|
||||
}
|
||||
|
@ -3398,7 +3415,7 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
|||
if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
|
||||
/* Don't move a reg that has an explicit clobber.
|
||||
It's not worth the pain to try to do it correctly. */
|
||||
may_not_move[REGNO (XEXP (x, 0))] = 1;
|
||||
VARRAY_CHAR (may_not_move, REGNO (XEXP (x, 0))) = 1;
|
||||
|
||||
if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
|
||||
{
|
||||
|
@ -3411,13 +3428,14 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
|||
if (GET_CODE (dest) == REG)
|
||||
{
|
||||
register int regno = REGNO (dest);
|
||||
if (n_times_set[regno] > 0 && last_set[regno] == 0)
|
||||
may_not_move[regno] = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) > 0
|
||||
&& last_set[regno] == 0)
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (last_set[regno] != 0
|
||||
&& reg_used_between_p (dest, last_set[regno], insn))
|
||||
may_not_move[regno] = 1;
|
||||
if (n_times_set[regno] < 127)
|
||||
++n_times_set[regno];
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) < 127)
|
||||
++VARRAY_INT (n_times_set, regno);
|
||||
last_set[regno] = insn;
|
||||
}
|
||||
}
|
||||
|
@ -3745,7 +3763,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
|||
if (reg_iv_type[bl->regno] != BASIC_INDUCT
|
||||
/* Above happens if register modified by subreg, etc. */
|
||||
/* Make sure it is not recognized as a basic induction var: */
|
||||
|| n_times_set[bl->regno] != bl->biv_count
|
||||
|| VARRAY_INT (n_times_set, bl->regno) != bl->biv_count
|
||||
/* If never incremented, it is invariant that we decided not to
|
||||
move. So leave it alone. */
|
||||
|| ! bl->incremented)
|
||||
|
@ -3906,7 +3924,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
|||
if (GET_CODE (p) == INSN
|
||||
&& (set = single_set (p))
|
||||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
&& ! may_not_optimize[REGNO (SET_DEST (set))])
|
||||
&& ! VARRAY_CHAR (may_not_optimize, REGNO (SET_DEST (set))))
|
||||
{
|
||||
rtx src_reg;
|
||||
rtx add_val;
|
||||
|
@ -3932,7 +3950,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
|||
/* Don't recognize a BASIC_INDUCT_VAR here. */
|
||||
&& dest_reg != src_reg
|
||||
/* This must be the only place where the register is set. */
|
||||
&& (n_times_set[REGNO (dest_reg)] == 1
|
||||
&& (VARRAY_INT (n_times_set, REGNO (dest_reg)) == 1
|
||||
/* or all sets must be consecutive and make a giv. */
|
||||
|| (benefit = consec_sets_giv (benefit, p,
|
||||
src_reg, dest_reg,
|
||||
|
@ -3948,7 +3966,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
|||
benefit += libcall_benefit (p);
|
||||
|
||||
/* Skip the consecutive insns, if there are any. */
|
||||
for (count = n_times_set[REGNO (dest_reg)] - 1;
|
||||
for (count = VARRAY_INT (n_times_set, REGNO (dest_reg)) - 1;
|
||||
count > 0; count--)
|
||||
{
|
||||
/* If first insn of libcall sequence, skip to end.
|
||||
|
@ -4890,7 +4908,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
|
|||
v->lifetime = (uid_luid[REGNO_LAST_UID (REGNO (dest_reg))]
|
||||
- uid_luid[REGNO_FIRST_UID (REGNO (dest_reg))]);
|
||||
|
||||
v->times_used = n_times_used[REGNO (dest_reg)];
|
||||
v->times_used = VARRAY_INT (n_times_used, REGNO (dest_reg));
|
||||
|
||||
/* If the lifetime is zero, it means that this register is
|
||||
really a dead store. So mark this as a giv that can be
|
||||
|
@ -6050,7 +6068,7 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
|
|||
reg_iv_type[REGNO (dest_reg)] = GENERAL_INDUCT;
|
||||
reg_iv_info[REGNO (dest_reg)] = v;
|
||||
|
||||
count = n_times_set[REGNO (dest_reg)] - 1;
|
||||
count = VARRAY_INT (n_times_set, REGNO (dest_reg)) - 1;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
|
@ -6322,12 +6340,12 @@ combine_givs_used_once (g1, g2)
|
|||
struct induction *g1, *g2;
|
||||
{
|
||||
if (g1->giv_type == DEST_REG
|
||||
&& n_times_used[REGNO (g1->dest_reg)] == 1
|
||||
&& VARRAY_INT (n_times_used, REGNO (g1->dest_reg)) == 1
|
||||
&& reg_mentioned_p (g1->dest_reg, PATTERN (g2->insn)))
|
||||
return -1;
|
||||
|
||||
if (g2->giv_type == DEST_REG
|
||||
&& n_times_used[REGNO (g2->dest_reg)] == 1
|
||||
&& VARRAY_INT (n_times_used, REGNO (g2->dest_reg)) == 1
|
||||
&& reg_mentioned_p (g2->dest_reg, PATTERN (g1->insn)))
|
||||
return 1;
|
||||
|
||||
|
@ -8398,6 +8416,8 @@ insert_loop_mem (mem, data)
|
|||
loop_mems[loop_mems_idx].optimize = (GET_MODE (m) != BLKmode);
|
||||
loop_mems[loop_mems_idx].reg = NULL_RTX;
|
||||
++loop_mems_idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Like load_mems, but also ensures that N_TIMES_SET,
|
||||
|
@ -8411,7 +8431,7 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start,
|
|||
rtx end;
|
||||
rtx loop_top;
|
||||
rtx start;
|
||||
rtx *reg_single_usage;
|
||||
varray_type reg_single_usage;
|
||||
int *insn_count;
|
||||
{
|
||||
int nregs = max_reg_num ();
|
||||
|
@ -8428,32 +8448,42 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start,
|
|||
old_nregs = nregs;
|
||||
nregs = max_reg_num ();
|
||||
|
||||
/* Note that we assume here that enough room was allocated in
|
||||
the various arrays to accomodate the extra registers created
|
||||
by load_mems. */
|
||||
bzero ((char *) n_times_set, nregs * sizeof (int));
|
||||
bzero (may_not_optimize, nregs);
|
||||
if (loop_has_call && reg_single_usage)
|
||||
bzero ((char *) reg_single_usage, nregs * sizeof (rtx));
|
||||
if (nregs > n_times_set->num_elements)
|
||||
{
|
||||
/* Grow all the arrays. */
|
||||
VARRAY_GROW (n_times_set, nregs);
|
||||
VARRAY_GROW (n_times_used, nregs);
|
||||
VARRAY_GROW (may_not_optimize, nregs);
|
||||
if (reg_single_usage)
|
||||
VARRAY_GROW (reg_single_usage, nregs);
|
||||
}
|
||||
/* Clear the arrays */
|
||||
bzero ((char *) &n_times_set->data, nregs * sizeof (int));
|
||||
bzero ((char *) &may_not_optimize->data, nregs * sizeof (char));
|
||||
if (reg_single_usage)
|
||||
bzero ((char *) ®_single_usage->data, nregs * sizeof (rtx));
|
||||
|
||||
count_loop_regs_set (loop_top ? loop_top : start, end,
|
||||
may_not_optimize, reg_single_usage,
|
||||
insn_count, nregs);
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
may_not_optimize[i] = 1, n_times_set[i] = 1;
|
||||
{
|
||||
VARRAY_CHAR (may_not_optimize, i) = 1;
|
||||
VARRAY_INT (n_times_set, i) = 1;
|
||||
}
|
||||
|
||||
#ifdef AVOID_CCMODE_COPIES
|
||||
/* Don't try to move insns which set CC registers if we should not
|
||||
create CCmode register copies. */
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < nregs - loop_mems_idx; i++)
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
|
||||
if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
|
||||
may_not_optimize[i] = 1;
|
||||
VARRAY_CHAR (may_not_optimize, i) = 1;
|
||||
#endif
|
||||
|
||||
/* Set n_times_used for the new registers. */
|
||||
bcopy ((char *) (n_times_set + old_nregs),
|
||||
(char *) (n_times_used + old_nregs),
|
||||
bcopy ((char *) (&n_times_set->data.i[0] + old_nregs),
|
||||
(char *) (&n_times_used->data.i[0] + old_nregs),
|
||||
(nregs - old_nregs) * sizeof (int));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue