Commit 0534b804 by Michael Hayes Committed by Michael Hayes

loop.c (current_loop_info): Delete.

2000-01-26  Michael Hayes  <m.hayes@elec.canterbury.ac.nz>

	* loop.c (current_loop_info): Delete.
	(consec_sets_invariant_p): Add loop argument, update callers.
	(get_condition_for_loop): Likewise.
	(count_nonfixed_reads, update_giv_derive): Likewise.
	(simplify_giv_expr, general_induction_var): Likewise.
	(consec_sets_giv, recombine_givs): Likewise.
	(move_movables): Delete loop_start and loop_end arguments,
	add loop argument, and update callers.
	(find_mem_givs, check_final_value): Likewise.
	(record_giv, maybe_eliminate_biv, maybe_eliminate_biv_1): Likewise.
	(loop_invariant_p): Rename from invariant_p, add loop argument, and
	update callers.
	(basic_induction_var): Add loop argument, delete loop_level argument,
	and update callers.
	* unroll.c (iteration_info): Delete loop_start and loop_end arguments,
	add loop argument, and update callers.
	(find_splittable_regs, find_splittable_givs): Likewise.
	(reg_dead_after_loop, loop_find_equiv_value): Likewise.
	(final_biv_value, final_giv_value, back_branch_in_range_p): Likewise.
	(biv_total_increment): Delete loop_start and loop_end arguments;
	update callers.
	(precondition_loop_p): Delete loop_start and loop_info arguments;
	update callers.
	* loop.h (get_condition_for_loop): Add loop argument.
	(biv_total_increment): Delete loop_start and loop_end arguments.
	(precondition_loop_p): Delete loop_start and loop_info arguments;
	add loop argument.
	(final_biv_value): Delete loop_start and loop_end arguments;
	add loop argument.
	(final_giv_value, back_branch_in_range_p): Likewise.

