Commit 8deb8e2c by Mark Mitchell Committed by Mark Mitchell

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