loop.c (count_loop_regs_set): Delete.

* loop.c (count_loop_regs_set): Delete.
	(load_mems_and_recount_loop_regs_set): Delete.
	(loop_regs_scan): Merge common code from count_loop_regs_set,
	scan_loop, and load_mems_and_recount_loop_regs_set.
	(scan_loop): Call load_mems directly and loop_regs_scan
	again if new registers created.

From-SVN: r38758
This commit is contained in:
Michael Hayes 2001-01-07 03:59:47 +00:00 committed by Michael Hayes
parent cd2a3ba227
commit 1d7ae25007
2 changed files with 111 additions and 141 deletions

View File

@ -1,3 +1,12 @@
2001-01-07 Michael Hayes <mhayes@redhat.com>
* loop.c (count_loop_regs_set): Delete.
(load_mems_and_recount_loop_regs_set): Delete.
(loop_regs_scan): Merge common code from count_loop_regs_set,
scan_loop, and load_mems_and_recount_loop_regs_set.
(scan_loop): Call load_mems directly and loop_regs_scan
again if new registers created.
2001-01-07 Neil Booth <neil@daikokuya.demon.co.uk>
* toplev.c (main): Call the front-end specific post_options

View File

@ -153,8 +153,6 @@ static int consec_sets_invariant_p PARAMS ((const struct loop *,
rtx, int, rtx));
static int labels_in_range_p PARAMS ((rtx, int));
static void count_one_set PARAMS ((struct loop_regs *, rtx, rtx, rtx *));
static void count_loop_regs_set PARAMS ((const struct loop *, int *));
static void note_addr_stored PARAMS ((rtx, rtx, void *));
static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *));
static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
@ -232,8 +230,7 @@ static int last_use_this_basic_block PARAMS ((rtx, rtx));
static void record_initial PARAMS ((rtx, rtx, void *));
static void update_reg_last_use PARAMS ((rtx, rtx));
static rtx next_insn_in_loop PARAMS ((const struct loop *, rtx));
static void load_mems_and_recount_loop_regs_set PARAMS ((const struct loop*,
int *));
static void loop_regs_scan PARAMS ((const struct loop*, int, int *));
static void load_mems PARAMS ((const struct loop *));
static int insert_loop_mem PARAMS ((rtx *, void *));
static int replace_loop_mem PARAMS ((rtx *, void *));
@ -614,39 +611,10 @@ scan_loop (loop, flags)
return;
}
/* Count number of times each reg is set during this loop. Set
regs->array[I].may_not_optimize if it is not safe to move out the
setting of register I. Set regs->array[I].single_usage. */
regs->num = max_reg_num ();
/* Allocate extra space for REGs that might be created by
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. */
regs->size = regs->num + loop_info->mems_idx + 16;
regs->array = (struct loop_reg *)
xcalloc (regs->size, sizeof (*regs->array));
count_loop_regs_set (loop, &insn_count);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
regs->array[i].may_not_optimize = 1;
regs->array[i].set_in_loop = 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 = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--)
if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
regs->array[i].may_not_optimize = 1;
#endif
for (i = 0; i < regs->num; i++)
regs->array[i].n_times_set = regs->array[i].set_in_loop;
/* Allocate extra space for REGs that might be created by load_mems.
We allocate a little extra slop as well, in the hopes that we
won't have to reallocate the regs array. */
loop_regs_scan (loop, loop_info->mems_idx + 16, &insn_count);
if (loop_dump_stream)
{
@ -1011,7 +979,11 @@ scan_loop (loop, flags)
/* Now that we've moved some things out of the loop, we might be able to
hoist even more memory references. */
load_mems_and_recount_loop_regs_set (loop, &insn_count);
load_mems (loop);
/* Recalculate regs->array if load_mems has created new registers. */
if (max_reg_num () > regs->num)
loop_regs_scan (loop, 0, &insn_count);
for (update_start = loop_start;
PREV_INSN (update_start)
@ -3344,67 +3316,6 @@ count_one_set (regs, insn, x, last_set)
}
}
}
/* Increment REGS->array[I].SET_IN_LOOP at the index I of each
register that is modified by an insn between FROM and TO. If the
value of an element of REGS->array[I].SET_IN_LOOP becomes 127 or
more, stop incrementing it, to avoid overflow.
Store in REGS->array[I].SINGLE_USAGE[I] the single insn in which
register I is used, if it is only used once. Otherwise, it is set
to 0 (for no uses) or const0_rtx for more than one use. This
parameter may be zero, in which case this processing is not done.
Store in *COUNT_PTR the number of actual instruction
in the loop. We use this to decide what is worth moving out. */
/* last_set[n] is nonzero iff reg n has been set in the current basic block.
In that case, it is the insn that last set reg n. */
static void
count_loop_regs_set (loop, count_ptr)
const struct loop *loop;
int *count_ptr;
{
struct loop_regs *regs = LOOP_REGS (loop);
register rtx *last_set = (rtx *) xcalloc (regs->num, sizeof (rtx));
register rtx insn;
register int count = 0;
for (insn = loop->top ? loop->top : loop->start; insn != loop->end;
insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
{
++count;
/* Record registers that have exactly one use. */
find_single_use_in_loop (regs, insn, PATTERN (insn));
/* Include uses in REG_EQUAL notes. */
if (REG_NOTES (insn))
find_single_use_in_loop (regs, insn, REG_NOTES (insn));
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
count_one_set (regs, insn, PATTERN (insn), last_set);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
register int i;
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i),
last_set);
}
}
if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
memset ((char *) last_set, 0, regs->num * sizeof (rtx));
}
*count_ptr = count;
/* Clean up. */
free (last_set);
}
/* Given a loop that is bounded by LOOP->START and LOOP->END and that
is entered at LOOP->SCAN_START, return 1 if the register set in SET
@ -8687,70 +8598,120 @@ insert_loop_mem (mem, data)
return 0;
}
/* Like load_mems, but also ensures that REGS->array[I].SET_IN_LOOP,
REGS->array[I].MAY_NOT_OPTIMIZE, REGS->array[I].SINGLE_USAGE, and
INSN_COUNT have the correct values after load_mems. */
/* Allocate REGS->ARRAY or reallocate it if it is too small.
Increment REGS->ARRAY[I].SET_IN_LOOP at the index I of each
register that is modified by an insn between FROM and TO. If the
value of an element of REGS->array[I].SET_IN_LOOP becomes 127 or
more, stop incrementing it, to avoid overflow.
Store in REGS->ARRAY[I].SINGLE_USAGE the single insn in which
register I is used, if it is only used once. Otherwise, it is set
to 0 (for no uses) or const0_rtx for more than one use. This
parameter may be zero, in which case this processing is not done.
Set REGS->ARRAY[I].MAY_NOT_OPTIMIZE nonzero if we should not
optimize register I.
Store in *COUNT_PTR the number of actual instructions
in the loop. We use this to decide what is worth moving out. */
static void
load_mems_and_recount_loop_regs_set (loop, insn_count)
loop_regs_scan (loop, extra_size, count_ptr)
const struct loop *loop;
int *insn_count;
int extra_size;
int *count_ptr;
{
struct loop_regs *regs = LOOP_REGS (loop);
int old_nregs;
/* last_set[n] is nonzero iff reg n has been set in the current
basic block. In that case, it is the insn that last set reg n. */
rtx *last_set;
rtx insn;
int count = 0;
int i;
load_mems (loop);
old_nregs = regs->num;
regs->num = max_reg_num ();
/* Recalculate regs->array since load_mems may have created new
registers. */
if (max_reg_num () > regs->num)
/* Grow the regs array if not allocated or too small. */
if (regs->num >= regs->size)
{
int i;
int old_nregs;
regs->size = regs->num + extra_size;
regs->array = (struct loop_reg *)
xrealloc (regs->array, regs->size * sizeof (*regs->array));
old_nregs = regs->num;
regs->num = max_reg_num ();
/* Zero the new elements. */
memset (regs->array + old_nregs, 0,
(regs->size - old_nregs) * sizeof (*regs->array));
}
if (regs->num >= regs->size)
/* Clear previously scanned fields but do not clear n_times_set. */
for (i = 0; i < old_nregs; i++)
{
regs->array[i].set_in_loop = 0;
regs->array[i].may_not_optimize = 0;
regs->array[i].single_usage = NULL_RTX;
}
last_set = (rtx *) xcalloc (regs->num, sizeof (rtx));
/* Scan the loop, recording register usage. */
for (insn = loop->top ? loop->top : loop->start; insn != loop->end;
insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
{
regs->size = regs->num;
++count;
/* Grow the array. */
regs->array = (struct loop_reg *)
xrealloc (regs->array, regs->size * sizeof (*regs->array));
/* Record registers that have exactly one use. */
find_single_use_in_loop (regs, insn, PATTERN (insn));
memset (regs->array + old_nregs, 0,
(regs->size - old_nregs) * sizeof (*regs->array));
/* Include uses in REG_EQUAL notes. */
if (REG_NOTES (insn))
find_single_use_in_loop (regs, insn, REG_NOTES (insn));
if (GET_CODE (PATTERN (insn)) == SET
|| GET_CODE (PATTERN (insn)) == CLOBBER)
count_one_set (regs, insn, PATTERN (insn), last_set);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
register int i;
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i),
last_set);
}
}
for (i = 0; i < old_nregs; i++)
{
regs->array[i].set_in_loop = 0;
regs->array[i].may_not_optimize = 0;
regs->array[i].single_usage = NULL_RTX;
}
if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
memset (last_set, 0, regs->num * sizeof (rtx));
}
count_loop_regs_set (loop, insn_count);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
regs->array[i].may_not_optimize = 1;
regs->array[i].set_in_loop = 1;
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
regs->array[i].may_not_optimize = 1;
regs->array[i].set_in_loop = 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 = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--)
if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
regs->array[i].may_not_optimize = 1;
/* Don't try to move insns which set CC registers if we should not
create CCmode register copies. */
for (i = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--)
if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC)
regs->array[i].may_not_optimize = 1;
#endif
/* Set regs->array[I].n_times_set for the new registers. */
for (i = old_nregs; i < regs->num; i++)
regs->array[i].n_times_set = regs->array[i].set_in_loop;
/* Set regs->array[I].n_times_set for the new registers. */
for (i = old_nregs; i < regs->num; i++)
regs->array[i].n_times_set = regs->array[i].set_in_loop;
}
free (last_set);
*count_ptr = count;
}
/* Move MEMs into registers for the duration of the loop. */
static void