From-SVN: r31618
parent 8e466531
2000-01-26 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* loop.c (current_loop_info): Delete.
(consec_sets_invariant_p): Add loop argument, update callers.
(get_condition_for_loop): Likewise.
(count_nonfixed_reads, update_giv_derive): Likewise.
(simplify_giv_expr, general_induction_var): Likewise.
(consec_sets_giv, recombine_givs): Likewise.
(move_movables): Delete loop_start and loop_end arguments,
add loop argument, and update callers.
(find_mem_givs, check_final_value): Likewise.
(record_giv, maybe_eliminate_biv, maybe_eliminate_biv_1): Likewise.
(loop_invariant_p): Rename from invariant_p, add loop argument, and
update callers.
(basic_induction_var): Add loop argument, delete loop_level argument,
and update callers.
* unroll.c (iteration_info): Delete loop_start and loop_end arguments,
add loop argument, and update callers.
(find_splittable_regs, find_splittable_givs): Likewise.
(reg_dead_after_loop, loop_find_equiv_value): Likewise.
(final_biv_value, final_giv_value, back_branch_in_range_p): Likewise.
(biv_total_increment): Delete loop_start and loop_end arguments;
update callers.
(precondition_loop_p): Delete loop_start and loop_info arguments;
update callers.
* loop.h (get_condition_for_loop): Add loop argument.
(biv_total_increment): Delete loop_start and loop_end arguments.
(precondition_loop_p): Delete loop_start and loop_info arguments;
add loop argument.
(final_biv_value): Delete loop_start and loop_end arguments;
add loop argument.
(final_giv_value, back_branch_in_range_p): Likewise.
2000-01-25 Gavin Romig-Koch <gavin@cygnus.com> 2000-01-25 Gavin Romig-Koch <gavin@cygnus.com>
* config/mips/mips.h (LEGITIMATE_CONSTANT_P): Fix for mips16. * config/mips/mips.h (LEGITIMATE_CONSTANT_P): Fix for mips16.
......
...@@ -53,11 +53,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -53,11 +53,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h" #include "except.h"
#include "toplev.h" #include "toplev.h"
/* Information about the current loop being processed used to compute
the number of loop iterations for loop unrolling and doloop
optimization. */
static struct loop_info *current_loop_info;
/* Vector mapping INSN_UIDs to luids. /* Vector mapping INSN_UIDs to luids.
The luids are like uids but increase monotonically always. The luids are like uids but increase monotonically always.
We use them to see whether a jump comes from outside a given loop. */ We use them to see whether a jump comes from outside a given loop. */
...@@ -239,12 +234,13 @@ static void find_and_verify_loops PARAMS ((rtx, struct loops *)); ...@@ -239,12 +234,13 @@ static void find_and_verify_loops PARAMS ((rtx, struct loops *));
static void mark_loop_jump PARAMS ((rtx, struct loop *)); static void mark_loop_jump PARAMS ((rtx, struct loop *));
static void prescan_loop PARAMS ((struct loop *)); static void prescan_loop PARAMS ((struct loop *));
static int reg_in_basic_block_p PARAMS ((rtx, rtx)); static int reg_in_basic_block_p PARAMS ((rtx, rtx));
static int consec_sets_invariant_p PARAMS ((rtx, int, rtx)); static int consec_sets_invariant_p PARAMS ((const struct loop *,
rtx, int, rtx));
static int labels_in_range_p PARAMS ((rtx, int)); static int labels_in_range_p PARAMS ((rtx, int));
static void count_one_set PARAMS ((rtx, rtx, varray_type, rtx *)); static void count_one_set PARAMS ((rtx, rtx, varray_type, rtx *));
static void count_loop_regs_set PARAMS ((rtx, rtx, varray_type, varray_type, static void count_loop_regs_set PARAMS ((rtx, rtx, varray_type, varray_type,
int *, int)); int *, int));
static void note_addr_stored PARAMS ((rtx, rtx, void *)); static void note_addr_stored PARAMS ((rtx, rtx, void *));
static void note_set_pseudo_multiple_uses 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)); static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
...@@ -260,37 +256,49 @@ static void combine_movables PARAMS ((struct movable *, int)); ...@@ -260,37 +256,49 @@ static void combine_movables PARAMS ((struct movable *, int));
static int regs_match_p PARAMS ((rtx, rtx, struct movable *)); static int regs_match_p PARAMS ((rtx, rtx, struct movable *));
static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movable *)); static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movable *));
static void add_label_notes PARAMS ((rtx, rtx)); static void add_label_notes PARAMS ((rtx, rtx));
static void move_movables PARAMS ((struct movable *, int, int, rtx, rtx, int)); static void move_movables PARAMS ((struct loop *loop, struct movable *,
static int count_nonfixed_reads PARAMS ((rtx)); int, int, int));
static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
static void strength_reduce PARAMS ((struct loop *, int, int, int)); static void strength_reduce PARAMS ((struct loop *, int, int, int));
static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type)); static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx)); static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
static void find_mem_givs PARAMS ((rtx, rtx, int, int, rtx, 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 *, int, int, int)); static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *,
static void check_final_value PARAMS ((struct induction *, rtx, rtx, int, int, int));
unsigned HOST_WIDE_INT)); static void check_final_value PARAMS ((const struct loop *,
static void record_giv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, int, rtx *, rtx, rtx)); struct induction *));
static void update_giv_derive PARAMS ((rtx)); static void record_giv PARAMS ((const struct loop *, struct induction *,
static int basic_induction_var PARAMS ((rtx, enum machine_mode, rtx, rtx, int, rtx *, rtx *, rtx **, int *)); rtx, rtx, rtx, rtx, rtx, int, enum g_types,
static rtx simplify_giv_expr PARAMS ((rtx, int *)); int, int, rtx *));
static int general_induction_var PARAMS ((rtx, rtx *, rtx *, rtx *, int, int *)); static void update_giv_derive PARAMS ((const struct loop *, rtx));
static int consec_sets_giv PARAMS ((int, rtx, rtx, rtx, rtx *, rtx *, rtx *)); static int basic_induction_var PARAMS ((const struct loop *, rtx,
enum machine_mode, rtx, rtx,
rtx *, rtx *, rtx **, int *));
static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, int *));
static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
rtx *, rtx *, int, int *));
static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
rtx, rtx, rtx *, rtx *, rtx *));
static int check_dbra_loop PARAMS ((struct loop *, int)); static int check_dbra_loop PARAMS ((struct loop *, int));
static rtx express_from_1 PARAMS ((rtx, rtx, rtx)); static rtx express_from_1 PARAMS ((rtx, rtx, rtx));
static rtx combine_givs_p PARAMS ((struct induction *, struct induction *)); static rtx combine_givs_p PARAMS ((struct induction *, struct induction *));
static void combine_givs PARAMS ((struct iv_class *)); static void combine_givs PARAMS ((struct iv_class *));
struct recombine_givs_stats; struct recombine_givs_stats;
static int find_life_end PARAMS ((rtx, struct recombine_givs_stats *, rtx, rtx)); static int find_life_end PARAMS ((rtx, struct recombine_givs_stats *,
static void recombine_givs PARAMS ((struct iv_class *, rtx, rtx, int)); rtx, rtx));
static void recombine_givs PARAMS ((const struct loop *, struct iv_class *,
int));
static int product_cheap_p PARAMS ((rtx, rtx)); static int product_cheap_p PARAMS ((rtx, rtx));
static int maybe_eliminate_biv PARAMS ((struct iv_class *, rtx, rtx, int, int, int)); static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *,
static int maybe_eliminate_biv_1 PARAMS ((rtx, rtx, struct iv_class *, int, rtx)); int, int, int));
static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx,
struct iv_class *, int, rtx));
static int last_use_this_basic_block PARAMS ((rtx, rtx)); static int last_use_this_basic_block PARAMS ((rtx, rtx));
static void record_initial PARAMS ((rtx, rtx, void *)); static void record_initial PARAMS ((rtx, rtx, void *));
static void update_reg_last_use PARAMS ((rtx, rtx)); static void update_reg_last_use PARAMS ((rtx, rtx));
static rtx next_insn_in_loop PARAMS ((const struct loop *, 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*, static void load_mems_and_recount_loop_regs_set PARAMS ((const struct loop*,
int *)); int *));
static void load_mems PARAMS ((const struct loop *)); static void load_mems PARAMS ((const struct loop *));
static int insert_loop_mem PARAMS ((rtx *, void *)); static int insert_loop_mem PARAMS ((rtx *, void *));
static int replace_loop_mem PARAMS ((rtx *, void *)); static int replace_loop_mem PARAMS ((rtx *, void *));
...@@ -546,7 +554,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -546,7 +554,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
/* Returns the next insn, in execution order, after INSN. START and /* Returns the next insn, in execution order, after INSN. START and
END are the NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END for the loop, END are the NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END for the loop,
respectively. LOOP_TOP, if non-NULL, is the top of the loop in the respectively. LOOP->TOP, if non-NULL, is the top of the loop in the
insn-stream; it is used with loops that are entered near the insn-stream; it is used with loops that are entered near the
bottom. */ bottom. */
...@@ -590,6 +598,9 @@ scan_loop (loop, unroll_p, bct_p) ...@@ -590,6 +598,9 @@ scan_loop (loop, unroll_p, bct_p)
register int i; register int i;
rtx loop_start = loop->start; rtx loop_start = loop->start;
rtx loop_end = loop->end; rtx loop_end = loop->end;
/* Additional information about the current loop being processed
that is used to compute the number of loop iterations for loop
unrolling and doloop optimization. */
struct loop_info *loop_info = LOOP_INFO (loop); struct loop_info *loop_info = LOOP_INFO (loop);
rtx p; rtx p;
/* 1 if we are scanning insns that could be executed zero times. */ /* 1 if we are scanning insns that could be executed zero times. */
...@@ -619,7 +630,6 @@ scan_loop (loop, unroll_p, bct_p) ...@@ -619,7 +630,6 @@ scan_loop (loop, unroll_p, bct_p)
int loop_depth = 0; int loop_depth = 0;
int nregs; int nregs;
current_loop_info = loop_info;
loop->top = 0; loop->top = 0;
/* Determine whether this loop starts with a jump down to a test at /* Determine whether this loop starts with a jump down to a test at
...@@ -827,14 +837,14 @@ scan_loop (loop, unroll_p, bct_p) ...@@ -827,14 +837,14 @@ scan_loop (loop, unroll_p, bct_p)
which was not created by the user and not used in an exit test. which was not created by the user and not used in an exit test.
That behavior is incorrect and was removed. */ That behavior is incorrect and was removed. */
; ;
else if ((tem = invariant_p (src)) else if ((tem = loop_invariant_p (loop, src))
&& (dependencies == 0 && (dependencies == 0
|| (tem2 = invariant_p (dependencies)) != 0) || (tem2 = loop_invariant_p (loop, dependencies)) != 0)
&& (VARRAY_INT (set_in_loop, && (VARRAY_INT (set_in_loop,
REGNO (SET_DEST (set))) == 1 REGNO (SET_DEST (set))) == 1
|| (tem1 || (tem1
= consec_sets_invariant_p = consec_sets_invariant_p
(SET_DEST (set), (loop, SET_DEST (set),
VARRAY_INT (set_in_loop, REGNO (SET_DEST (set))), VARRAY_INT (set_in_loop, REGNO (SET_DEST (set))),
p))) 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),
...@@ -1109,8 +1119,7 @@ scan_loop (loop, unroll_p, bct_p) ...@@ -1109,8 +1119,7 @@ scan_loop (loop, unroll_p, bct_p)
optimizing for code size. */ optimizing for code size. */
if (! optimize_size) if (! optimize_size)
move_movables (movables, threshold, move_movables (loop, movables, threshold, insn_count, nregs);
insn_count, loop_start, loop_end, nregs);
/* Now candidates that still are negative are those not moved. /* Now candidates that still are negative are those not moved.
Change set_in_loop to indicate that those are not actually invariant. */ Change set_in_loop to indicate that those are not actually invariant. */
...@@ -1123,7 +1132,8 @@ scan_loop (loop, unroll_p, bct_p) ...@@ -1123,7 +1132,8 @@ scan_loop (loop, unroll_p, bct_p)
load_mems_and_recount_loop_regs_set (loop, &insn_count); load_mems_and_recount_loop_regs_set (loop, &insn_count);
for (update_start = loop_start; for (update_start = loop_start;
PREV_INSN (update_start) && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL; PREV_INSN (update_start)
&& GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
update_start = PREV_INSN (update_start)) update_start = PREV_INSN (update_start))
; ;
update_end = NEXT_INSN (loop_end); update_end = NEXT_INSN (loop_end);
...@@ -1702,17 +1712,18 @@ add_label_notes (x, insns) ...@@ -1702,17 +1712,18 @@ add_label_notes (x, insns)
other throughout. */ other throughout. */
static void static void
move_movables (movables, threshold, insn_count, loop_start, end, nregs) move_movables (loop, movables, threshold, insn_count, nregs)
struct loop *loop;
struct movable *movables; struct movable *movables;
int threshold; int threshold;
int insn_count; int insn_count;
rtx loop_start;
rtx end;
int nregs; int nregs;
{ {
rtx new_start = 0; rtx new_start = 0;
register struct movable *m; register struct movable *m;
register rtx p; register rtx p;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
/* Map of pseudo-register replacements to handle combining /* Map of pseudo-register replacements to handle combining
when we move several insns that load the same value when we move several insns that load the same value
into different pseudo-registers. */ into different pseudo-registers. */
...@@ -1757,11 +1768,11 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs) ...@@ -1757,11 +1768,11 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
if (!m->done if (!m->done
&& (! m->cond && (! m->cond
|| (1 == invariant_p (m->set_src) || (1 == loop_invariant_p (loop, m->set_src)
&& (m->dependencies == 0 && (m->dependencies == 0
|| 1 == invariant_p (m->dependencies)) || 1 == loop_invariant_p (loop, m->dependencies))
&& (m->consec == 0 && (m->consec == 0
|| 1 == consec_sets_invariant_p (m->set_dest, || 1 == consec_sets_invariant_p (loop, m->set_dest,
m->consec + 1, m->consec + 1,
m->insn)))) m->insn))))
&& (! m->forces || m->forces->done)) && (! m->forces || m->forces->done))
...@@ -2062,7 +2073,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs) ...@@ -2062,7 +2073,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
like this as a result of record_jump_cond. */ like this as a result of record_jump_cond. */
if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX)) if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX))
&& ! invariant_p (XEXP (temp, 0))) && ! loop_invariant_p (loop, XEXP (temp, 0)))
remove_note (i1, temp); remove_note (i1, temp);
} }
...@@ -2123,8 +2134,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs) ...@@ -2123,8 +2134,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
We can't use the moved insn because it is out of range We can't use the moved insn because it is out of range
in uid_luid. Only the old insns have luids. */ in uid_luid. Only the old insns have luids. */
REGNO_FIRST_UID (regno) = INSN_UID (loop_start); REGNO_FIRST_UID (regno) = INSN_UID (loop_start);
if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (end)) if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (loop_end))
REGNO_LAST_UID (regno) = INSN_UID (end); REGNO_LAST_UID (regno) = INSN_UID (loop_end);
/* Combine with this moved insn any other matching movables. */ /* Combine with this moved insn any other matching movables. */
...@@ -2192,7 +2203,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs) ...@@ -2192,7 +2203,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* Go through all the instructions in the loop, making /* Go through all the instructions in the loop, making
all the register substitutions scheduled in REG_MAP. */ all the register substitutions scheduled in REG_MAP. */
for (p = new_start; p != end; p = NEXT_INSN (p)) for (p = new_start; p != loop_end; p = NEXT_INSN (p))
if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
|| GET_CODE (p) == CALL_INSN) || GET_CODE (p) == CALL_INSN)
{ {
...@@ -2274,7 +2285,8 @@ replace_call_address (x, reg, addr) ...@@ -2274,7 +2285,8 @@ replace_call_address (x, reg, addr)
in the rtx X. */ in the rtx X. */
static int static int
count_nonfixed_reads (x) count_nonfixed_reads (loop, x)
const struct loop *loop;
rtx x; rtx x;
{ {
register enum rtx_code code; register enum rtx_code code;
...@@ -2299,8 +2311,8 @@ count_nonfixed_reads (x) ...@@ -2299,8 +2311,8 @@ count_nonfixed_reads (x)
return 0; return 0;
case MEM: case MEM:
return ((invariant_p (XEXP (x, 0)) != 1) return ((loop_invariant_p (loop, XEXP (x, 0)) != 1)
+ count_nonfixed_reads (XEXP (x, 0))); + count_nonfixed_reads (loop, XEXP (x, 0)));
default: default:
break; break;
...@@ -2311,12 +2323,12 @@ count_nonfixed_reads (x) ...@@ -2311,12 +2323,12 @@ count_nonfixed_reads (x)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
value += count_nonfixed_reads (XEXP (x, i)); value += count_nonfixed_reads (loop, XEXP (x, i));
else if (fmt[i] == 'E') if (fmt[i] == 'E')
{ {
register int j; register int j;
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
value += count_nonfixed_reads (XVECEXP (x, i, j)); value += count_nonfixed_reads (loop, XVECEXP (x, i, j));
} }
} }
return value; return value;
...@@ -3189,7 +3201,8 @@ note_set_pseudo_multiple_uses (x, y, data) ...@@ -3189,7 +3201,8 @@ note_set_pseudo_multiple_uses (x, y, data)
anything stored in `loop_store_mems'. */ anything stored in `loop_store_mems'. */
int int
invariant_p (x) loop_invariant_p (loop, x)
const struct loop *loop;
register rtx x; register rtx x;
{ {
register int i; register int i;
...@@ -3238,7 +3251,7 @@ invariant_p (x) ...@@ -3238,7 +3251,7 @@ invariant_p (x)
&& ! current_function_has_nonlocal_goto) && ! current_function_has_nonlocal_goto)
return 1; return 1;
if (current_loop_info->has_call if (LOOP_INFO (loop)->has_call
&& REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)]) && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
return 0; return 0;
...@@ -3292,7 +3305,7 @@ invariant_p (x) ...@@ -3292,7 +3305,7 @@ invariant_p (x)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
{ {
int tem = invariant_p (XEXP (x, i)); int tem = loop_invariant_p (loop, XEXP (x, i));
if (tem == 0) if (tem == 0)
return 0; return 0;
if (tem == 2) if (tem == 2)
...@@ -3303,7 +3316,7 @@ invariant_p (x) ...@@ -3303,7 +3316,7 @@ invariant_p (x)
register int j; register int j;
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
{ {
int tem = invariant_p (XVECEXP (x, i, j)); int tem = loop_invariant_p (loop, XVECEXP (x, i, j));
if (tem == 0) if (tem == 0)
return 0; return 0;
if (tem == 2) if (tem == 2)
...@@ -3328,7 +3341,8 @@ invariant_p (x) ...@@ -3328,7 +3341,8 @@ invariant_p (x)
and that its source is invariant. */ and that its source is invariant. */
static int static int
consec_sets_invariant_p (reg, n_sets, insn) consec_sets_invariant_p (loop, reg, n_sets, insn)
const struct loop *loop;
int n_sets; int n_sets;
rtx reg, insn; rtx reg, insn;
{ {
...@@ -3365,7 +3379,7 @@ consec_sets_invariant_p (reg, n_sets, insn) ...@@ -3365,7 +3379,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
&& GET_CODE (SET_DEST (set)) == REG && GET_CODE (SET_DEST (set)) == REG
&& REGNO (SET_DEST (set)) == regno) && REGNO (SET_DEST (set)) == regno)
{ {
this = invariant_p (SET_SRC (set)); this = loop_invariant_p (loop, SET_SRC (set));
if (this != 0) if (this != 0)
value |= this; value |= this;
else if ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))) else if ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX)))
...@@ -3375,7 +3389,7 @@ consec_sets_invariant_p (reg, n_sets, insn) ...@@ -3375,7 +3389,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
notes are OK. */ notes are OK. */
this = (CONSTANT_P (XEXP (temp, 0)) this = (CONSTANT_P (XEXP (temp, 0))
|| (find_reg_note (p, REG_RETVAL, NULL_RTX) || (find_reg_note (p, REG_RETVAL, NULL_RTX)
&& invariant_p (XEXP (temp, 0)))); && loop_invariant_p (loop, XEXP (temp, 0))));
if (this != 0) if (this != 0)
value |= this; value |= this;
} }
...@@ -3390,7 +3404,7 @@ consec_sets_invariant_p (reg, n_sets, insn) ...@@ -3390,7 +3404,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
} }
VARRAY_INT (set_in_loop, regno) = old; VARRAY_INT (set_in_loop, regno) = old;
/* If invariant_p ever returned 2, we return 2. */ /* If loop_invariant_p ever returned 2, we return 2. */
return 1 + (value & 2); return 1 + (value & 2);
} }
...@@ -3420,7 +3434,7 @@ all_sets_invariant_p (reg, insn, table) ...@@ -3420,7 +3434,7 @@ all_sets_invariant_p (reg, insn, table)
&& GET_CODE (SET_DEST (PATTERN (p))) == REG && GET_CODE (SET_DEST (PATTERN (p))) == REG
&& REGNO (SET_DEST (PATTERN (p))) == regno) && REGNO (SET_DEST (PATTERN (p))) == regno)
{ {
if (!invariant_p (SET_SRC (PATTERN (p)), table)) if (! loop_invariant_p (loop, SET_SRC (PATTERN (p)), table))
return 0; return 0;
} }
} }
...@@ -3575,11 +3589,10 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs) ...@@ -3575,11 +3589,10 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
free (last_set); free (last_set);
} }
/* Given a loop that is bounded by LOOP_START and LOOP_END /* Given a loop that is bounded by LOOP->START and LOOP->END and that
and that is entered at LOOP_SCAN_START, is entered at LOOP->SCAN_START, return 1 if the register set in SET
return 1 if the register set in SET contained in insn INSN is used by contained in insn INSN is used by any insn that precedes INSN in
any insn that precedes INSN in cyclic order starting cyclic order starting from the loop entry point.
from the loop entry point.
We don't want to use INSN_LUID here because if we restrict INSN to those We don't want to use INSN_LUID here because if we restrict INSN to those
that have a valid INSN_LUID, it means we cannot move an invariant out that have a valid INSN_LUID, it means we cannot move an invariant out
...@@ -3685,13 +3698,7 @@ static rtx addr_placeholder; ...@@ -3685,13 +3698,7 @@ static rtx addr_placeholder;
valid index in several tables including n_times_set and regno_last_uid. valid index in several tables including n_times_set and regno_last_uid.
This does not cause a problem here, because the added registers cannot be This does not cause a problem here, because the added registers cannot be
givs outside of their loop, and hence will never be reconsidered. givs outside of their loop, and hence will never be reconsidered.
But scan_loop must check regnos to make sure they are in bounds. But scan_loop must check regnos to make sure they are in bounds. */
LOOP_SCAN_START is the first instruction in the loop, as the loop would
actually be executed. END is the NOTE_INSN_LOOP_END. LOOP_TOP is
the first instruction in the loop, as it is layed out in the
instruction stream. LOOP_START is the NOTE_INSN_LOOP_BEG.
LOOP_CONT is the NOTE_INSN_LOOP_CONT. */
static void static void
strength_reduce (loop, insn_count, unroll_p, bct_p) strength_reduce (loop, insn_count, unroll_p, bct_p)
...@@ -3741,7 +3748,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -3741,7 +3748,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
/* If loop_scan_start points to the loop exit test, we have to be wary of /* If loop_scan_start points to the loop exit test, we have to be wary of
subversive use of gotos inside expression statements. */ subversive use of gotos inside expression statements. */
if (prev_nonnote_insn (loop_scan_start) != prev_nonnote_insn (loop_start)) if (prev_nonnote_insn (loop_scan_start) != prev_nonnote_insn (loop_start))
maybe_multiple = back_branch_in_range_p (loop_scan_start, loop_start, loop_end); maybe_multiple = back_branch_in_range_p (loop, loop_scan_start);
VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type"); 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"); VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info");
...@@ -3780,9 +3787,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -3780,9 +3787,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
{ {
int multi_insn_incr = 0; int multi_insn_incr = 0;
if (basic_induction_var (SET_SRC (set), GET_MODE (SET_SRC (set)), if (basic_induction_var (loop, SET_SRC (set),
dest_reg, p, loop->level, GET_MODE (SET_SRC (set)),
&inc_val, &mult_val, dest_reg, p, &inc_val, &mult_val,
&location, &multi_insn_incr)) &location, &multi_insn_incr))
{ {
/* It is a possible basic induction variable. /* It is a possible basic induction variable.
...@@ -3860,9 +3867,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -3860,9 +3867,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
matter. Check to see if the target of this branch is on the matter. Check to see if the target of this branch is on the
loop->exits_labels list. */ loop->exits_labels list. */
for (label = uid_loop[INSN_UID (loop_start)]->exit_labels; for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
label;
label = LABEL_NEXTREF (label))
if (XEXP (label, 0) == JUMP_LABEL (p)) if (XEXP (label, 0) == JUMP_LABEL (p))
break; break;
...@@ -3999,7 +4004,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -3999,7 +4004,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
if (GET_CODE (p) == JUMP_INSN if (GET_CODE (p) == JUMP_INSN
&& JUMP_LABEL (p) != 0 && JUMP_LABEL (p) != 0
&& next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop_end) && next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop_end)
&& (test = get_condition_for_loop (p)) != 0 && (test = get_condition_for_loop (loop, p)) != 0
&& GET_CODE (XEXP (test, 0)) == REG && GET_CODE (XEXP (test, 0)) == REG
&& REGNO (XEXP (test, 0)) < max_reg_before_loop && REGNO (XEXP (test, 0)) < max_reg_before_loop
&& (bl = reg_biv_class[REGNO (XEXP (test, 0))]) != 0 && (bl = reg_biv_class[REGNO (XEXP (test, 0))]) != 0
...@@ -4080,8 +4085,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4080,8 +4085,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
&& GET_CODE (src) == PLUS && GET_CODE (src) == PLUS
&& GET_CODE (XEXP (src, 0)) == REG && GET_CODE (XEXP (src, 0)) == REG
&& CONSTANT_P (XEXP (src, 1)) && CONSTANT_P (XEXP (src, 1))
&& ((increment = biv_total_increment (bl, loop_start, loop_end)) && ((increment = biv_total_increment (bl)) != NULL_RTX))
!= NULL_RTX))
{ {
int regno = REGNO (XEXP (src, 0)); int regno = REGNO (XEXP (src, 0));
...@@ -4093,8 +4097,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4093,8 +4097,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
/* Now, can we transform this biv into a giv? */ /* Now, can we transform this biv into a giv? */
if (bl2 if (bl2
&& bl2->biv_count == 1 && bl2->biv_count == 1
&& rtx_equal_p (increment, && rtx_equal_p (increment, biv_total_increment (bl2))
biv_total_increment (bl2, loop_start, loop_end))
/* init_insn is only set to insns that are before loop_start /* init_insn is only set to insns that are before loop_start
without any intervening labels. */ without any intervening labels. */
&& ! reg_set_between_p (bl2->biv->src_reg, && ! reg_set_between_p (bl2->biv->src_reg,
...@@ -4114,7 +4117,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4114,7 +4117,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
&SET_SRC (single_set (bl->biv->insn)), &SET_SRC (single_set (bl->biv->insn)),
copy_rtx (src), 0)) copy_rtx (src), 0))
{ {
rtx dominator = uid_loop[INSN_UID (loop_start)]->cont_dominator; rtx dominator = loop->cont_dominator;
rtx giv = bl->biv->src_reg; rtx giv = bl->biv->src_reg;
rtx giv_insn = bl->biv->insn; rtx giv_insn = bl->biv->insn;
rtx after_giv = NEXT_INSN (giv_insn); rtx after_giv = NEXT_INSN (giv_insn);
...@@ -4467,11 +4470,11 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4467,11 +4470,11 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
continue; continue;
if (/* SET_SRC is a giv. */ if (/* SET_SRC is a giv. */
(general_induction_var (SET_SRC (set), &src_reg, &add_val, (general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
&mult_val, 0, &benefit) &mult_val, 0, &benefit)
/* Equivalent expression is a giv. */ /* Equivalent expression is a giv. */
|| ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX)) || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
&& general_induction_var (XEXP (regnote, 0), &src_reg, && general_induction_var (loop, XEXP (regnote, 0), &src_reg,
&add_val, &mult_val, 0, &add_val, &mult_val, 0,
&benefit))) &benefit)))
/* Don't try to handle any regs made by loop optimization. /* Don't try to handle any regs made by loop optimization.
...@@ -4482,7 +4485,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4482,7 +4485,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
/* This must be the only place where the register is set. */ /* This must be the only place where the register is set. */
&& (VARRAY_INT (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 (loop, benefit, p,
src_reg, dest_reg, src_reg, dest_reg,
&add_val, &mult_val, &add_val, &mult_val,
&last_consec_insn)))) &last_consec_insn))))
...@@ -4498,9 +4501,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4498,9 +4501,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
if (VARRAY_INT (n_times_set, REGNO (dest_reg)) != 1) if (VARRAY_INT (n_times_set, REGNO (dest_reg)) != 1)
p = last_consec_insn; p = last_consec_insn;
record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit, record_giv (loop, v, p, src_reg, dest_reg, mult_val, add_val,
DEST_REG, not_every_iteration, maybe_multiple, benefit, DEST_REG, not_every_iteration,
NULL_PTR, loop_start, loop_end); maybe_multiple, NULL_PTR);
} }
} }
...@@ -4510,15 +4513,15 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4510,15 +4513,15 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
/* This resulted in worse code on a VAX 8600. I wonder if it /* This resulted in worse code on a VAX 8600. I wonder if it
still does. */ still does. */
if (GET_CODE (p) == INSN) if (GET_CODE (p) == INSN)
find_mem_givs (PATTERN (p), p, not_every_iteration, maybe_multiple, find_mem_givs (loop, PATTERN (p), p, not_every_iteration,
loop_start, loop_end); maybe_multiple);
#endif #endif
/* Update the status of whether giv can derive other givs. This can /* Update the status of whether giv can derive other givs. This can
change when we pass a label or an insn that updates a biv. */ change when we pass a label or an insn that updates a biv. */
if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
|| GET_CODE (p) == CODE_LABEL) || GET_CODE (p) == CODE_LABEL)
update_giv_derive (p); update_giv_derive (loop, p);
/* Past CODE_LABEL, we get to insns that may be executed multiple /* Past CODE_LABEL, we get to insns that may be executed multiple
times. The only way we can be sure that they can't is if every times. The only way we can be sure that they can't is if every
...@@ -4582,9 +4585,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4582,9 +4585,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
matter. Check to see if the target of this branch is on the matter. Check to see if the target of this branch is on the
loop->exits_labels list. */ loop->exits_labels list. */
for (label = uid_loop[INSN_UID (loop_start)]->exit_labels; for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
label;
label = LABEL_NEXTREF (label))
if (XEXP (label, 0) == JUMP_LABEL (p)) if (XEXP (label, 0) == JUMP_LABEL (p))
break; break;
...@@ -4643,7 +4644,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4643,7 +4644,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
for (v = bl->giv; v; v = v->next_iv) for (v = bl->giv; v; v = v->next_iv)
if (! v->replaceable && ! v->not_replaceable) if (! v->replaceable && ! v->not_replaceable)
check_final_value (v, loop_start, loop_end, loop_info->n_iterations); check_final_value (loop, v);
} }
/* Try to prove that the loop counter variable (if any) is always /* Try to prove that the loop counter variable (if any) is always
...@@ -4692,14 +4693,13 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4692,14 +4693,13 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
&& ! bl->nonneg && ! bl->nonneg
#endif #endif
&& ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
|| ((final_value = final_biv_value (bl, loop_start, loop_end, || ((final_value = final_biv_value (loop, bl))
loop_info->n_iterations))
#ifdef HAVE_decrement_and_branch_until_zero #ifdef HAVE_decrement_and_branch_until_zero
&& ! bl->nonneg && ! bl->nonneg
#endif #endif
)) ))
bl->eliminable = maybe_eliminate_biv (bl, loop_start, loop_end, 0, bl->eliminable = maybe_eliminate_biv (loop, bl, 0, threshold,
threshold, insn_count); insn_count);
else else
{ {
if (loop_dump_stream) if (loop_dump_stream)
...@@ -4863,7 +4863,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -4863,7 +4863,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
VARRAY_GROW (reg_iv_type, nregs); VARRAY_GROW (reg_iv_type, nregs);
VARRAY_GROW (reg_iv_info, nregs); VARRAY_GROW (reg_iv_info, nregs);
} }
recombine_givs (bl, loop_start, loop_end, unroll_p); recombine_givs (loop, bl, unroll_p);
/* Reduce each giv that we decided to reduce. */ /* Reduce each giv that we decided to reduce. */
...@@ -5096,7 +5096,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -5096,7 +5096,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
loop to ensure that it will always be executed no matter loop to ensure that it will always be executed no matter
how the loop exits. Otherwise, emit the insn after the loop, how the loop exits. Otherwise, emit the insn after the loop,
since this is slightly more efficient. */ since this is slightly more efficient. */
if (uid_loop[INSN_UID (loop_start)]->exit_count) if (loop->exit_count)
insert_before = loop_start; insert_before = loop_start;
else else
insert_before = end_insert_before; insert_before = end_insert_before;
...@@ -5164,9 +5164,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -5164,9 +5164,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
doing so in the rare cases where it can occur. */ doing so in the rare cases where it can occur. */
if (all_reduced == 1 && bl->eliminable if (all_reduced == 1 && bl->eliminable
&& maybe_eliminate_biv (bl, loop_start, loop_end, 1, && maybe_eliminate_biv (loop, bl, 1, threshold, insn_count))
threshold, insn_count))
{ {
/* ?? If we created a new test to bypass the loop entirely, /* ?? If we created a new test to bypass the loop entirely,
or otherwise drop straight in, based on this test, then or otherwise drop straight in, based on this test, then
...@@ -5188,7 +5186,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p) ...@@ -5188,7 +5186,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
loop to ensure that it will always be executed no matter loop to ensure that it will always be executed no matter
how the loop exits. Otherwise, emit the insn after the how the loop exits. Otherwise, emit the insn after the
loop, since this is slightly more efficient. */ loop, since this is slightly more efficient. */
if (uid_loop[INSN_UID (loop_start)]->exit_count) if (loop->exit_count)
insert_before = loop_start; insert_before = loop_start;
else else
insert_before = end_insert_before; insert_before = end_insert_before;
...@@ -5328,12 +5326,11 @@ valid_initial_value_p (x, insn, call_seen, loop_start) ...@@ -5328,12 +5326,11 @@ valid_initial_value_p (x, insn, call_seen, loop_start)
more thanonce in each loop iteration. */ more thanonce in each loop iteration. */
static void static void
find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start, find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
loop_end) const struct loop *loop;
rtx x; rtx x;
rtx insn; rtx insn;
int not_every_iteration, maybe_multiple; int not_every_iteration, maybe_multiple;
rtx loop_start, loop_end;
{ {
register int i, j; register int i, j;
register enum rtx_code code; register enum rtx_code code;
...@@ -5371,16 +5368,16 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start, ...@@ -5371,16 +5368,16 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
it comes time to combine a set of related DEST_ADDR GIVs, since it comes time to combine a set of related DEST_ADDR GIVs, since
this one would not be seen. */ this one would not be seen. */
if (general_induction_var (XEXP (x, 0), &src_reg, &add_val, if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
&mult_val, 1, &benefit)) &mult_val, 1, &benefit))
{ {
/* Found one; record it. */ /* Found one; record it. */
struct induction *v struct induction *v
= (struct induction *) oballoc (sizeof (struct induction)); = (struct induction *) oballoc (sizeof (struct induction));
record_giv (v, insn, src_reg, addr_placeholder, mult_val, record_giv (loop, v, insn, src_reg, addr_placeholder, mult_val,
add_val, benefit, DEST_ADDR, not_every_iteration, add_val, benefit, DEST_ADDR, not_every_iteration,
maybe_multiple, &XEXP (x, 0), loop_start, loop_end); maybe_multiple, &XEXP (x, 0));
v->mem_mode = GET_MODE (x); v->mem_mode = GET_MODE (x);
} }
...@@ -5396,12 +5393,12 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start, ...@@ -5396,12 +5393,12 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
fmt = GET_RTX_FORMAT (code); fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e') if (fmt[i] == 'e')
find_mem_givs (XEXP (x, i), insn, not_every_iteration, maybe_multiple, find_mem_givs (loop, XEXP (x, i), insn, not_every_iteration,
loop_start, loop_end); maybe_multiple);
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
find_mem_givs (XVECEXP (x, i, j), insn, not_every_iteration, find_mem_givs (loop, XVECEXP (x, i, j), insn, not_every_iteration,
maybe_multiple, loop_start, loop_end); maybe_multiple);
} }
/* Fill in the data about one biv update. /* Fill in the data about one biv update.
...@@ -5524,9 +5521,9 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location, ...@@ -5524,9 +5521,9 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
LOCATION points to the place where this giv's value appears in INSN. */ LOCATION points to the place where this giv's value appears in INSN. */
static void static void
record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
type, not_every_iteration, maybe_multiple, location, loop_start, type, not_every_iteration, maybe_multiple, location)
loop_end) const struct loop *loop;
struct induction *v; struct induction *v;
rtx insn; rtx insn;
rtx src_reg; rtx src_reg;
...@@ -5536,7 +5533,6 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, ...@@ -5536,7 +5533,6 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
enum g_types type; enum g_types type;
int not_every_iteration, maybe_multiple; int not_every_iteration, maybe_multiple;
rtx *location; rtx *location;
rtx loop_start, loop_end;
{ {
struct induction *b; struct induction *b;
struct iv_class *bl; struct iv_class *bl;
...@@ -5637,7 +5633,8 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, ...@@ -5637,7 +5633,8 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
if (REGNO_FIRST_UID (REGNO (dest_reg)) == INSN_UID (insn) if (REGNO_FIRST_UID (REGNO (dest_reg)) == INSN_UID (insn)
/* Previous line always fails if INSN was moved by loop opt. */ /* Previous line always fails if INSN was moved by loop opt. */
&& uid_luid[REGNO_LAST_UID (REGNO (dest_reg))] < INSN_LUID (loop_end) && uid_luid[REGNO_LAST_UID (REGNO (dest_reg))]
< INSN_LUID (loop->end)
&& (! not_every_iteration && (! not_every_iteration
|| last_use_this_basic_block (dest_reg, insn))) || last_use_this_basic_block (dest_reg, insn)))
{ {
...@@ -5674,7 +5671,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, ...@@ -5674,7 +5671,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
biv update to before it, then this giv is not replaceable. */ biv update to before it, then this giv is not replaceable. */
if (v->replaceable) if (v->replaceable)
for (b = bl->biv; b; b = b->next_iv) for (b = bl->biv; b; b = b->next_iv)
if (back_branch_in_range_p (b->insn, loop_start, loop_end)) if (back_branch_in_range_p (loop, b->insn))
{ {
v->replaceable = 0; v->replaceable = 0;
v->not_replaceable = 1; v->not_replaceable = 1;
...@@ -5772,10 +5769,9 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, ...@@ -5772,10 +5769,9 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
have been identified. */ have been identified. */
static void static void
check_final_value (v, loop_start, loop_end, n_iterations) check_final_value (loop, v)
const struct loop *loop;
struct induction *v; struct induction *v;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
rtx final_value = 0; rtx final_value = 0;
...@@ -5802,7 +5798,7 @@ check_final_value (v, loop_start, loop_end, n_iterations) ...@@ -5802,7 +5798,7 @@ check_final_value (v, loop_start, loop_end, n_iterations)
v->replaceable = 0; v->replaceable = 0;
#endif #endif
if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations)) if ((final_value = final_giv_value (loop, v))
&& (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn))) && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
{ {
int biv_increment_seen = 0; int biv_increment_seen = 0;
...@@ -5834,8 +5830,8 @@ check_final_value (v, loop_start, loop_end, n_iterations) ...@@ -5834,8 +5830,8 @@ check_final_value (v, loop_start, loop_end, n_iterations)
while (1) while (1)
{ {
p = NEXT_INSN (p); p = NEXT_INSN (p);
if (p == loop_end) if (p == loop->end)
p = NEXT_INSN (loop_start); p = NEXT_INSN (loop->start);
if (p == v->insn) if (p == v->insn)
break; break;
...@@ -5868,17 +5864,17 @@ check_final_value (v, loop_start, loop_end, n_iterations) ...@@ -5868,17 +5864,17 @@ check_final_value (v, loop_start, loop_end, n_iterations)
while (1) while (1)
{ {
p = NEXT_INSN (p); p = NEXT_INSN (p);
if (p == loop_end) if (p == loop->end)
p = NEXT_INSN (loop_start); p = NEXT_INSN (loop->start);
if (p == last_giv_use) if (p == last_giv_use)
break; break;
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
&& LABEL_NAME (JUMP_LABEL (p)) && LABEL_NAME (JUMP_LABEL (p))
&& ((loop_insn_first_p (JUMP_LABEL (p), v->insn) && ((loop_insn_first_p (JUMP_LABEL (p), v->insn)
&& loop_insn_first_p (loop_start, JUMP_LABEL (p))) && loop_insn_first_p (loop->start, JUMP_LABEL (p)))
|| (loop_insn_first_p (last_giv_use, JUMP_LABEL (p)) || (loop_insn_first_p (last_giv_use, JUMP_LABEL (p))
&& loop_insn_first_p (JUMP_LABEL (p), loop_end)))) && loop_insn_first_p (JUMP_LABEL (p), loop->end))))
{ {
v->replaceable = 0; v->replaceable = 0;
v->not_replaceable = 1; v->not_replaceable = 1;
...@@ -5914,7 +5910,8 @@ check_final_value (v, loop_start, loop_end, n_iterations) ...@@ -5914,7 +5910,8 @@ check_final_value (v, loop_start, loop_end, n_iterations)
The cases we look at are when a label or an update to a biv is passed. */ The cases we look at are when a label or an update to a biv is passed. */
static void static void
update_giv_derive (p) update_giv_derive (loop, p)
const struct loop *loop;
rtx p; rtx p;
{ {
struct iv_class *bl; struct iv_class *bl;
...@@ -5982,14 +5979,16 @@ update_giv_derive (p) ...@@ -5982,14 +5979,16 @@ update_giv_derive (p)
tem = 0; tem = 0;
if (biv->mult_val == const1_rtx) if (biv->mult_val == const1_rtx)
tem = simplify_giv_expr (gen_rtx_MULT (giv->mode, tem = simplify_giv_expr (loop,
gen_rtx_MULT (giv->mode,
biv->add_val, biv->add_val,
giv->mult_val), giv->mult_val),
&dummy); &dummy);
if (tem && giv->derive_adjustment) if (tem && giv->derive_adjustment)
tem = simplify_giv_expr tem = simplify_giv_expr
(gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment), (loop,
gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment),
&dummy); &dummy);
if (tem) if (tem)
...@@ -6042,13 +6041,13 @@ update_giv_derive (p) ...@@ -6042,13 +6041,13 @@ update_giv_derive (p)
If we cannot find a biv, we return 0. */ If we cannot find a biv, we return 0. */
static int static int
basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
location, multi_insn_incr) location, multi_insn_incr)
const struct loop *loop;
register rtx x; register rtx x;
enum machine_mode mode; enum machine_mode mode;
rtx dest_reg; rtx dest_reg;
rtx p; rtx p;
int level;
rtx *inc_val; rtx *inc_val;
rtx *mult_val; rtx *mult_val;
rtx **location; rtx **location;
...@@ -6081,7 +6080,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6081,7 +6080,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
return 0; return 0;
arg = *argp; arg = *argp;
if (invariant_p (arg) != 1) if (loop_invariant_p (loop, arg) != 1)
return 0; return 0;
*inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0); *inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
...@@ -6093,9 +6092,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6093,9 +6092,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
/* If this is a SUBREG for a promoted variable, check the inner /* If this is a SUBREG for a promoted variable, check the inner
value. */ value. */
if (SUBREG_PROMOTED_VAR_P (x)) if (SUBREG_PROMOTED_VAR_P (x))
return basic_induction_var (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)), return basic_induction_var (loop, SUBREG_REG (x),
dest_reg, p, level, GET_MODE (SUBREG_REG (x)),
inc_val, mult_val, location, dest_reg, p, inc_val, mult_val, location,
multi_insn_incr); multi_insn_incr);
return 0; return 0;
...@@ -6124,11 +6123,11 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6124,11 +6123,11 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
&& (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) && (GET_MODE_CLASS (GET_MODE (SET_DEST (set)))
== MODE_INT) == MODE_INT)
&& SUBREG_REG (SET_DEST (set)) == x)) && SUBREG_REG (SET_DEST (set)) == x))
&& basic_induction_var (SET_SRC (set), && basic_induction_var (loop, SET_SRC (set),
(GET_MODE (SET_SRC (set)) == VOIDmode (GET_MODE (SET_SRC (set)) == VOIDmode
? GET_MODE (x) ? GET_MODE (x)
: GET_MODE (SET_SRC (set))), : GET_MODE (SET_SRC (set))),
dest_reg, insn, level, dest_reg, insn,
inc_val, mult_val, location, inc_val, mult_val, location,
multi_insn_incr)) multi_insn_incr))
{ {
...@@ -6143,7 +6142,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6143,7 +6142,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
as a biv of the outer loop, as a biv of the outer loop,
causing code to be moved INTO the inner loop. */ causing code to be moved INTO the inner loop. */
case MEM: case MEM:
if (invariant_p (x) != 1) if (loop_invariant_p (loop, x) != 1)
return 0; return 0;
case CONST_INT: case CONST_INT:
case SYMBOL_REF: case SYMBOL_REF:
...@@ -6151,7 +6150,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6151,7 +6150,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
/* convert_modes aborts if we try to convert to or from CCmode, so just /* convert_modes aborts if we try to convert to or from CCmode, so just
exclude that case. It is very unlikely that a condition code value exclude that case. It is very unlikely that a condition code value
would be a useful iterator anyways. */ would be a useful iterator anyways. */
if (level == 0 if (loop->level == 1
&& GET_MODE_CLASS (mode) != MODE_CC && GET_MODE_CLASS (mode) != MODE_CC
&& GET_MODE_CLASS (GET_MODE (dest_reg)) != MODE_CC) && GET_MODE_CLASS (GET_MODE (dest_reg)) != MODE_CC)
{ {
...@@ -6164,9 +6163,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6164,9 +6163,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
return 0; return 0;
case SIGN_EXTEND: case SIGN_EXTEND:
return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)), return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
dest_reg, p, level, inc_val, mult_val, dest_reg, p, inc_val, mult_val, location,
location, multi_insn_incr); multi_insn_incr);
case ASHIFTRT: case ASHIFTRT:
/* Similar, since this can be a sign extension. */ /* Similar, since this can be a sign extension. */
...@@ -6184,9 +6183,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6184,9 +6183,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
&& INTVAL (XEXP (x, 1)) >= 0 && INTVAL (XEXP (x, 1)) >= 0
&& GET_CODE (SET_SRC (set)) == ASHIFT && GET_CODE (SET_SRC (set)) == ASHIFT
&& XEXP (x, 1) == XEXP (SET_SRC (set), 1) && XEXP (x, 1) == XEXP (SET_SRC (set), 1)
&& basic_induction_var (XEXP (SET_SRC (set), 0), && basic_induction_var (loop, XEXP (SET_SRC (set), 0),
GET_MODE (XEXP (x, 0)), GET_MODE (XEXP (x, 0)),
dest_reg, insn, level, inc_val, mult_val, dest_reg, insn, inc_val, mult_val,
location, multi_insn_incr)) location, multi_insn_incr))
{ {
*multi_insn_incr = 1; *multi_insn_incr = 1;
...@@ -6214,7 +6213,8 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val, ...@@ -6214,7 +6213,8 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
such that the value of X is biv * mult + add; */ such that the value of X is biv * mult + add; */
static int static int
general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit) general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
const struct loop *loop;
rtx x; rtx x;
rtx *src_reg; rtx *src_reg;
rtx *add_val; rtx *add_val;
...@@ -6226,14 +6226,14 @@ general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit) ...@@ -6226,14 +6226,14 @@ general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit)
char *storage; char *storage;
/* If this is an invariant, forget it, it isn't a giv. */ /* If this is an invariant, forget it, it isn't a giv. */
if (invariant_p (x) == 1) if (loop_invariant_p (loop, x) == 1)
return 0; return 0;
/* See if the expression could be a giv and get its form. /* See if the expression could be a giv and get its form.
Mark our place on the obstack in case we don't find a giv. */ Mark our place on the obstack in case we don't find a giv. */
storage = (char *) oballoc (0); storage = (char *) oballoc (0);
*pbenefit = 0; *pbenefit = 0;
x = simplify_giv_expr (x, pbenefit); x = simplify_giv_expr (loop, x, pbenefit);
if (x == 0) if (x == 0)
{ {
obfree (storage); obfree (storage);
...@@ -6336,7 +6336,8 @@ static int cmp_combine_givs_stats PARAMS ((const PTR, const PTR)); ...@@ -6336,7 +6336,8 @@ static int cmp_combine_givs_stats PARAMS ((const PTR, const PTR));
static int cmp_recombine_givs_stats PARAMS ((const PTR, const PTR)); static int cmp_recombine_givs_stats PARAMS ((const PTR, const PTR));
static rtx static rtx
simplify_giv_expr (x, benefit) simplify_giv_expr (loop, x, benefit)
const struct loop *loop;
rtx x; rtx x;
int *benefit; int *benefit;
{ {
...@@ -6354,8 +6355,8 @@ simplify_giv_expr (x, benefit) ...@@ -6354,8 +6355,8 @@ simplify_giv_expr (x, benefit)
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case PLUS: case PLUS:
arg0 = simplify_giv_expr (XEXP (x, 0), benefit); arg0 = simplify_giv_expr (loop, XEXP (x, 0), benefit);
arg1 = simplify_giv_expr (XEXP (x, 1), benefit); arg1 = simplify_giv_expr (loop, XEXP (x, 1), benefit);
if (arg0 == 0 || arg1 == 0) if (arg0 == 0 || arg1 == 0)
return NULL_RTX; return NULL_RTX;
...@@ -6401,7 +6402,8 @@ simplify_giv_expr (x, benefit) ...@@ -6401,7 +6402,8 @@ simplify_giv_expr (x, benefit)
case PLUS: case PLUS:
/* (a + invar_1) + invar_2. Associate. */ /* (a + invar_1) + invar_2. Associate. */
return return
simplify_giv_expr (gen_rtx_PLUS (mode, simplify_giv_expr (loop,
gen_rtx_PLUS (mode,
XEXP (arg0, 0), XEXP (arg0, 0),
gen_rtx_PLUS (mode, gen_rtx_PLUS (mode,
XEXP (arg0, 1), XEXP (arg0, 1),
...@@ -6427,7 +6429,8 @@ simplify_giv_expr (x, benefit) ...@@ -6427,7 +6429,8 @@ simplify_giv_expr (x, benefit)
if (GET_CODE (arg1) == PLUS) if (GET_CODE (arg1) == PLUS)
return return
simplify_giv_expr (gen_rtx_PLUS (mode, simplify_giv_expr (loop,
gen_rtx_PLUS (mode,
gen_rtx_PLUS (mode, arg0, gen_rtx_PLUS (mode, arg0,
XEXP (arg1, 0)), XEXP (arg1, 0)),
XEXP (arg1, 1)), XEXP (arg1, 1)),
...@@ -6440,7 +6443,8 @@ simplify_giv_expr (x, benefit) ...@@ -6440,7 +6443,8 @@ simplify_giv_expr (x, benefit)
if (!rtx_equal_p (arg0, arg1)) if (!rtx_equal_p (arg0, arg1))
return NULL_RTX; return NULL_RTX;
return simplify_giv_expr (gen_rtx_MULT (mode, return simplify_giv_expr (loop,
gen_rtx_MULT (mode,
XEXP (arg0, 0), XEXP (arg0, 0),
gen_rtx_PLUS (mode, gen_rtx_PLUS (mode,
XEXP (arg0, 1), XEXP (arg0, 1),
...@@ -6449,7 +6453,8 @@ simplify_giv_expr (x, benefit) ...@@ -6449,7 +6453,8 @@ simplify_giv_expr (x, benefit)
case MINUS: case MINUS:
/* Handle "a - b" as "a + b * (-1)". */ /* Handle "a - b" as "a + b * (-1)". */
return simplify_giv_expr (gen_rtx_PLUS (mode, return simplify_giv_expr (loop,
gen_rtx_PLUS (mode,
XEXP (x, 0), XEXP (x, 0),
gen_rtx_MULT (mode, gen_rtx_MULT (mode,
XEXP (x, 1), XEXP (x, 1),
...@@ -6457,8 +6462,8 @@ simplify_giv_expr (x, benefit) ...@@ -6457,8 +6462,8 @@ simplify_giv_expr (x, benefit)
benefit); benefit);
case MULT: case MULT:
arg0 = simplify_giv_expr (XEXP (x, 0), benefit); arg0 = simplify_giv_expr (loop, XEXP (x, 0), benefit);
arg1 = simplify_giv_expr (XEXP (x, 1), benefit); arg1 = simplify_giv_expr (loop, XEXP (x, 1), benefit);
if (arg0 == 0 || arg1 == 0) if (arg0 == 0 || arg1 == 0)
return NULL_RTX; return NULL_RTX;
...@@ -6511,7 +6516,8 @@ simplify_giv_expr (x, benefit) ...@@ -6511,7 +6516,8 @@ simplify_giv_expr (x, benefit)
case MULT: case MULT:
/* (a * invar_1) * invar_2. Associate. */ /* (a * invar_1) * invar_2. Associate. */
return simplify_giv_expr (gen_rtx_MULT (mode, return simplify_giv_expr (loop,
gen_rtx_MULT (mode,
XEXP (arg0, 0), XEXP (arg0, 0),
gen_rtx_MULT (mode, gen_rtx_MULT (mode,
XEXP (arg0, 1), XEXP (arg0, 1),
...@@ -6520,7 +6526,8 @@ simplify_giv_expr (x, benefit) ...@@ -6520,7 +6526,8 @@ simplify_giv_expr (x, benefit)
case PLUS: case PLUS:
/* (a + invar_1) * invar_2. Distribute. */ /* (a + invar_1) * invar_2. Distribute. */
return simplify_giv_expr (gen_rtx_PLUS (mode, return simplify_giv_expr (loop,
gen_rtx_PLUS (mode,
gen_rtx_MULT (mode, gen_rtx_MULT (mode,
XEXP (arg0, 0), XEXP (arg0, 0),
arg1), arg1),
...@@ -6539,7 +6546,8 @@ simplify_giv_expr (x, benefit) ...@@ -6539,7 +6546,8 @@ simplify_giv_expr (x, benefit)
return 0; return 0;
return return
simplify_giv_expr (gen_rtx_MULT (mode, simplify_giv_expr (loop,
gen_rtx_MULT (mode,
XEXP (x, 0), XEXP (x, 0),
GEN_INT ((HOST_WIDE_INT) 1 GEN_INT ((HOST_WIDE_INT) 1
<< INTVAL (XEXP (x, 1)))), << INTVAL (XEXP (x, 1)))),
...@@ -6547,12 +6555,14 @@ simplify_giv_expr (x, benefit) ...@@ -6547,12 +6555,14 @@ simplify_giv_expr (x, benefit)
case NEG: case NEG:
/* "-a" is "a * (-1)" */ /* "-a" is "a * (-1)" */
return simplify_giv_expr (gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx), return simplify_giv_expr (loop,
gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx),
benefit); benefit);
case NOT: case NOT:
/* "~a" is "-a - 1". Silly, but easy. */ /* "~a" is "-a - 1". Silly, but easy. */
return simplify_giv_expr (gen_rtx_MINUS (mode, return simplify_giv_expr (loop,
gen_rtx_MINUS (mode,
gen_rtx_NEG (mode, XEXP (x, 0)), gen_rtx_NEG (mode, XEXP (x, 0)),
const1_rtx), const1_rtx),
benefit); benefit);
...@@ -6587,14 +6597,14 @@ simplify_giv_expr (x, benefit) ...@@ -6587,14 +6597,14 @@ simplify_giv_expr (x, benefit)
if (v->derive_adjustment) if (v->derive_adjustment)
tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment); tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment);
return simplify_giv_expr (tem, benefit); return simplify_giv_expr (loop, tem, benefit);
} }
default: default:
/* If it isn't an induction variable, and it is invariant, we /* If it isn't an induction variable, and it is invariant, we
may be able to simplify things further by looking through may be able to simplify things further by looking through
the bits we just moved outside the loop. */ the bits we just moved outside the loop. */
if (invariant_p (x) == 1) if (loop_invariant_p (loop, x) == 1)
{ {
struct movable *m; struct movable *m;
...@@ -6606,7 +6616,8 @@ simplify_giv_expr (x, benefit) ...@@ -6606,7 +6616,8 @@ simplify_giv_expr (x, benefit)
/* If we match another movable, we must use that, as /* If we match another movable, we must use that, as
this one is going away. */ this one is going away. */
if (m->match) if (m->match)
return simplify_giv_expr (m->match->set_dest, benefit); return simplify_giv_expr (loop, m->match->set_dest,
benefit);
/* If consec is non-zero, this is a member of a group of /* If consec is non-zero, this is a member of a group of
instructions that were moved together. We handle this instructions that were moved together. We handle this
...@@ -6640,7 +6651,7 @@ simplify_giv_expr (x, benefit) ...@@ -6640,7 +6651,7 @@ simplify_giv_expr (x, benefit)
|| GET_CODE (tem) == CONST_INT || GET_CODE (tem) == CONST_INT
|| GET_CODE (tem) == SYMBOL_REF) || GET_CODE (tem) == SYMBOL_REF)
{ {
tem = simplify_giv_expr (tem, benefit); tem = simplify_giv_expr (loop, tem, benefit);
if (tem) if (tem)
return tem; return tem;
} }
...@@ -6649,7 +6660,8 @@ simplify_giv_expr (x, benefit) ...@@ -6649,7 +6660,8 @@ simplify_giv_expr (x, benefit)
&& GET_CODE (XEXP (XEXP (tem, 0), 0)) == SYMBOL_REF && GET_CODE (XEXP (XEXP (tem, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT) && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)
{ {
tem = simplify_giv_expr (XEXP (tem, 0), benefit); tem = simplify_giv_expr (loop, XEXP (tem, 0),
benefit);
if (tem) if (tem)
return tem; return tem;
} }
...@@ -6667,7 +6679,7 @@ simplify_giv_expr (x, benefit) ...@@ -6667,7 +6679,7 @@ simplify_giv_expr (x, benefit)
if (GET_CODE (x) == USE) if (GET_CODE (x) == USE)
x = XEXP (x, 0); x = XEXP (x, 0);
if (invariant_p (x) == 1) if (loop_invariant_p (loop, x) == 1)
{ {
if (GET_CODE (x) == CONST_INT) if (GET_CODE (x) == CONST_INT)
return x; return x;
...@@ -6753,8 +6765,9 @@ sge_plus (mode, x, y) ...@@ -6753,8 +6765,9 @@ sge_plus (mode, x, y)
*MULT_VAL and *ADD_VAL. */ *MULT_VAL and *ADD_VAL. */
static int static int
consec_sets_giv (first_benefit, p, src_reg, dest_reg, consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
add_val, mult_val, last_consec_insn) add_val, mult_val, last_consec_insn)
const struct loop *loop;
int first_benefit; int first_benefit;
rtx p; rtx p;
rtx src_reg; rtx src_reg;
...@@ -6803,11 +6816,11 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg, ...@@ -6803,11 +6816,11 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
&& (set = single_set (p)) && (set = single_set (p))
&& GET_CODE (SET_DEST (set)) == REG && GET_CODE (SET_DEST (set)) == REG
&& SET_DEST (set) == dest_reg && SET_DEST (set) == dest_reg
&& (general_induction_var (SET_SRC (set), &src_reg, && (general_induction_var (loop, SET_SRC (set), &src_reg,
add_val, mult_val, 0, &benefit) add_val, mult_val, 0, &benefit)
/* Giv created by equivalent expression. */ /* Giv created by equivalent expression. */
|| ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX)) || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
&& general_induction_var (XEXP (temp, 0), &src_reg, && general_induction_var (loop, XEXP (temp, 0), &src_reg,
add_val, mult_val, 0, &benefit))) add_val, mult_val, 0, &benefit)))
&& src_reg == v->src_reg) && src_reg == v->src_reg)
{ {
...@@ -7380,9 +7393,9 @@ find_life_end (x, stats, insn, biv) ...@@ -7380,9 +7393,9 @@ find_life_end (x, stats, insn, biv)
This tends to shorten giv lifetimes, and helps the next step: This tends to shorten giv lifetimes, and helps the next step:
try to derive givs from other givs. */ try to derive givs from other givs. */
static void static void
recombine_givs (bl, loop_start, loop_end, unroll_p) recombine_givs (loop, bl, unroll_p)
const struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
rtx loop_start, loop_end;
int unroll_p; int unroll_p;
{ {
struct induction *v, **giv_array, *last_giv; struct induction *v, **giv_array, *last_giv;
...@@ -7535,7 +7548,7 @@ recombine_givs (bl, loop_start, loop_end, unroll_p) ...@@ -7535,7 +7548,7 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
else else
{ {
stats[i].end_luid = uid_luid[REGNO_LAST_UID (regno)]; stats[i].end_luid = uid_luid[REGNO_LAST_UID (regno)];
if (stats[i].end_luid > INSN_LUID (loop_end)) if (stats[i].end_luid > INSN_LUID (loop->end))
{ {
stats[i].end_luid = -1; stats[i].end_luid = -1;
ends_need_computing++; ends_need_computing++;
...@@ -7550,12 +7563,12 @@ recombine_givs (bl, loop_start, loop_end, unroll_p) ...@@ -7550,12 +7563,12 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
if (ends_need_computing) if (ends_need_computing)
{ {
rtx biv = bl->biv->src_reg; rtx biv = bl->biv->src_reg;
rtx p = loop_end; rtx p = loop->end;
do do
{ {
if (p == loop_start) if (p == loop->start)
p = loop_end; p = loop->end;
p = PREV_INSN (p); p = PREV_INSN (p);
if (GET_RTX_CLASS (GET_CODE (p)) != 'i') if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
continue; continue;
...@@ -7641,8 +7654,8 @@ recombine_givs (bl, loop_start, loop_end, unroll_p) ...@@ -7641,8 +7654,8 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
derived giv would defeat the purpose of reducing register derived giv would defeat the purpose of reducing register
pressure. pressure.
??? We could arrange to move the insn. */ ??? We could arrange to move the insn. */
&& ((unsigned) stats[i].end_luid - INSN_LUID (loop_start) && ((unsigned) stats[i].end_luid - INSN_LUID (loop->start)
> (unsigned) stats[i].start_luid - INSN_LUID (loop_start)) > (unsigned) stats[i].start_luid - INSN_LUID (loop->start))
&& rtx_equal_p (last_giv->mult_val, v->mult_val) && rtx_equal_p (last_giv->mult_val, v->mult_val)
/* ??? Could handle libcalls, but would need more logic. */ /* ??? Could handle libcalls, but would need more logic. */
&& ! find_reg_note (v->insn, REG_RETVAL, NULL_RTX) && ! find_reg_note (v->insn, REG_RETVAL, NULL_RTX)
...@@ -7860,7 +7873,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7860,7 +7873,7 @@ check_dbra_loop (loop, insn_count)
register value, try to optimize it. Otherwise, we can't do anything. */ register value, try to optimize it. Otherwise, we can't do anything. */
jump = PREV_INSN (loop_end); jump = PREV_INSN (loop_end);
comparison = get_condition_for_loop (jump); comparison = get_condition_for_loop (loop, jump);
if (comparison == 0) if (comparison == 0)
return 0; return 0;
...@@ -7931,7 +7944,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7931,7 +7944,7 @@ check_dbra_loop (loop, insn_count)
if (GET_CODE (p) != JUMP_INSN) if (GET_CODE (p) != JUMP_INSN)
continue; continue;
before_comparison = get_condition_for_loop (p); before_comparison = get_condition_for_loop (loop, p);
if (before_comparison if (before_comparison
&& XEXP (before_comparison, 0) == bl->biv->dest_reg && XEXP (before_comparison, 0) == bl->biv->dest_reg
&& GET_CODE (before_comparison) == LT && GET_CODE (before_comparison) == LT
...@@ -7969,8 +7982,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7969,8 +7982,7 @@ check_dbra_loop (loop, insn_count)
which is reversible. */ which is reversible. */
int reversible_mem_store = 1; int reversible_mem_store = 1;
if (bl->giv_count == 0 if (bl->giv_count == 0 && ! loop->exit_count)
&& ! uid_loop[INSN_UID (loop_start)]->exit_count)
{ {
rtx bivreg = regno_reg_rtx[bl->regno]; rtx bivreg = regno_reg_rtx[bl->regno];
...@@ -8018,7 +8030,7 @@ check_dbra_loop (loop, insn_count) ...@@ -8018,7 +8030,7 @@ check_dbra_loop (loop, insn_count)
{ {
for (p = loop_start; p != loop_end; p = NEXT_INSN (p)) for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i') if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
num_nonfixed_reads += count_nonfixed_reads (PATTERN (p)); num_nonfixed_reads += count_nonfixed_reads (loop, PATTERN (p));
/* If the loop has a single store, and the destination address is /* If the loop has a single store, and the destination address is
invariant, then we can't reverse the loop, because this address invariant, then we can't reverse the loop, because this address
...@@ -8033,7 +8045,9 @@ check_dbra_loop (loop, insn_count) ...@@ -8033,7 +8045,9 @@ check_dbra_loop (loop, insn_count)
reversible_mem_store reversible_mem_store
= (! unknown_address_altered = (! unknown_address_altered
&& ! unknown_constant_address_altered && ! unknown_constant_address_altered
&& ! invariant_p (XEXP (XEXP (loop_store_mems, 0), 0))); && ! loop_invariant_p (loop,
XEXP (XEXP (loop_store_mems, 0),
0)));
/* If the store depends on a register that is set after the /* If the store depends on a register that is set after the
store, it depends on the initial value, and is thus not store, it depends on the initial value, and is thus not
...@@ -8115,7 +8129,7 @@ check_dbra_loop (loop, insn_count) ...@@ -8115,7 +8129,7 @@ check_dbra_loop (loop, insn_count)
??? If the insns which initialize the comparison value as ??? If the insns which initialize the comparison value as
a whole compute an invariant result, then we could move a whole compute an invariant result, then we could move
them out of the loop and proceed with loop reversal. */ them out of the loop and proceed with loop reversal. */
if (!invariant_p (comparison_value)) if (! loop_invariant_p (loop, comparison_value))
return 0; return 0;
if (GET_CODE (comparison_value) == CONST_INT) if (GET_CODE (comparison_value) == CONST_INT)
...@@ -8403,7 +8417,6 @@ check_dbra_loop (loop, insn_count) ...@@ -8403,7 +8417,6 @@ check_dbra_loop (loop, insn_count)
/* Verify whether the biv BL appears to be eliminable, /* Verify whether the biv BL appears to be eliminable,
based on the insns in the loop that refer to it. based on the insns in the loop that refer to it.
LOOP_START is the first insn of the loop, and END is the end insn.
If ELIMINATE_P is non-zero, actually do the elimination. If ELIMINATE_P is non-zero, actually do the elimination.
...@@ -8412,15 +8425,15 @@ check_dbra_loop (loop, insn_count) ...@@ -8412,15 +8425,15 @@ check_dbra_loop (loop, insn_count)
start of the loop. */ start of the loop. */
static int static int
maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold, maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
insn_count) const struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
rtx loop_start;
rtx loop_end;
int eliminate_p; int eliminate_p;
int threshold, insn_count; int threshold, insn_count;
{ {
rtx reg = bl->biv->dest_reg; rtx reg = bl->biv->dest_reg;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
rtx p; rtx p;
/* Scan all insns in the loop, stopping if we find one that uses the /* Scan all insns in the loop, stopping if we find one that uses the
...@@ -8454,7 +8467,8 @@ maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold, ...@@ -8454,7 +8467,8 @@ maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold,
} }
if ((code == INSN || code == JUMP_INSN || code == CALL_INSN) if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
&& reg_mentioned_p (reg, PATTERN (p)) && reg_mentioned_p (reg, PATTERN (p))
&& ! maybe_eliminate_biv_1 (PATTERN (p), p, bl, eliminate_p, where)) && ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl,
eliminate_p, where))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -8558,7 +8572,8 @@ biv_elimination_giv_has_0_offset (biv, giv, insn) ...@@ -8558,7 +8572,8 @@ biv_elimination_giv_has_0_offset (biv, giv, insn)
the loop. */ the loop. */
static int static int
maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where) maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
const struct loop *loop;
rtx x, insn; rtx x, insn;
struct iv_class *bl; struct iv_class *bl;
int eliminate_p; int eliminate_p;
...@@ -8777,7 +8792,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where) ...@@ -8777,7 +8792,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
} }
else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM) else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM)
{ {
if (invariant_p (arg) == 1) if (loop_invariant_p (loop, arg) == 1)
{ {
/* Look for giv with constant positive mult_val and nonconst /* Look for giv with constant positive mult_val and nonconst
add_val. Insert insns to compute new compare value. add_val. Insert insns to compute new compare value.
...@@ -8884,14 +8899,14 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where) ...@@ -8884,14 +8899,14 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
switch (fmt[i]) switch (fmt[i])
{ {
case 'e': case 'e':
if (! maybe_eliminate_biv_1 (XEXP (x, i), insn, bl, if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl,
eliminate_p, where)) eliminate_p, where))
return 0; return 0;
break; break;
case 'E': case 'E':
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (! maybe_eliminate_biv_1 (XVECEXP (x, i, j), insn, bl, if (! maybe_eliminate_biv_1 (loop, XVECEXP (x, i, j), insn, bl,
eliminate_p, where)) eliminate_p, where))
return 0; return 0;
break; break;
...@@ -9250,14 +9265,15 @@ get_condition (jump, earliest) ...@@ -9250,14 +9265,15 @@ get_condition (jump, earliest)
unless both operands are invariants. */ unless both operands are invariants. */
rtx rtx
get_condition_for_loop (x) get_condition_for_loop (loop, x)
const struct loop *loop;
rtx x; rtx x;
{ {
rtx comparison = get_condition (x, NULL_PTR); rtx comparison = get_condition (x, NULL_PTR);
if (comparison == 0 if (comparison == 0
|| ! invariant_p (XEXP (comparison, 0)) || ! loop_invariant_p (loop, XEXP (comparison, 0))
|| invariant_p (XEXP (comparison, 1))) || loop_invariant_p (loop, XEXP (comparison, 1)))
return comparison; return comparison;
return gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)), VOIDmode, return gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)), VOIDmode,
...@@ -9762,7 +9778,7 @@ load_mems (loop) ...@@ -9762,7 +9778,7 @@ load_mems (loop)
rtx mem_list_entry; rtx mem_list_entry;
if (MEM_VOLATILE_P (mem) if (MEM_VOLATILE_P (mem)
|| invariant_p (XEXP (mem, 0)) != 1) || loop_invariant_p (loop, XEXP (mem, 0)) != 1)
/* There's no telling whether or not MEM is modified. */ /* There's no telling whether or not MEM is modified. */
loop_mems[i].optimize = 0; loop_mems[i].optimize = 0;
...@@ -9874,7 +9890,7 @@ load_mems (loop) ...@@ -9874,7 +9890,7 @@ load_mems (loop)
int j; int j;
rtx set; rtx set;
/* Load the memory immediately before START, which is /* Load the memory immediately before LOOP->START, which is
the NOTE_LOOP_BEG. */ the NOTE_LOOP_BEG. */
set = gen_move_insn (reg, mem); set = gen_move_insn (reg, mem);
emit_insn_before (set, loop->start); emit_insn_before (set, loop->start);
...@@ -9963,8 +9979,7 @@ note_reg_stored (x, setter, arg) ...@@ -9963,8 +9979,7 @@ note_reg_stored (x, setter, arg)
/* Try to replace every occurrence of pseudo REGNO with REPLACEMENT. /* Try to replace every occurrence of pseudo REGNO with REPLACEMENT.
There must be exactly one insn that sets this pseudo; it will be There must be exactly one insn that sets this pseudo; it will be
deleted if all replacements succeed and we can prove that the register deleted if all replacements succeed and we can prove that the register
is not used after the loop. is not used after the loop. */
The arguments SCAN_START, LOOP_TOP and END are as in load_mems. */
static void static void
try_copy_prop (loop, replacement, regno) try_copy_prop (loop, replacement, regno)
const struct loop *loop; const struct loop *loop;
......
...@@ -230,23 +230,21 @@ extern int first_increment_giv, last_increment_giv; ...@@ -230,23 +230,21 @@ extern int first_increment_giv, last_increment_giv;
/* Forward declarations for non-static functions declared in loop.c and /* Forward declarations for non-static functions declared in loop.c and
unroll.c. */ unroll.c. */
int invariant_p PARAMS ((rtx)); int loop_invariant_p PARAMS ((const struct loop *, rtx));
rtx get_condition_for_loop PARAMS ((rtx)); rtx get_condition_for_loop PARAMS ((const struct loop *, rtx));
void emit_iv_add_mult PARAMS ((rtx, rtx, rtx, rtx, rtx)); void emit_iv_add_mult PARAMS ((rtx, rtx, rtx, rtx, rtx));
rtx express_from PARAMS ((struct induction *, struct induction *)); rtx express_from PARAMS ((struct induction *, struct induction *));
void unroll_loop PARAMS ((struct loop *, int, rtx, int)); void unroll_loop PARAMS ((struct loop *, int, rtx, int));
rtx biv_total_increment PARAMS ((struct iv_class *, rtx, rtx)); rtx biv_total_increment PARAMS ((struct iv_class *));
unsigned HOST_WIDE_INT loop_iterations PARAMS ((struct loop *)); unsigned HOST_WIDE_INT loop_iterations PARAMS ((struct loop *));
int precondition_loop_p PARAMS ((rtx, struct loop_info *, int precondition_loop_p PARAMS ((const struct loop *,
rtx *, rtx *, rtx *, rtx *, rtx *, rtx *,
enum machine_mode *mode)); enum machine_mode *mode));
rtx final_biv_value PARAMS ((struct iv_class *, rtx, rtx, rtx final_biv_value PARAMS ((const struct loop *, struct iv_class *));
unsigned HOST_WIDE_INT)); rtx final_giv_value PARAMS ((const struct loop *, struct induction *));
rtx final_giv_value PARAMS ((struct induction *, rtx, rtx,
unsigned HOST_WIDE_INT));
void emit_unrolled_add PARAMS ((rtx, rtx, rtx)); void emit_unrolled_add PARAMS ((rtx, rtx, rtx));
int back_branch_in_range_p PARAMS ((rtx, rtx, rtx)); int back_branch_in_range_p PARAMS ((const struct loop *, rtx));
int loop_insn_first_p PARAMS ((rtx, rtx)); int loop_insn_first_p PARAMS ((rtx, rtx));
......
...@@ -200,26 +200,27 @@ static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *)); ...@@ -200,26 +200,27 @@ static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *)); static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int, static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx)); enum unroll_types, rtx, rtx, rtx, rtx));
static void iteration_info PARAMS ((rtx, rtx *, rtx *, rtx, rtx)); static void iteration_info PARAMS ((const struct loop *, rtx, rtx *, rtx *));
static int find_splittable_regs PARAMS ((enum unroll_types, rtx, rtx, rtx, int, static int find_splittable_regs PARAMS ((const struct loop *,
unsigned HOST_WIDE_INT)); enum unroll_types, rtx, int));
static int find_splittable_givs PARAMS ((struct iv_class *, enum unroll_types, static int find_splittable_givs PARAMS ((const struct loop *,
rtx, rtx, rtx, int)); struct iv_class *, enum unroll_types,
static int reg_dead_after_loop PARAMS ((rtx, rtx, rtx)); rtx, int));
static int reg_dead_after_loop PARAMS ((const struct loop *, rtx));
static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode)); static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
static int verify_addresses PARAMS ((struct induction *, rtx, int)); static int verify_addresses PARAMS ((struct induction *, rtx, int));
static rtx remap_split_bivs PARAMS ((rtx)); static rtx remap_split_bivs PARAMS ((rtx));
static rtx find_common_reg_term PARAMS ((rtx, rtx)); static rtx find_common_reg_term PARAMS ((rtx, rtx));
static rtx subtract_reg_term PARAMS ((rtx, rtx)); static rtx subtract_reg_term PARAMS ((rtx, rtx));
static rtx loop_find_equiv_value PARAMS ((rtx, rtx)); static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx));
/* Try to unroll one loop and split induction variables in the loop. /* Try to unroll one loop and split induction variables in the loop.
The loop is described by the arguments LOOP_END, INSN_COUNT, and The loop is described by the arguments LOOP and INSN_COUNT.
LOOP_START. END_INSERT_BEFORE indicates where insns should be added END_INSERT_BEFORE indicates where insns should be added which need
which need to be executed when the loop falls through. STRENGTH_REDUCTION_P to be executed when the loop falls through. STRENGTH_REDUCTION_P
indicates whether information generated in the strength reduction pass indicates whether information generated in the strength reduction
is available. pass is available.
This function is intended to be called from within `strength_reduce' This function is intended to be called from within `strength_reduce'
in loop.c. */ in loop.c. */
...@@ -894,7 +895,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -894,7 +895,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
rtx initial_value, final_value, increment; rtx initial_value, final_value, increment;
enum machine_mode mode; enum machine_mode mode;
if (precondition_loop_p (loop_start, loop_info, if (precondition_loop_p (loop,
&initial_value, &final_value, &increment, &initial_value, &final_value, &increment,
&mode)) &mode))
{ {
...@@ -1158,9 +1159,8 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1158,9 +1159,8 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
if (splitting_not_safe) if (splitting_not_safe)
temp = 0; temp = 0;
else else
temp = find_splittable_regs (unroll_type, loop_start, loop_end, temp = find_splittable_regs (loop, unroll_type,
end_insert_before, unroll_number, end_insert_before, unroll_number);
loop_info->n_iterations);
/* find_splittable_regs may have created some new registers, so must /* find_splittable_regs may have created some new registers, so must
reallocate the reg_map with the new larger size, and must realloc reallocate the reg_map with the new larger size, and must realloc
...@@ -1356,13 +1356,13 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1356,13 +1356,13 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
reflected in RTX_COST. */ reflected in RTX_COST. */
int int
precondition_loop_p (loop_start, loop_info, precondition_loop_p (loop, initial_value, final_value, increment, mode)
initial_value, final_value, increment, mode) const struct loop *loop;
rtx loop_start;
struct loop_info *loop_info;
rtx *initial_value, *final_value, *increment; rtx *initial_value, *final_value, *increment;
enum machine_mode *mode; enum machine_mode *mode;
{ {
rtx loop_start = loop->start;
struct loop_info *loop_info = LOOP_INFO (loop);
if (loop_info->n_iterations > 0) if (loop_info->n_iterations > 0)
{ {
...@@ -1423,16 +1423,16 @@ precondition_loop_p (loop_start, loop_info, ...@@ -1423,16 +1423,16 @@ precondition_loop_p (loop_start, loop_info,
return 0; return 0;
} }
/* Must ensure that final_value is invariant, so call invariant_p to /* Must ensure that final_value is invariant, so call
check. Before doing so, must check regno against max_reg_before_loop loop_invariant_p to check. Before doing so, must check regno
to make sure that the register is in the range covered by invariant_p. against max_reg_before_loop to make sure that the register is in
If it isn't, then it is most likely a biv/giv which by definition are the range covered by loop_invariant_p. If it isn't, then it is
not invariant. */ most likely a biv/giv which by definition are not invariant. */
if ((GET_CODE (loop_info->final_value) == REG if ((GET_CODE (loop_info->final_value) == REG
&& REGNO (loop_info->final_value) >= max_reg_before_loop) && REGNO (loop_info->final_value) >= max_reg_before_loop)
|| (GET_CODE (loop_info->final_value) == PLUS || (GET_CODE (loop_info->final_value) == PLUS
&& REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop) && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
|| ! invariant_p (loop_info->final_value)) || ! loop_invariant_p (loop, loop_info->final_value))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -2288,21 +2288,23 @@ emit_unrolled_add (dest_reg, src_reg, increment) ...@@ -2288,21 +2288,23 @@ emit_unrolled_add (dest_reg, src_reg, increment)
emit_move_insn (dest_reg, result); emit_move_insn (dest_reg, result);
} }
/* Searches the insns between INSN and LOOP_END. Returns 1 if there /* Searches the insns between INSN and LOOP->END. Returns 1 if there
is a backward branch in that range that branches to somewhere between is a backward branch in that range that branches to somewhere between
LOOP_START and INSN. Returns 0 otherwise. */ LOOP->START and INSN. Returns 0 otherwise. */
/* ??? This is quadratic algorithm. Could be rewritten to be linear. /* ??? This is quadratic algorithm. Could be rewritten to be linear.
In practice, this is not a problem, because this function is seldom called, In practice, this is not a problem, because this function is seldom called,
and uses a negligible amount of CPU time on average. */ and uses a negligible amount of CPU time on average. */
int int
back_branch_in_range_p (insn, loop_start, loop_end) back_branch_in_range_p (loop, insn)
const struct loop *loop;
rtx insn; rtx insn;
rtx loop_start, loop_end;
{ {
rtx p, q, target_insn; rtx p, q, target_insn;
rtx orig_loop_end = loop_end; rtx loop_start = loop->start;
rtx loop_end = loop->end;
rtx orig_loop_end = loop->end;
/* Stop before we get to the backward branch at the end of the loop. */ /* Stop before we get to the backward branch at the end of the loop. */
loop_end = prev_nonnote_insn (loop_end); loop_end = prev_nonnote_insn (loop_end);
...@@ -2392,9 +2394,8 @@ fold_rtx_mult_add (mult1, mult2, add1, mode) ...@@ -2392,9 +2394,8 @@ fold_rtx_mult_add (mult1, mult2, add1, mode)
if it can be calculated. Otherwise, returns 0. */ if it can be calculated. Otherwise, returns 0. */
rtx rtx
biv_total_increment (bl, loop_start, loop_end) biv_total_increment (bl)
struct iv_class *bl; struct iv_class *bl;
rtx loop_start ATTRIBUTE_UNUSED, loop_end ATTRIBUTE_UNUSED;
{ {
struct induction *v; struct induction *v;
rtx result; rtx result;
...@@ -2427,14 +2428,11 @@ biv_total_increment (bl, loop_start, loop_end) ...@@ -2427,14 +2428,11 @@ biv_total_increment (bl, loop_start, loop_end)
be calculated. */ be calculated. */
static void static void
iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) iteration_info (loop, iteration_var, initial_value, increment)
const struct loop *loop;
rtx iteration_var, *initial_value, *increment; rtx iteration_var, *initial_value, *increment;
rtx loop_start, loop_end;
{ {
struct iv_class *bl; struct iv_class *bl;
#if 0
struct induction *v;
#endif
/* Clear the result values, in case no answer can be found. */ /* Clear the result values, in case no answer can be found. */
*initial_value = 0; *initial_value = 0;
...@@ -2484,7 +2482,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) ...@@ -2484,7 +2482,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
bl = reg_biv_class[REGNO (iteration_var)]; bl = reg_biv_class[REGNO (iteration_var)];
*initial_value = bl->initial_value; *initial_value = bl->initial_value;
*increment = biv_total_increment (bl, loop_start, loop_end); *increment = biv_total_increment (bl);
} }
else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT) else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT)
{ {
...@@ -2498,7 +2496,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) ...@@ -2498,7 +2496,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
/* Increment value is mult_val times the increment value of the biv. */ /* Increment value is mult_val times the increment value of the biv. */
*increment = biv_total_increment (bl, loop_start, loop_end); *increment = biv_total_increment (bl);
if (*increment) if (*increment)
{ {
struct induction *biv_inc; struct induction *biv_inc;
...@@ -2564,13 +2562,11 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) ...@@ -2564,13 +2562,11 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
times, since multiplies by small integers (1,2,3,4) are very cheap. */ times, since multiplies by small integers (1,2,3,4) are very cheap. */
static int static int
find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
unroll_number, n_iterations) const struct loop *loop;
enum unroll_types unroll_type; enum unroll_types unroll_type;
rtx loop_start, loop_end;
rtx end_insert_before; rtx end_insert_before;
int unroll_number; int unroll_number;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
struct induction *v; struct induction *v;
...@@ -2578,13 +2574,15 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2578,13 +2574,15 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
rtx biv_final_value; rtx biv_final_value;
int biv_splittable; int biv_splittable;
int result = 0; int result = 0;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
for (bl = loop_iv_list; bl; bl = bl->next) for (bl = loop_iv_list; bl; bl = bl->next)
{ {
/* Biv_total_increment must return a constant value, /* Biv_total_increment must return a constant value,
otherwise we can not calculate the split values. */ otherwise we can not calculate the split values. */
increment = biv_total_increment (bl, loop_start, loop_end); increment = biv_total_increment (bl);
if (! increment || GET_CODE (increment) != CONST_INT) if (! increment || GET_CODE (increment) != CONST_INT)
continue; continue;
...@@ -2600,16 +2598,14 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2600,16 +2598,14 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
biv_splittable = 1; biv_splittable = 1;
biv_final_value = 0; biv_final_value = 0;
if (unroll_type != UNROLL_COMPLETELY if (unroll_type != UNROLL_COMPLETELY
&& (uid_loop[INSN_UID (loop_start)]->exit_count && (loop->exit_count || unroll_type == UNROLL_NAIVE)
|| unroll_type == UNROLL_NAIVE)
&& (uid_luid[REGNO_LAST_UID (bl->regno)] >= INSN_LUID (loop_end) && (uid_luid[REGNO_LAST_UID (bl->regno)] >= INSN_LUID (loop_end)
|| ! bl->init_insn || ! bl->init_insn
|| INSN_UID (bl->init_insn) >= max_uid_for_loop || INSN_UID (bl->init_insn) >= max_uid_for_loop
|| (uid_luid[REGNO_FIRST_UID (bl->regno)] || (uid_luid[REGNO_FIRST_UID (bl->regno)]
< INSN_LUID (bl->init_insn)) < INSN_LUID (bl->init_insn))
|| reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) || reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
&& ! (biv_final_value = final_biv_value (bl, loop_start, loop_end, && ! (biv_final_value = final_biv_value (loop, bl)))
n_iterations)))
biv_splittable = 0; biv_splittable = 0;
/* If any of the insns setting the BIV don't do so with a simple /* If any of the insns setting the BIV don't do so with a simple
...@@ -2641,7 +2637,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2641,7 +2637,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
if (GET_CODE (bl->initial_value) == REG if (GET_CODE (bl->initial_value) == REG
&& (REGNO (bl->initial_value) == bl->regno && (REGNO (bl->initial_value) == bl->regno
|| REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER || REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER
|| ! invariant_p (bl->initial_value))) || ! loop_invariant_p (loop, bl->initial_value)))
{ {
rtx tem = gen_reg_rtx (bl->biv->mode); rtx tem = gen_reg_rtx (bl->biv->mode);
...@@ -2677,8 +2673,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2677,8 +2673,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
depend on it may be splittable if the biv is live outside the depend on it may be splittable if the biv is live outside the
loop, and the givs aren't. */ loop, and the givs aren't. */
result += find_splittable_givs (bl, unroll_type, loop_start, loop_end, result += find_splittable_givs (loop, bl, unroll_type, increment,
increment, unroll_number); unroll_number);
/* If final value is non-zero, then must emit an instruction which sets /* If final value is non-zero, then must emit an instruction which sets
the value of the biv to the proper value. This is done after the value of the biv to the proper value. This is done after
...@@ -2690,7 +2686,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2690,7 +2686,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
loop to ensure that it will always be executed no matter loop to ensure that it will always be executed no matter
how the loop exits. Otherwise emit the insn after the loop, how the loop exits. Otherwise emit the insn after the loop,
since this is slightly more efficient. */ since this is slightly more efficient. */
if (! uid_loop[INSN_UID (loop_start)]->exit_count) if (! loop->exit_count)
emit_insn_before (gen_move_insn (bl->biv->src_reg, emit_insn_before (gen_move_insn (bl->biv->src_reg,
biv_final_value), biv_final_value),
end_insert_before); end_insert_before);
...@@ -2758,11 +2754,10 @@ verify_addresses (v, giv_inc, unroll_number) ...@@ -2758,11 +2754,10 @@ verify_addresses (v, giv_inc, unroll_number)
Return the number of instructions that set splittable registers. */ Return the number of instructions that set splittable registers. */
static int static int
find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
unroll_number) const struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
enum unroll_types unroll_type; enum unroll_types unroll_type;
rtx loop_start, loop_end;
rtx increment; rtx increment;
int unroll_number; int unroll_number;
{ {
...@@ -2796,7 +2791,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2796,7 +2791,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
won't reach here if they aren't. */ won't reach here if they aren't. */
if (v->giv_type != DEST_ADDR if (v->giv_type != DEST_ADDR
&& (! v->always_computable && (! v->always_computable
|| back_branch_in_range_p (v->insn, loop_start, loop_end))) || back_branch_in_range_p (loop, v->insn)))
continue; continue;
/* The giv increment value must be a constant. */ /* The giv increment value must be a constant. */
...@@ -2817,8 +2812,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2817,8 +2812,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
final_value = 0; final_value = 0;
if (unroll_type != UNROLL_COMPLETELY if (unroll_type != UNROLL_COMPLETELY
&& (uid_loop[INSN_UID (loop_start)]->exit_count && (loop->exit_count || unroll_type == UNROLL_NAIVE)
|| unroll_type == UNROLL_NAIVE)
&& v->giv_type != DEST_ADDR && v->giv_type != DEST_ADDR
/* The next part is true if the pseudo is used outside the loop. /* The next part is true if the pseudo is used outside the loop.
We assume that this is true for any pseudo created after loop We assume that this is true for any pseudo created after loop
...@@ -2833,7 +2827,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2833,7 +2827,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
!= INSN_UID (XEXP (tem, 0))))) != INSN_UID (XEXP (tem, 0)))))
/* Line above always fails if INSN was moved by loop opt. */ /* Line above always fails if INSN was moved by loop opt. */
|| (uid_luid[REGNO_LAST_UID (REGNO (v->dest_reg))] || (uid_luid[REGNO_LAST_UID (REGNO (v->dest_reg))]
>= INSN_LUID (loop_end))) >= INSN_LUID (loop->end)))
/* Givs made from biv increments are missed by the above test, so /* Givs made from biv increments are missed by the above test, so
test explicitly for them. */ test explicitly for them. */
&& (REGNO (v->dest_reg) < first_increment_giv && (REGNO (v->dest_reg) < first_increment_giv
...@@ -2891,7 +2885,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2891,7 +2885,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
record_base_value (REGNO (tem), bl->biv->add_val, 0); record_base_value (REGNO (tem), bl->biv->add_val, 0);
emit_insn_before (gen_move_insn (tem, bl->biv->src_reg), emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
loop_start); loop->start);
biv_initial_value = tem; biv_initial_value = tem;
} }
value = fold_rtx_mult_add (v->mult_val, biv_initial_value, value = fold_rtx_mult_add (v->mult_val, biv_initial_value,
...@@ -2933,7 +2927,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2933,7 +2927,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
rtx tem = gen_reg_rtx (v->mode); rtx tem = gen_reg_rtx (v->mode);
record_base_value (REGNO (tem), v->add_val, 0); record_base_value (REGNO (tem), v->add_val, 0);
emit_iv_add_mult (bl->initial_value, v->mult_val, emit_iv_add_mult (bl->initial_value, v->mult_val,
v->add_val, tem, loop_start); v->add_val, tem, loop->start);
value = tem; value = tem;
} }
...@@ -3082,8 +3076,8 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -3082,8 +3076,8 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
to calculate the value from scratch. */ to calculate the value from scratch. */
emit_insn_before (gen_rtx_SET (VOIDmode, tem, emit_insn_before (gen_rtx_SET (VOIDmode, tem,
copy_rtx (v->new_reg)), copy_rtx (v->new_reg)),
loop_start); loop->start);
if (recog_memoized (PREV_INSN (loop_start)) < 0) if (recog_memoized (PREV_INSN (loop->start)) < 0)
{ {
rtx sequence, ret; rtx sequence, ret;
...@@ -3091,7 +3085,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -3091,7 +3085,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
value, because the loop may have been preconditioned. value, because the loop may have been preconditioned.
We must calculate it from NEW_REG. Try using We must calculate it from NEW_REG. Try using
force_operand instead of emit_iv_add_mult. */ force_operand instead of emit_iv_add_mult. */
delete_insn (PREV_INSN (loop_start)); delete_insn (PREV_INSN (loop->start));
start_sequence (); start_sequence ();
ret = force_operand (v->new_reg, tem); ret = force_operand (v->new_reg, tem);
...@@ -3099,7 +3093,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -3099,7 +3093,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
emit_move_insn (tem, ret); emit_move_insn (tem, ret);
sequence = gen_sequence (); sequence = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (sequence, loop_start); emit_insn_before (sequence, loop->start);
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3238,14 +3232,14 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -3238,14 +3232,14 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
it can search past if statements and other similar structures. */ it can search past if statements and other similar structures. */
static int static int
reg_dead_after_loop (reg, loop_start, loop_end) reg_dead_after_loop (loop, reg)
rtx reg, loop_start, loop_end; const struct loop *loop;
rtx reg;
{ {
rtx insn, label; rtx insn, label;
enum rtx_code code; enum rtx_code code;
int jump_count = 0; int jump_count = 0;
int label_count = 0; int label_count = 0;
struct loop *loop = uid_loop[INSN_UID (loop_start)];
/* In addition to checking all exits of this loop, we must also check /* In addition to checking all exits of this loop, we must also check
all exits of inner nested loops that would exit this loop. We don't all exits of inner nested loops that would exit this loop. We don't
...@@ -3259,9 +3253,9 @@ reg_dead_after_loop (reg, loop_start, loop_end) ...@@ -3259,9 +3253,9 @@ reg_dead_after_loop (reg, loop_start, loop_end)
return 0; return 0;
/* HACK: Must also search the loop fall through exit, create a label_ref /* HACK: Must also search the loop fall through exit, create a label_ref
here which points to the loop_end, and append the loop_number_exit_labels here which points to the loop->end, and append the loop_number_exit_labels
list to it. */ list to it. */
label = gen_rtx_LABEL_REF (VOIDmode, loop_end); label = gen_rtx_LABEL_REF (VOIDmode, loop->end);
LABEL_NEXTREF (label) = loop->exit_labels; LABEL_NEXTREF (label) = loop->exit_labels;
for ( ; label; label = LABEL_NEXTREF (label)) for ( ; label; label = LABEL_NEXTREF (label))
...@@ -3310,11 +3304,12 @@ reg_dead_after_loop (reg, loop_start, loop_end) ...@@ -3310,11 +3304,12 @@ reg_dead_after_loop (reg, loop_start, loop_end)
the end of the loop. If we can do it, return that value. */ the end of the loop. If we can do it, return that value. */
rtx rtx
final_biv_value (bl, loop_start, loop_end, n_iterations) final_biv_value (loop, bl)
const struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
rtx increment, tem; rtx increment, tem;
/* ??? This only works for MODE_INT biv's. Reject all others for now. */ /* ??? This only works for MODE_INT biv's. Reject all others for now. */
...@@ -3342,12 +3337,12 @@ final_biv_value (bl, loop_start, loop_end, n_iterations) ...@@ -3342,12 +3337,12 @@ final_biv_value (bl, loop_start, loop_end, n_iterations)
value of the biv must be invariant. */ value of the biv must be invariant. */
if (n_iterations != 0 if (n_iterations != 0
&& ! uid_loop[INSN_UID (loop_start)]->exit_count && ! loop->exit_count
&& invariant_p (bl->initial_value)) && loop_invariant_p (loop, bl->initial_value))
{ {
increment = biv_total_increment (bl, loop_start, loop_end); increment = biv_total_increment (bl);
if (increment && invariant_p (increment)) if (increment && loop_invariant_p (loop, increment))
{ {
/* Can calculate the loop exit value, emit insns after loop /* Can calculate the loop exit value, emit insns after loop
end to calculate this value into a temporary register in end to calculate this value into a temporary register in
...@@ -3370,7 +3365,7 @@ final_biv_value (bl, loop_start, loop_end, n_iterations) ...@@ -3370,7 +3365,7 @@ final_biv_value (bl, loop_start, loop_end, n_iterations)
} }
/* Check to see if the biv is dead at all loop exits. */ /* Check to see if the biv is dead at all loop exits. */
if (reg_dead_after_loop (bl->biv->src_reg, loop_start, loop_end)) if (reg_dead_after_loop (loop, bl->biv->src_reg))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3387,15 +3382,16 @@ final_biv_value (bl, loop_start, loop_end, n_iterations) ...@@ -3387,15 +3382,16 @@ final_biv_value (bl, loop_start, loop_end, n_iterations)
the end of the loop. If we can do it, return that value. */ the end of the loop. If we can do it, return that value. */
rtx rtx
final_giv_value (v, loop_start, loop_end, n_iterations) final_giv_value (loop, v)
const struct loop *loop;
struct induction *v; struct induction *v;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
rtx insn; rtx insn;
rtx increment, tem; rtx increment, tem;
rtx insert_before, seq; rtx insert_before, seq;
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 = reg_biv_class[REGNO (v->src_reg)];
...@@ -3422,7 +3418,7 @@ final_giv_value (v, loop_start, loop_end, n_iterations) ...@@ -3422,7 +3418,7 @@ final_giv_value (v, loop_start, loop_end, n_iterations)
to be known. */ to be known. */
if (n_iterations != 0 if (n_iterations != 0
&& ! uid_loop[INSN_UID (loop_start)]->exit_count) && ! loop->exit_count)
{ {
/* ?? It is tempting to use the biv's value here since these insns will /* ?? It is tempting to use the biv's value here since these insns will
be put after the loop, and hence the biv will have its final value be put after the loop, and hence the biv will have its final value
...@@ -3435,10 +3431,10 @@ final_giv_value (v, loop_start, loop_end, n_iterations) ...@@ -3435,10 +3431,10 @@ final_giv_value (v, loop_start, loop_end, n_iterations)
sure that bl->initial_value is still valid then. It will still sure that bl->initial_value is still valid then. It will still
be valid if it is invariant. */ be valid if it is invariant. */
increment = biv_total_increment (bl, loop_start, loop_end); increment = biv_total_increment (bl);
if (increment && invariant_p (increment) if (increment && loop_invariant_p (loop, increment)
&& invariant_p (bl->initial_value)) && loop_invariant_p (loop, bl->initial_value))
{ {
/* Can calculate the loop exit value of its biv as /* Can calculate the loop exit value of its biv as
(n_iterations * increment) + initial_value */ (n_iterations * increment) + initial_value */
...@@ -3495,7 +3491,7 @@ final_giv_value (v, loop_start, loop_end, n_iterations) ...@@ -3495,7 +3491,7 @@ final_giv_value (v, loop_start, loop_end, n_iterations)
abort (); abort ();
/* Check to see if the biv is dead at all loop exits. */ /* Check to see if the biv is dead at all loop exits. */
if (reg_dead_after_loop (v->dest_reg, loop_start, loop_end)) if (reg_dead_after_loop (loop, v->dest_reg))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3509,15 +3505,16 @@ final_giv_value (v, loop_start, loop_end, n_iterations) ...@@ -3509,15 +3505,16 @@ final_giv_value (v, loop_start, loop_end, n_iterations)
} }
/* Look back before LOOP_START for then insn that sets REG and return /* Look back before LOOP->START for then insn that sets REG and return
the equivalent constant if there is a REG_EQUAL note otherwise just the equivalent constant if there is a REG_EQUAL note otherwise just
the SET_SRC of REG. */ the SET_SRC of REG. */
static rtx static rtx
loop_find_equiv_value (loop_start, reg) loop_find_equiv_value (loop, reg)
rtx loop_start; const struct loop *loop;
rtx reg; rtx reg;
{ {
rtx loop_start = loop->start;
rtx insn, set; rtx insn, set;
rtx ret; rtx ret;
...@@ -3678,7 +3675,7 @@ loop_iterations (loop) ...@@ -3678,7 +3675,7 @@ loop_iterations (loop)
branch, and the insn before tests a register value, make that the branch, and the insn before tests a register value, make that the
iteration variable. */ iteration variable. */
comparison = get_condition_for_loop (last_loop_insn); comparison = get_condition_for_loop (loop, last_loop_insn);
if (comparison == 0) if (comparison == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
...@@ -3712,8 +3709,8 @@ loop_iterations (loop) ...@@ -3712,8 +3709,8 @@ loop_iterations (loop)
&& ! REG_USERVAR_P (iteration_var)) && ! REG_USERVAR_P (iteration_var))
abort (); abort ();
iteration_info (iteration_var, &initial_value, &increment, iteration_info (loop, iteration_var, &initial_value, &increment);
loop->start, loop->end);
if (initial_value == 0) if (initial_value == 0)
/* iteration_info already printed a message. */ /* iteration_info already printed a message. */
return 0; return 0;
...@@ -3758,12 +3755,14 @@ loop_iterations (loop) ...@@ -3758,12 +3755,14 @@ loop_iterations (loop)
its value from the insns before the start of the loop. */ its value from the insns before the start of the loop. */
final_value = comparison_value; final_value = comparison_value;
if (GET_CODE (comparison_value) == REG && invariant_p (comparison_value)) if (GET_CODE (comparison_value) == REG
&& loop_invariant_p (loop, comparison_value))
{ {
final_value = loop_find_equiv_value (loop->start, comparison_value); final_value = loop_find_equiv_value (loop, comparison_value);
/* If we don't get an invariant final value, we are better /* If we don't get an invariant final value, we are better
off with the original register. */ off with the original register. */
if (!invariant_p (final_value)) if (! loop_invariant_p (loop, final_value))
final_value = comparison_value; final_value = comparison_value;
} }
...@@ -3820,7 +3819,8 @@ loop_iterations (loop) ...@@ -3820,7 +3819,8 @@ loop_iterations (loop)
/* Find what reg1 is equivalent to. Hopefully it will /* Find what reg1 is equivalent to. Hopefully it will
either be reg2 or reg2 plus a constant. */ either be reg2 or reg2 plus a constant. */
temp = loop_find_equiv_value (loop->start, reg1); temp = loop_find_equiv_value (loop, reg1);
if (find_common_reg_term (temp, reg2)) if (find_common_reg_term (temp, reg2))
initial_value = temp; initial_value = temp;
else else
...@@ -3828,7 +3828,8 @@ loop_iterations (loop) ...@@ -3828,7 +3828,8 @@ loop_iterations (loop)
/* Find what reg2 is equivalent to. Hopefully it will /* Find what reg2 is equivalent to. Hopefully it will
either be reg1 or reg1 plus a constant. Let's ignore either be reg1 or reg1 plus a constant. Let's ignore
the latter case for now since it is not so common. */ the latter case for now since it is not so common. */
temp = loop_find_equiv_value (loop->start, reg2); temp = loop_find_equiv_value (loop, reg2);
if (temp == loop_info->iteration_var) if (temp == loop_info->iteration_var)
temp = initial_value; temp = initial_value;
if (temp == reg1) if (temp == reg1)
...@@ -3847,10 +3848,12 @@ loop_iterations (loop) ...@@ -3847,10 +3848,12 @@ loop_iterations (loop)
where temp2 = init + const. If the loop has a vtop we where temp2 = init + const. If the loop has a vtop we
can replace initial_value with const. */ can replace initial_value with const. */
temp = loop_find_equiv_value (loop->start, reg1); temp = loop_find_equiv_value (loop, reg1);
if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0))) if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0)))
{ {
rtx temp2 = loop_find_equiv_value (loop->start, XEXP (temp, 0)); rtx temp2 = loop_find_equiv_value (loop, XEXP (temp, 0));
if (GET_CODE (temp2) == PLUS if (GET_CODE (temp2) == PLUS
&& XEXP (temp2, 0) == XEXP (temp, 1)) && XEXP (temp2, 0) == XEXP (temp, 1))
initial_value = XEXP (temp2, 1); initial_value = XEXP (temp2, 1);
...@@ -3897,7 +3900,7 @@ loop_iterations (loop) ...@@ -3897,7 +3900,7 @@ loop_iterations (loop)
/* ??? Other RTL, such as (neg (reg)) is possible here, but it isn't /* ??? Other RTL, such as (neg (reg)) is possible here, but it isn't
clear if it is worthwhile to try to handle such RTL. */ clear if it is worthwhile to try to handle such RTL. */
if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG) if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG)
increment = loop_find_equiv_value (loop->start, increment); increment = loop_find_equiv_value (loop, increment);
if (GET_CODE (increment) != CONST_INT) if (GET_CODE (increment) != CONST_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