Commit a2be868f by Michael Hayes Committed by Michael Hayes

loop.c (this_loop_info): Delete.

	* loop.c (this_loop_info): Delete.
	(uid_loop): Add in place of uid_loop_num.  All uses updated.
 	(loop_number_exit_count): Delete and replace with entry in loop
	structure.  All uses updated.
	(loop_number_loop_starts, loop_number_loop_ends): Likewise.
	(loop_number_loop_cont, loop_number_cont_dominator): Likewise.
	(loop_outer_loop): Likewise.
	(loop_invalid, loop_number_exit_labels): Likewise.
	(loop_used_count_register): Delete and replace with entry in
	loop_info structure.
	(find_and_verify_loops): Add loops argument.
	(verify_dominator, mark_loop_jump, prescan_loop): Replace loop_start,
	loop_end, etc. arguments with loop structure pointer.  All callers
	changed.
	(loop_reg_used_before_p, scan_loop, strength_reduce): Likewise.
	(check_dbra_loop, next_insn_in_loop, try_copy_prop): Likewise.
	(load_mems_and_recount_loop_regs_set, load_mems): Likewise.
	(insert_bct): Likewise.
	(basic_induction_var): New argument level.
	* loop.h (struct loop_info): Delete fields num, loops_enclosed,
	vtop, and cont.  Add used_count_register.
	(uid_loop): Delete declaration.
 	(loop_number_exit_count): Likewise.
	(loop_number_loop_starts, loop_number_loop_ends): Likewise.
	(loop_number_loop_cont, loop_number_cont_dominator): Likewise.
	(loop_outer_loop, loop_used_count_register): Likewise.
	(loop_invalid, loop_number_exit_labels): Likewise.
	(unroll_loop): Replace loop_start and loop_end arguments
 	with loop structure pointer.
	(loop_precondition_p, loop_iterations): Likewise.
	Include basic-block.h.
	* unroll.c: (unroll_loop): Replace loop_start and loop_end arguments
 	with loop structure pointer.
	(loop_precondition_p, loop_iterations): Likewise.
	* basic-block.h (struct loop): New entries vtop, cont,
 	cont_dominator, start, end, top, scan_start, exit_labels,
	exit_count.
	* Makefile.in (LOOP_H): Add basic-block.h to dependencies.

From-SVN: r31434
parent d07ecc3b
2000-01-15 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* loop.c (this_loop_info): Delete.
(uid_loop): Add in place of uid_loop_num. All uses updated.
(loop_number_exit_count): Delete and replace with entry in loop
structure. All uses updated.
(loop_number_loop_starts, loop_number_loop_ends): Likewise.
(loop_number_loop_cont, loop_number_cont_dominator): Likewise.
(loop_outer_loop): Likewise.
(loop_invalid, loop_number_exit_labels): Likewise.
(loop_used_count_register): Delete and replace with entry in
loop_info structure.
(find_and_verify_loops): Add loops argument.
(verify_dominator, mark_loop_jump, prescan_loop): Replace loop_start,
loop_end, etc. arguments with loop structure pointer. All callers
changed.
(loop_reg_used_before_p, scan_loop, strength_reduce): Likewise.
(check_dbra_loop, next_insn_in_loop, try_copy_prop): Likewise.
(load_mems_and_recount_loop_regs_set, load_mems): Likewise.
(insert_bct): Likewise.
(basic_induction_var): New argument level.
* loop.h (struct loop_info): Delete fields num, loops_enclosed,
vtop, and cont. Add used_count_register.
(uid_loop): Delete declaration.
(loop_number_exit_count): Likewise.
(loop_number_loop_starts, loop_number_loop_ends): Likewise.
(loop_number_loop_cont, loop_number_cont_dominator): Likewise.
(loop_outer_loop, loop_used_count_register): Likewise.
(loop_invalid, loop_number_exit_labels): Likewise.
(unroll_loop): Replace loop_start and loop_end arguments
with loop structure pointer.
(loop_precondition_p, loop_iterations): Likewise.
Include basic-block.h.
* unroll.c: (unroll_loop): Replace loop_start and loop_end arguments
with loop structure pointer.
(loop_precondition_p, loop_iterations): Likewise.
* basic-block.h (struct loop): New entries vtop, cont,
cont_dominator, start, end, top, scan_start, exit_labels,
exit_count.
* Makefile.in (LOOP_H): Add basic-block.h to dependencies.
2000-01-15 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at> 2000-01-15 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
* defaults.h (ASM_OUTPUT_ASCII): Use ISDIGIT. * defaults.h (ASM_OUTPUT_ASCII): Use ISDIGIT.
......
...@@ -756,7 +756,7 @@ RECOG_H = recog.h ...@@ -756,7 +756,7 @@ RECOG_H = recog.h
EXPR_H = expr.h insn-codes.h EXPR_H = expr.h insn-codes.h
REGS_H = regs.h varray.h $(MACHMODE_H) REGS_H = regs.h varray.h $(MACHMODE_H)
INTEGRATE_H = integrate.h varray.h INTEGRATE_H = integrate.h varray.h
LOOP_H = loop.h varray.h LOOP_H = loop.h varray.h basic-block.h
# #
# Language makefile fragments. # Language makefile fragments.
......
...@@ -275,6 +275,47 @@ struct loop ...@@ -275,6 +275,47 @@ struct loop
/* Auxiliary info specific to a pass. */ /* Auxiliary info specific to a pass. */
void *info; void *info;
/* The following are currently used by loop.c but they are likely to
disappear as loop.c is converted to use the CFG. */
/* Non-zero if the loop has a NOTE_INSN_LOOP_VTOP. */
rtx vtop;
/* Non-zero if the loop has a NOTE_INSN_LOOP_CONT.
A continue statement will generate a branch to NEXT_INSN (cont). */
rtx cont;
/* The dominator of cont. */
rtx cont_dominator;
/* The NOTE_INSN_LOOP_BEG. */
rtx start;
/* The NOTE_INSN_LOOP_END. */
rtx end;
/* For a rotated loop that is entered near the bottom,
this is the label at the top. Otherwise it is zero. */
rtx top;
/* Place in the loop where control enters. */
rtx scan_start;
/* List of all LABEL_REFs which refer to code labels outside the
loop. Used by routines that need to know all loop exits, such as
final_biv_value and final_giv_value.
This does not include loop exits due to return instructions.
This is because all bivs and givs are pseudos, and hence must be
dead after a return, so the presense of a return does not affect
any of the optimizations that use this info. It is simpler to
just not include return instructions on this list. */
rtx exit_labels;
/* The number of LABEL_REFs on exit_labels for this loop and all
loops nested inside it. */
int exit_count;
}; };
......
...@@ -56,7 +56,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -56,7 +56,7 @@ Boston, MA 02111-1307, USA. */
/* Information about the loop being processed used to compute /* Information about the loop being processed used to compute
the number of loop iterations for loop unrolling and doloop the number of loop iterations for loop unrolling and doloop
optimization. */ optimization. */
static struct loop_info this_loop_info; static struct loop_info loop_info_data;
/* 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.
...@@ -67,7 +67,7 @@ int *uid_luid; ...@@ -67,7 +67,7 @@ int *uid_luid;
/* Indexed by INSN_UID, contains the ordinal giving the (innermost) loop /* Indexed by INSN_UID, contains the ordinal giving the (innermost) loop
number the insn is contained in. */ number the insn is contained in. */
int *uid_loop_num; struct loop **uid_loop;
/* 1 + largest uid of any insn. */ /* 1 + largest uid of any insn. */
...@@ -82,52 +82,6 @@ static int max_luid; ...@@ -82,52 +82,6 @@ static int max_luid;
static int max_loop_num; static int max_loop_num;
/* Indexed by loop number, contains the first and last insn of each loop. */
static rtx *loop_number_loop_starts, *loop_number_loop_ends;
/* Likewise for the continue insn */
static rtx *loop_number_loop_cont;
/* The first code_label that is reached in every loop iteration.
0 when not computed yet, initially const0_rtx if a jump couldn't be
followed.
Also set to 0 when there is no such label before the NOTE_INSN_LOOP_CONT
of this loop, or in verify_dominator, if a jump couldn't be followed. */
static rtx *loop_number_cont_dominator;
/* For each loop, gives the containing loop number, -1 if none. */
int *loop_outer_loop;
#ifdef HAVE_decrement_and_branch_on_count
/* Records whether resource in use by inner loop. */
int *loop_used_count_register;
#endif /* HAVE_decrement_and_branch_on_count */
/* Indexed by loop number, contains a nonzero value if the "loop" isn't
really a loop (an insn outside the loop branches into it). */
static char *loop_invalid;
/* Indexed by loop number, links together all LABEL_REFs which refer to
code labels outside the loop. Used by routines that need to know all
loop exits, such as final_biv_value and final_giv_value.
This does not include loop exits due to return instructions. This is
because all bivs and givs are pseudos, and hence must be dead after a
return, so the presense of a return does not affect any of the
optimizations that use this info. It is simpler to just not include return
instructions on this list. */
rtx *loop_number_exit_labels;
/* Indexed by loop number, counts the number of LABEL_REFs on
loop_number_exit_labels for this loop and all loops nested inside it. */
int *loop_number_exit_count;
/* Indexed by register number, contains the number of times the reg /* Indexed by register number, contains the number of times the reg
is set during the loop being scanned. is set during the loop being scanned.
During code motion, a negative value indicates a reg that has been During code motion, a negative value indicates a reg that has been
...@@ -280,10 +234,10 @@ FILE *loop_dump_stream; ...@@ -280,10 +234,10 @@ FILE *loop_dump_stream;
/* Forward declarations. */ /* Forward declarations. */
static void verify_dominator PROTO((int)); static void verify_dominator PROTO((struct loop *));
static void find_and_verify_loops PROTO((rtx)); static void find_and_verify_loops PROTO((rtx, struct loops *));
static void mark_loop_jump PROTO((rtx, int)); static void mark_loop_jump PROTO((rtx, struct loop *));
static void prescan_loop PROTO((rtx, rtx, struct loop_info *)); static void prescan_loop PROTO((struct loop *));
static int reg_in_basic_block_p PROTO((rtx, rtx)); static int reg_in_basic_block_p PROTO((rtx, rtx));
static int consec_sets_invariant_p PROTO((rtx, int, rtx)); static int consec_sets_invariant_p PROTO((rtx, int, rtx));
static int labels_in_range_p PROTO((rtx, int)); static int labels_in_range_p PROTO((rtx, int));
...@@ -293,8 +247,8 @@ static void count_loop_regs_set PROTO((rtx, rtx, varray_type, varray_type, ...@@ -293,8 +247,8 @@ static void count_loop_regs_set PROTO((rtx, rtx, varray_type, varray_type,
int *, int)); int *, int));
static void note_addr_stored PROTO((rtx, rtx, void *)); static void note_addr_stored PROTO((rtx, rtx, void *));
static void note_set_pseudo_multiple_uses PROTO((rtx, rtx, void *)); static void note_set_pseudo_multiple_uses PROTO((rtx, rtx, void *));
static int loop_reg_used_before_p PROTO((rtx, rtx, rtx, rtx, rtx)); static int loop_reg_used_before_p PROTO((const struct loop *, rtx, rtx));
static void scan_loop PROTO((rtx, rtx, rtx, int, int)); static void scan_loop PROTO((struct loop*, int, int));
#if 0 #if 0
static void replace_call_address PROTO((rtx, rtx, rtx)); static void replace_call_address PROTO((rtx, rtx, rtx));
#endif #endif
...@@ -308,8 +262,7 @@ static int rtx_equal_for_loop_p PROTO((rtx, rtx, struct movable *)); ...@@ -308,8 +262,7 @@ static int rtx_equal_for_loop_p PROTO((rtx, rtx, struct movable *));
static void add_label_notes PROTO((rtx, rtx)); static void add_label_notes PROTO((rtx, rtx));
static void move_movables PROTO((struct movable *, int, int, rtx, rtx, int)); static void move_movables PROTO((struct movable *, int, int, rtx, rtx, int));
static int count_nonfixed_reads PROTO((rtx)); static int count_nonfixed_reads PROTO((rtx));
static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx, static void strength_reduce PROTO((struct loop *, int, int, int));
struct loop_info *, rtx, int, int));
static void find_single_use_in_loop PROTO((rtx, rtx, varray_type)); static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
static int valid_initial_value_p PROTO((rtx, rtx, int, rtx)); static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
static void find_mem_givs PROTO((rtx, rtx, int, int, rtx, rtx)); static void find_mem_givs PROTO((rtx, rtx, int, int, rtx, rtx));
...@@ -318,11 +271,11 @@ static void check_final_value PROTO((struct induction *, rtx, rtx, ...@@ -318,11 +271,11 @@ static void check_final_value PROTO((struct induction *, rtx, rtx,
unsigned HOST_WIDE_INT)); unsigned HOST_WIDE_INT));
static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, int, rtx *, rtx, rtx)); static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, int, rtx *, rtx, rtx));
static void update_giv_derive PROTO((rtx)); static void update_giv_derive PROTO((rtx));
static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **, int *)); static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, int, rtx *, rtx *, rtx **, int *));
static rtx simplify_giv_expr PROTO((rtx, int *)); static rtx simplify_giv_expr PROTO((rtx, int *));
static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *)); static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *));
static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *)); static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
static int check_dbra_loop PROTO((rtx, int, rtx, struct loop_info *)); static int check_dbra_loop PROTO((struct loop *, int));
static rtx express_from_1 PROTO((rtx, rtx, rtx)); static rtx express_from_1 PROTO((rtx, rtx, rtx));
static rtx combine_givs_p PROTO((struct induction *, struct induction *)); static rtx combine_givs_p PROTO((struct induction *, struct induction *));
static void combine_givs PROTO((struct iv_class *)); static void combine_givs PROTO((struct iv_class *));
...@@ -335,15 +288,15 @@ static int maybe_eliminate_biv_1 PROTO((rtx, rtx, struct iv_class *, int, rtx)); ...@@ -335,15 +288,15 @@ static int maybe_eliminate_biv_1 PROTO((rtx, rtx, struct iv_class *, int, rtx));
static int last_use_this_basic_block PROTO((rtx, rtx)); static int last_use_this_basic_block PROTO((rtx, rtx));
static void record_initial PROTO((rtx, rtx, void *)); static void record_initial PROTO((rtx, rtx, void *));
static void update_reg_last_use PROTO((rtx, rtx)); static void update_reg_last_use PROTO((rtx, rtx));
static rtx next_insn_in_loop PROTO((rtx, rtx, rtx, rtx)); static rtx next_insn_in_loop PROTO((const struct loop *, rtx));
static void load_mems_and_recount_loop_regs_set PROTO((rtx, rtx, rtx, static void load_mems_and_recount_loop_regs_set PROTO((const struct loop*,
rtx, int *)); int *));
static void load_mems PROTO((rtx, rtx, rtx, rtx)); static void load_mems PROTO((const struct loop *));
static int insert_loop_mem PROTO((rtx *, void *)); static int insert_loop_mem PROTO((rtx *, void *));
static int replace_loop_mem PROTO((rtx *, void *)); static int replace_loop_mem PROTO((rtx *, void *));
static int replace_loop_reg PROTO((rtx *, void *)); static int replace_loop_reg PROTO((rtx *, void *));
static void note_reg_stored PROTO((rtx, rtx, void *)); static void note_reg_stored PROTO((rtx, rtx, void *));
static void try_copy_prop PROTO((rtx, rtx, rtx, rtx, int)); static void try_copy_prop PROTO((const struct loop *, rtx, int));
static int replace_label PROTO((rtx *, void *)); static int replace_label PROTO((rtx *, void *));
typedef struct rtx_and_int { typedef struct rtx_and_int {
...@@ -364,7 +317,7 @@ typedef struct rtx_pair { ...@@ -364,7 +317,7 @@ typedef struct rtx_pair {
#ifdef HAVE_decrement_and_branch_on_count #ifdef HAVE_decrement_and_branch_on_count
/* Test whether BCT applicable and safe. */ /* Test whether BCT applicable and safe. */
static void insert_bct PROTO((rtx, rtx, struct loop_info *)); static void insert_bct PROTO((struct loop *));
/* Auxiliary function that inserts the BCT pattern into the loop. */ /* Auxiliary function that inserts the BCT pattern into the loop. */
static void instrument_loop_bct PROTO((rtx, rtx, rtx)); static void instrument_loop_bct PROTO((rtx, rtx, rtx));
...@@ -464,6 +417,8 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -464,6 +417,8 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
{ {
register rtx insn; register rtx insn;
register int i; register int i;
struct loops loops_data;
struct loops *loops = &loops_data;
loop_dump_stream = dumpfile; loop_dump_stream = dumpfile;
...@@ -488,6 +443,8 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -488,6 +443,8 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
if (max_loop_num == 0) if (max_loop_num == 0)
return; return;
loops->num = max_loop_num;
moved_once = (char *) xcalloc (max_reg_before_loop, sizeof (char)); moved_once = (char *) xcalloc (max_reg_before_loop, sizeof (char));
/* Get size to use for tables indexed by uids. /* Get size to use for tables indexed by uids.
...@@ -495,27 +452,12 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -495,27 +452,12 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32; max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32;
uid_luid = (int *) xcalloc (max_uid_for_loop, sizeof (int)); uid_luid = (int *) xcalloc (max_uid_for_loop, sizeof (int));
uid_loop_num = (int *) xcalloc (max_uid_for_loop, sizeof (int)); uid_loop = (struct loop **) xcalloc (max_uid_for_loop,
sizeof (struct loop *));
/* Allocate tables for recording each loop. We set each entry, so they need
not be zeroed. */
loop_number_loop_starts = (rtx *) xmalloc (max_loop_num * sizeof (rtx));
loop_number_loop_ends = (rtx *) xmalloc (max_loop_num * sizeof (rtx));
loop_number_loop_cont = (rtx *) xmalloc (max_loop_num * sizeof (rtx));
loop_number_cont_dominator = (rtx *) xmalloc (max_loop_num * sizeof (rtx));
loop_outer_loop = (int *) xmalloc (max_loop_num * sizeof (int));
loop_invalid = (char *) xmalloc (max_loop_num * sizeof (char));
loop_number_exit_labels = (rtx *) xmalloc (max_loop_num * sizeof (rtx));
loop_number_exit_count = (int *) xmalloc (max_loop_num * sizeof (int));
#ifdef HAVE_decrement_and_branch_on_count
/* Allocate for BCT optimization */
loop_used_count_register = (int *) xcalloc (max_loop_num, sizeof (int));
#endif /* HAVE_decrement_and_branch_on_count */
/* Find and process each loop. /* Find and process each loop.
First, find them, and record them in order of their beginnings. */ First, find them, and record them in order of their beginnings. */
find_and_verify_loops (f); find_and_verify_loops (f, loops);
/* Now find all register lifetimes. This must be done after /* Now find all register lifetimes. This must be done after
find_and_verify_loops, because it might reorder the insns in the find_and_verify_loops, because it might reorder the insns in the
...@@ -536,8 +478,9 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -536,8 +478,9 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
/* Now reset it to the actual size we need. See above. */ /* Now reset it to the actual size we need. See above. */
max_uid_for_loop = get_max_uid (); max_uid_for_loop = get_max_uid ();
/* find_and_verify_loops has already called compute_luids, but it might /* find_and_verify_loops has already called compute_luids, but it
have rearranged code afterwards, so we need to recompute the luids now. */ might have rearranged code afterwards, so we need to recompute
the luids now. */
max_luid = compute_luids (f, NULL_RTX, 0); max_luid = compute_luids (f, NULL_RTX, 0);
/* Don't leave gaps in uid_luid for insns that have been /* Don't leave gaps in uid_luid for insns that have been
...@@ -569,10 +512,13 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -569,10 +512,13 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
/* Now scan the loops, last ones first, since this means inner ones are done /* Now scan the loops, last ones first, since this means inner ones are done
before outer ones. */ before outer ones. */
for (i = max_loop_num-1; i >= 0; i--) for (i = max_loop_num - 1; i >= 0; i--)
if (! loop_invalid[i] && loop_number_loop_ends[i]) {
scan_loop (loop_number_loop_starts[i], loop_number_loop_ends[i], struct loop *loop = &loops->array[i];
loop_number_loop_cont[i], unroll_p, bct_p);
if (! loop->invalid && loop->end)
scan_loop (loop, unroll_p, bct_p);
}
/* Replicate the BLOCKs. */ /* Replicate the BLOCKs. */
if (write_symbols != NO_DEBUG) if (write_symbols != NO_DEBUG)
...@@ -583,19 +529,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -583,19 +529,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
/* Clean up. */ /* Clean up. */
free (moved_once); free (moved_once);
free (uid_luid); free (uid_luid);
free (uid_loop_num); free (uid_loop);
free (loop_number_loop_starts);
free (loop_number_loop_ends);
free (loop_number_loop_cont);
free (loop_number_cont_dominator);
free (loop_outer_loop);
free (loop_invalid);
free (loop_number_exit_labels);
free (loop_number_exit_count);
#ifdef HAVE_decrement_and_branch_on_count
free (loop_used_count_register);
#endif /* HAVE_decrement_and_branch_on_count */
} }
/* Returns the next insn, in execution order, after INSN. START and /* Returns the next insn, in execution order, after INSN. START and
...@@ -605,35 +539,30 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -605,35 +539,30 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
bottom. */ bottom. */
static rtx static rtx
next_insn_in_loop (insn, start, end, loop_top) next_insn_in_loop (loop, insn)
const struct loop *loop;
rtx insn; rtx insn;
rtx start;
rtx end;
rtx loop_top;
{ {
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
if (insn == end) if (insn == loop->end)
{ {
if (loop_top) if (loop->top)
/* Go to the top of the loop, and continue there. */ /* Go to the top of the loop, and continue there. */
insn = loop_top; insn = loop->top;
else else
/* We're done. */ /* We're done. */
insn = NULL_RTX; insn = NULL_RTX;
} }
if (insn == start) if (insn == loop->scan_start)
/* We're done. */ /* We're done. */
insn = NULL_RTX; insn = NULL_RTX;
return insn; return insn;
} }
/* Optimize one loop whose start is LOOP_START and end is END. /* Optimize one loop described by LOOP. */
LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching
NOTE_INSN_LOOP_END.
LOOP_CONT is the NOTE_INSN_LOOP_CONT. */
/* ??? Could also move memory writes out of loops if the destination address /* ??? Could also move memory writes out of loops if the destination address
is invariant, the source is invariant, the memory write is not volatile, is invariant, the source is invariant, the memory write is not volatile,
...@@ -642,24 +571,21 @@ next_insn_in_loop (insn, start, end, loop_top) ...@@ -642,24 +571,21 @@ next_insn_in_loop (insn, start, end, loop_top)
write, then we can also mark the memory read as invariant. */ write, then we can also mark the memory read as invariant. */
static void static void
scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) scan_loop (loop, unroll_p, bct_p)
rtx loop_start, end, loop_cont; struct loop *loop;
int unroll_p, bct_p; int unroll_p, bct_p;
{ {
register int i; register int i;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
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. */
int maybe_never = 0; int maybe_never = 0;
/* 1 if we are scanning insns that might never be executed /* 1 if we are scanning insns that might never be executed
due to a subroutine call which might exit before they are reached. */ due to a subroutine call which might exit before they are reached. */
int call_passed = 0; int call_passed = 0;
/* For a rotated loop that is entered near the bottom,
this is the label at the top. Otherwise it is zero. */
rtx loop_top = 0;
/* Jump insn that enters the loop, or 0 if control drops in. */ /* Jump insn that enters the loop, or 0 if control drops in. */
rtx loop_entry_jump = 0; rtx loop_entry_jump = 0;
/* Place in the loop where control enters. */
rtx scan_start;
/* Number of insns in the loop. */ /* Number of insns in the loop. */
int insn_count; int insn_count;
int in_libcall = 0; int in_libcall = 0;
...@@ -679,7 +605,10 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -679,7 +605,10 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
/* Nonzero if we are scanning instructions in a sub-loop. */ /* Nonzero if we are scanning instructions in a sub-loop. */
int loop_depth = 0; int loop_depth = 0;
int nregs; int nregs;
struct loop_info *loop_info = &this_loop_info; struct loop_info *loop_info = &loop_info_data;
loop->info = loop_info;
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
the end. This will occur for a small number of loops with a test the end. This will occur for a small number of loops with a test
...@@ -698,7 +627,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -698,7 +627,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
exit test, the code here to detect that case is very conservative. */ exit test, the code here to detect that case is very conservative. */
for (p = NEXT_INSN (loop_start); for (p = NEXT_INSN (loop_start);
p != end p != loop_end
&& GET_CODE (p) != CODE_LABEL && GET_RTX_CLASS (GET_CODE (p)) != 'i' && GET_CODE (p) != CODE_LABEL && GET_RTX_CLASS (GET_CODE (p)) != 'i'
&& (GET_CODE (p) != NOTE && (GET_CODE (p) != NOTE
|| (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG || (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG
...@@ -706,16 +635,16 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -706,16 +635,16 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
p = NEXT_INSN (p)) p = NEXT_INSN (p))
; ;
scan_start = p; loop->scan_start = p;
/* Set up variables describing this loop. */ /* Set up variables describing this loop. */
prescan_loop (loop_start, end, loop_info); prescan_loop (loop);
threshold = (loop_info->has_call ? 1 : 2) * (1 + n_non_fixed_regs); threshold = (loop_info->has_call ? 1 : 2) * (1 + n_non_fixed_regs);
/* If loop has a jump before the first label, /* If loop has a jump before the first label,
the true entry is the target of that jump. the true entry is the target of that jump.
Start scan from there. Start scan from there.
But record in LOOP_TOP the place where the end-test jumps But record in LOOP->TOP the place where the end-test jumps
back to so we can scan that after the end of the loop. */ back to so we can scan that after the end of the loop. */
if (GET_CODE (p) == JUMP_INSN) if (GET_CODE (p) == JUMP_INSN)
{ {
...@@ -730,14 +659,14 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -730,14 +659,14 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
do {..} while (0). If this label was generated previously do {..} while (0). If this label was generated previously
by loop, we can't tell anything about it and have to reject by loop, we can't tell anything about it and have to reject
the loop. */ the loop. */
&& INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, end)) && INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, loop_end))
{ {
loop_top = next_label (scan_start); loop->top = next_label (loop->scan_start);
scan_start = JUMP_LABEL (p); loop->scan_start = JUMP_LABEL (p);
} }
} }
/* If SCAN_START was an insn created by loop, we don't know its luid /* If LOOP->SCAN_START was an insn created by loop, we don't know its luid
as required by loop_reg_used_before_p. So skip such loops. (This as required by loop_reg_used_before_p. So skip such loops. (This
test may never be true, but it's best to play it safe.) test may never be true, but it's best to play it safe.)
...@@ -745,12 +674,12 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -745,12 +674,12 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
test also rejects loops starting with a JUMP_INSN that failed the test also rejects loops starting with a JUMP_INSN that failed the
test above. */ test above. */
if (INSN_UID (scan_start) >= max_uid_for_loop if (INSN_UID (loop->scan_start) >= max_uid_for_loop
|| GET_CODE (scan_start) != CODE_LABEL) || GET_CODE (loop->scan_start) != CODE_LABEL)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n", fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n",
INSN_UID (loop_start), INSN_UID (end)); INSN_UID (loop_start), INSN_UID (loop_end));
return; return;
} }
...@@ -769,7 +698,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -769,7 +698,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
VARRAY_CHAR_INIT (may_not_optimize, nregs, "may_not_optimize"); VARRAY_CHAR_INIT (may_not_optimize, nregs, "may_not_optimize");
VARRAY_RTX_INIT (reg_single_usage, nregs, "reg_single_usage"); VARRAY_RTX_INIT (reg_single_usage, nregs, "reg_single_usage");
count_loop_regs_set (loop_top ? loop_top : loop_start, end, count_loop_regs_set (loop->top ? loop->top : loop->start, loop->end,
may_not_optimize, reg_single_usage, &insn_count, nregs); may_not_optimize, reg_single_usage, &insn_count, nregs);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
...@@ -792,10 +721,10 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -792,10 +721,10 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
if (loop_dump_stream) if (loop_dump_stream)
{ {
fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n", fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
INSN_UID (loop_start), INSN_UID (end), insn_count); INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
if (loop_info->cont) if (loop->cont)
fprintf (loop_dump_stream, "Continue at insn %d.\n", fprintf (loop_dump_stream, "Continue at insn %d.\n",
INSN_UID (loop_info->cont)); INSN_UID (loop->cont));
} }
/* Scan through the loop finding insns that are safe to move. /* Scan through the loop finding insns that are safe to move.
...@@ -811,9 +740,9 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -811,9 +740,9 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
When MAYBE_NEVER is 0, all insns will be executed at least once When MAYBE_NEVER is 0, all insns will be executed at least once
so that is not a problem. */ so that is not a problem. */
for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top); for (p = next_insn_in_loop (loop, loop->scan_start);
p != NULL_RTX; p != NULL_RTX;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
if (GET_RTX_CLASS (GET_CODE (p)) == 'i' if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& find_reg_note (p, REG_LIBCALL, NULL_RTX)) && find_reg_note (p, REG_LIBCALL, NULL_RTX))
...@@ -879,8 +808,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -879,8 +808,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
each time for register usage, we should build tables each time for register usage, we should build tables
of the register usage and use them here instead. */ of the register usage and use them here instead. */
&& (maybe_never && (maybe_never
|| loop_reg_used_before_p (set, p, loop_start, || loop_reg_used_before_p (loop, set, p)))
scan_start, end)))
/* It is unsafe to move the set. /* It is unsafe to move the set.
This code used to consider it OK to move a set of a variable This code used to consider it OK to move a set of a variable
...@@ -980,7 +908,8 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -980,7 +908,8 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
/* Set M->cond if either invariant_p or consec_sets_invariant_p /* Set M->cond if either invariant_p or consec_sets_invariant_p
returned 2 (only conditionally invariant). */ returned 2 (only conditionally invariant). */
m->cond = ((tem | tem1 | tem2) > 1); m->cond = ((tem | tem1 | tem2) > 1);
m->global = (uid_luid[REGNO_LAST_UID (regno)] > INSN_LUID (end) m->global = (uid_luid[REGNO_LAST_UID (regno)]
> INSN_LUID (loop_end)
|| uid_luid[REGNO_FIRST_UID (regno)] < INSN_LUID (loop_start)); || uid_luid[REGNO_FIRST_UID (regno)] < INSN_LUID (loop_start));
m->match = 0; m->match = 0;
m->lifetime = (uid_luid[REGNO_LAST_UID (regno)] m->lifetime = (uid_luid[REGNO_LAST_UID (regno)]
...@@ -1082,7 +1011,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -1082,7 +1011,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
assumption. */ assumption. */
m->global = (INSN_UID (p) >= max_uid_for_loop m->global = (INSN_UID (p) >= max_uid_for_loop
|| (uid_luid[REGNO_LAST_UID (regno)] || (uid_luid[REGNO_LAST_UID (regno)]
> INSN_LUID (end)) > INSN_LUID (loop_end))
|| (uid_luid[REGNO_FIRST_UID (regno)] || (uid_luid[REGNO_FIRST_UID (regno)]
< INSN_LUID (p)) < INSN_LUID (p))
|| (labels_in_range_p || (labels_in_range_p
...@@ -1125,8 +1054,8 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -1125,8 +1054,8 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
unconditional jump, otherwise the code at the top of the unconditional jump, otherwise the code at the top of the
loop might never be executed. Unconditional jumps are loop might never be executed. Unconditional jumps are
followed a by barrier then loop end. */ followed a by barrier then loop end. */
&& ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop_top && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
&& NEXT_INSN (NEXT_INSN (p)) == end && NEXT_INSN (NEXT_INSN (p)) == loop_end
&& simplejump_p (p))) && simplejump_p (p)))
maybe_never = 1; maybe_never = 1;
else if (GET_CODE (p) == NOTE) else if (GET_CODE (p) == NOTE)
...@@ -1169,7 +1098,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -1169,7 +1098,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
if (! optimize_size) if (! optimize_size)
move_movables (movables, threshold, move_movables (movables, threshold,
insn_count, loop_start, end, 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. */
...@@ -1179,14 +1108,13 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -1179,14 +1108,13 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
/* Now that we've moved some things out of the loop, we might be able to /* Now that we've moved some things out of the loop, we might be able to
hoist even more memory references. */ hoist even more memory references. */
load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, load_mems_and_recount_loop_regs_set (loop, &insn_count);
loop_start, &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 (end); update_end = NEXT_INSN (loop_end);
reg_scan_update (update_start, update_end, loop_max_reg); reg_scan_update (update_start, update_end, loop_max_reg);
loop_max_reg = max_reg_num (); loop_max_reg = max_reg_num ();
...@@ -1194,9 +1122,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p) ...@@ -1194,9 +1122,7 @@ scan_loop (loop_start, end, loop_cont, unroll_p, bct_p)
if (flag_strength_reduce) if (flag_strength_reduce)
{ {
the_movables = movables; the_movables = movables;
strength_reduce (scan_start, end, loop_top, strength_reduce (loop, insn_count, unroll_p, bct_p);
insn_count, loop_start, end,
loop_info, loop_cont, unroll_p, bct_p);
reg_scan_update (update_start, update_end, loop_max_reg); reg_scan_update (update_start, update_end, loop_max_reg);
loop_max_reg = max_reg_num (); loop_max_reg = max_reg_num ();
...@@ -2434,27 +2360,28 @@ constant_high_bytes (p, loop_start) ...@@ -2434,27 +2360,28 @@ constant_high_bytes (p, loop_start)
in the array `loop_mems' and the list `loop_store_mems'. */ in the array `loop_mems' and the list `loop_store_mems'. */
static void static void
prescan_loop (start, end, loop_info) prescan_loop (loop)
rtx start, end; struct loop *loop;
struct loop_info *loop_info;
{ {
register int level = 1; register int level = 1;
rtx insn; rtx insn;
struct loop_info *loop_info = loop->info;
rtx start = loop->start;
rtx end = loop->end;
/* The label after END. Jumping here is just like falling off the /* The label after END. Jumping here is just like falling off the
end of the loop. We use next_nonnote_insn instead of next_label end of the loop. We use next_nonnote_insn instead of next_label
as a hedge against the (pathological) case where some actual insn as a hedge against the (pathological) case where some actual insn
might end up between the two. */ might end up between the two. */
rtx exit_target = next_nonnote_insn (end); rtx exit_target = next_nonnote_insn (end);
loop_info->num = uid_loop_num [INSN_UID (start)];
loop_info->has_indirect_jump = indirect_jump_in_function; loop_info->has_indirect_jump = indirect_jump_in_function;
loop_info->has_call = 0; loop_info->has_call = 0;
loop_info->has_volatile = 0; loop_info->has_volatile = 0;
loop_info->has_tablejump = 0; loop_info->has_tablejump = 0;
loop_info->loops_enclosed = 1;
loop_info->has_multiple_exit_targets = 0; loop_info->has_multiple_exit_targets = 0;
loop_info->cont = 0; loop->cont = 0;
loop_info->vtop = 0; loop->vtop = 0;
loop->level = 1;
unknown_address_altered = 0; unknown_address_altered = 0;
unknown_constant_address_altered = 0; unknown_constant_address_altered = 0;
...@@ -2472,7 +2399,7 @@ prescan_loop (start, end, loop_info) ...@@ -2472,7 +2399,7 @@ prescan_loop (start, end, loop_info)
{ {
++level; ++level;
/* Count number of loops contained in this one. */ /* Count number of loops contained in this one. */
loop_info->loops_enclosed++; loop->level++;
} }
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
{ {
...@@ -2486,7 +2413,7 @@ prescan_loop (start, end, loop_info) ...@@ -2486,7 +2413,7 @@ prescan_loop (start, end, loop_info)
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT) else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
{ {
if (level == 1) if (level == 1)
loop_info->cont = insn; loop->cont = insn;
} }
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP) else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP)
{ {
...@@ -2495,7 +2422,7 @@ prescan_loop (start, end, loop_info) ...@@ -2495,7 +2422,7 @@ prescan_loop (start, end, loop_info)
start. Thus, we can assume that the loop condition start. Thus, we can assume that the loop condition
was true when the loop was entered. */ was true when the loop was entered. */
if (level == 1) if (level == 1)
loop_info->vtop = insn; loop->vtop = insn;
} }
} }
else if (GET_CODE (insn) == CALL_INSN) else if (GET_CODE (insn) == CALL_INSN)
...@@ -2565,48 +2492,47 @@ prescan_loop (start, end, loop_info) ...@@ -2565,48 +2492,47 @@ prescan_loop (start, end, loop_info)
/* Now, rescan the loop, setting up the LOOP_MEMS array. */ /* Now, rescan the loop, setting up the LOOP_MEMS array. */
if (/* We can't tell what MEMs are aliased by what. */ if (/* We can't tell what MEMs are aliased by what. */
!unknown_address_altered ! unknown_address_altered
/* An exception thrown by a called function might land us /* An exception thrown by a called function might land us
anywhere. */ anywhere. */
&& !loop_info->has_call && ! loop_info->has_call
/* We don't want loads for MEMs moved to a location before the /* We don't want loads for MEMs moved to a location before the
one at which their stack memory becomes allocated. (Note one at which their stack memory becomes allocated. (Note
that this is not a problem for malloc, etc., since those that this is not a problem for malloc, etc., since those
require actual function calls. */ require actual function calls. */
&& !current_function_calls_alloca && ! current_function_calls_alloca
/* There are ways to leave the loop other than falling off the /* There are ways to leave the loop other than falling off the
end. */ end. */
&& !loop_info->has_multiple_exit_targets) && ! loop_info->has_multiple_exit_targets)
for (insn = NEXT_INSN (start); insn != NEXT_INSN (end); for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
for_each_rtx (&insn, insert_loop_mem, 0); for_each_rtx (&insn, insert_loop_mem, 0);
} }
/* LOOP_NUMBER_CONT_DOMINATOR is now the last label between the loop start /* LOOP->CONT_DOMINATOR is now the last label between the loop start
and the continue note that is a the destination of a (cond)jump after and the continue note that is a the destination of a (cond)jump after
the continue note. If there is any (cond)jump between the loop start the continue note. If there is any (cond)jump between the loop start
and what we have so far as LOOP_NUMBER_CONT_DOMINATOR that has a and what we have so far as LOOP->CONT_DOMINATOR that has a
target between LOOP_DOMINATOR and the continue note, move target between LOOP->DOMINATOR and the continue note, move
LOOP_NUMBER_CONT_DOMINATOR forward to that label; if a jump's LOOP->CONT_DOMINATOR forward to that label; if a jump's
destination cannot be determined, clear LOOP_NUMBER_CONT_DOMINATOR. */ destination cannot be determined, clear LOOP->CONT_DOMINATOR. */
static void static void
verify_dominator (loop_number) verify_dominator (loop)
int loop_number; struct loop *loop;
{ {
rtx insn; rtx insn;
if (! loop_number_cont_dominator[loop_number]) if (! loop->cont_dominator)
/* This can happen for an empty loop, e.g. in /* This can happen for an empty loop, e.g. in
gcc.c-torture/compile/920410-2.c */ gcc.c-torture/compile/920410-2.c */
return; return;
if (loop_number_cont_dominator[loop_number] == const0_rtx) if (loop->cont_dominator == const0_rtx)
{ {
loop_number_cont_dominator[loop_number] = 0; loop->cont_dominator = 0;
return; return;
} }
for (insn = loop_number_loop_starts[loop_number]; for (insn = loop->start; insn != loop->cont_dominator;
insn != loop_number_cont_dominator[loop_number];
insn = NEXT_INSN (insn)) insn = NEXT_INSN (insn))
{ {
if (GET_CODE (insn) == JUMP_INSN if (GET_CODE (insn) == JUMP_INSN
...@@ -2618,20 +2544,20 @@ verify_dominator (loop_number) ...@@ -2618,20 +2544,20 @@ verify_dominator (loop_number)
/* If it is not a jump we can easily understand or for /* If it is not a jump we can easily understand or for
which we do not have jump target information in the JUMP_LABEL which we do not have jump target information in the JUMP_LABEL
field (consider ADDR_VEC and ADDR_DIFF_VEC insns), then clear field (consider ADDR_VEC and ADDR_DIFF_VEC insns), then clear
LOOP_NUMBER_CONT_DOMINATOR. */ LOOP->CONT_DOMINATOR. */
if ((! condjump_p (insn) if ((! condjump_p (insn)
&& ! condjump_in_parallel_p (insn)) && ! condjump_in_parallel_p (insn))
|| label == NULL_RTX) || label == NULL_RTX)
{ {
loop_number_cont_dominator[loop_number] = NULL_RTX; loop->cont_dominator = NULL_RTX;
return; return;
} }
label_luid = INSN_LUID (label); label_luid = INSN_LUID (label);
if (label_luid < INSN_LUID (loop_number_loop_cont[loop_number]) if (label_luid < INSN_LUID (loop->cont)
&& (label_luid && (label_luid
> INSN_LUID (loop_number_cont_dominator[loop_number]))) > INSN_LUID (loop->cont)))
loop_number_cont_dominator[loop_number] = label; loop->cont_dominator = label;
} }
} }
} }
...@@ -2641,115 +2567,120 @@ verify_dominator (loop_number) ...@@ -2641,115 +2567,120 @@ verify_dominator (loop_number)
to from outside the loop. */ to from outside the loop. */
static void static void
find_and_verify_loops (f) find_and_verify_loops (f, loops)
rtx f; rtx f;
struct loops *loops;
{ {
rtx insn, label; rtx insn;
int current_loop = -1; rtx label;
int next_loop = -1; int num_loops;
int loop; struct loop *current_loop;
struct loop *next_loop;
struct loop *loop;
num_loops = loops->num;
compute_luids (f, NULL_RTX, 0); compute_luids (f, NULL_RTX, 0);
/* If there are jumps to undefined labels, /* If there are jumps to undefined labels,
treat them as jumps out of any/all loops. treat them as jumps out of any/all loops.
This also avoids writing past end of tables when there are no loops. */ This also avoids writing past end of tables when there are no loops. */
uid_loop_num[0] = -1; uid_loop[0] = NULL;
loops->array = (struct loop *)
xmalloc (num_loops * sizeof (struct loop));
bzero ((char *)loops->array, num_loops * sizeof (struct loop));
/* Find boundaries of loops, mark which loops are contained within /* Find boundaries of loops, mark which loops are contained within
loops, and invalidate loops that have setjmp. */ loops, and invalidate loops that have setjmp. */
num_loops = 0;
current_loop = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn)) for (insn = f; insn; insn = NEXT_INSN (insn))
{ {
if (GET_CODE (insn) == NOTE) if (GET_CODE (insn) == NOTE)
switch (NOTE_LINE_NUMBER (insn)) switch (NOTE_LINE_NUMBER (insn))
{ {
case NOTE_INSN_LOOP_BEG: case NOTE_INSN_LOOP_BEG:
loop_number_loop_starts[++next_loop] = insn; next_loop = loops->array + num_loops;
loop_number_loop_ends[next_loop] = 0; next_loop->num = num_loops;
loop_number_loop_cont[next_loop] = 0; num_loops++;
loop_number_cont_dominator[next_loop] = 0; next_loop->start = insn;
loop_outer_loop[next_loop] = current_loop; next_loop->outer = current_loop;
loop_invalid[next_loop] = 0;
loop_number_exit_labels[next_loop] = 0;
loop_number_exit_count[next_loop] = 0;
current_loop = next_loop; current_loop = next_loop;
break; break;
case NOTE_INSN_SETJMP: case NOTE_INSN_SETJMP:
/* In this case, we must invalidate our current loop and any /* In this case, we must invalidate our current loop and any
enclosing loop. */ enclosing loop. */
for (loop = current_loop; loop != -1; loop = loop_outer_loop[loop]) for (loop = current_loop; loop; loop = loop->outer)
{ {
loop_invalid[loop] = 1; loop->invalid = 1;
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"\nLoop at %d ignored due to setjmp.\n", "\nLoop at %d ignored due to setjmp.\n",
INSN_UID (loop_number_loop_starts[loop])); INSN_UID (loop->start));
} }
break; break;
case NOTE_INSN_LOOP_CONT: case NOTE_INSN_LOOP_CONT:
loop_number_loop_cont[current_loop] = insn; current_loop->cont = insn;
break; break;
case NOTE_INSN_LOOP_END: case NOTE_INSN_LOOP_END:
if (current_loop == -1) if (! current_loop)
abort (); abort ();
loop_number_loop_ends[current_loop] = insn; current_loop->end = insn;
verify_dominator (current_loop); verify_dominator (current_loop);
current_loop = loop_outer_loop[current_loop]; current_loop = current_loop->outer;
break; break;
default: default:
break; break;
} }
/* If for any loop, this is a jump insn between the NOTE_INSN_LOOP_CONT /* If for any loop, this is a jump insn between the NOTE_INSN_LOOP_CONT
and NOTE_INSN_LOOP_END notes, update loop_number_loop_dominator. */ and NOTE_INSN_LOOP_END notes, update loop->dominator. */
else if (GET_CODE (insn) == JUMP_INSN else if (GET_CODE (insn) == JUMP_INSN
&& GET_CODE (PATTERN (insn)) != RETURN && GET_CODE (PATTERN (insn)) != RETURN
&& current_loop >= 0) && current_loop)
{ {
int this_loop_num;
rtx label = JUMP_LABEL (insn); rtx label = JUMP_LABEL (insn);
if (! condjump_p (insn) && ! condjump_in_parallel_p (insn)) if (! condjump_p (insn) && ! condjump_in_parallel_p (insn))
label = NULL_RTX; label = NULL_RTX;
this_loop_num = current_loop; loop = current_loop;
do do
{ {
/* First see if we care about this loop. */ /* First see if we care about this loop. */
if (loop_number_loop_cont[this_loop_num] if (loop->cont && loop->cont_dominator != const0_rtx)
&& loop_number_cont_dominator[this_loop_num] != const0_rtx)
{ {
/* If the jump destination is not known, invalidate /* If the jump destination is not known, invalidate
loop_number_const_dominator. */ loop->const_dominator. */
if (! label) if (! label)
loop_number_cont_dominator[this_loop_num] = const0_rtx; loop->cont_dominator = const0_rtx;
else else
/* Check if the destination is between loop start and /* Check if the destination is between loop start and
cont. */ cont. */
if ((INSN_LUID (label) if ((INSN_LUID (label)
< INSN_LUID (loop_number_loop_cont[this_loop_num])) < INSN_LUID (loop->cont))
&& (INSN_LUID (label) && (INSN_LUID (label)
> INSN_LUID (loop_number_loop_starts[this_loop_num])) > INSN_LUID (loop->start))
/* And if there is no later destination already /* And if there is no later destination already
recorded. */ recorded. */
&& (! loop_number_cont_dominator[this_loop_num] && (! loop->cont_dominator
|| (INSN_LUID (label) || (INSN_LUID (label)
> INSN_LUID (loop_number_cont_dominator > INSN_LUID (loop->cont_dominator))))
[this_loop_num])))) loop->cont_dominator = label;
loop_number_cont_dominator[this_loop_num] = label;
} }
this_loop_num = loop_outer_loop[this_loop_num]; loop = loop->outer;
} }
while (this_loop_num >= 0); while (loop);
} }
/* Note that this will mark the NOTE_INSN_LOOP_END note as being in the /* Note that this will mark the NOTE_INSN_LOOP_END note as being in the
enclosing loop, but this doesn't matter. */ enclosing loop, but this doesn't matter. */
uid_loop_num[INSN_UID (insn)] = current_loop; uid_loop[INSN_UID (insn)] = current_loop;
} }
/* Any loop containing a label used in an initializer must be invalidated, /* Any loop containing a label used in an initializer must be invalidated,
...@@ -2757,12 +2688,9 @@ find_and_verify_loops (f) ...@@ -2757,12 +2688,9 @@ find_and_verify_loops (f)
for (label = forced_labels; label; label = XEXP (label, 1)) for (label = forced_labels; label; label = XEXP (label, 1))
{ {
int loop_num; for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
loop; loop = loop->outer)
for (loop_num = uid_loop_num[INSN_UID (XEXP (label, 0))]; loop->invalid = 1;
loop_num != -1;
loop_num = loop_outer_loop[loop_num])
loop_invalid[loop_num] = 1;
} }
/* Any loop containing a label used for an exception handler must be /* Any loop containing a label used for an exception handler must be
...@@ -2770,12 +2698,9 @@ find_and_verify_loops (f) ...@@ -2770,12 +2698,9 @@ find_and_verify_loops (f)
for (label = exception_handler_labels; label; label = XEXP (label, 1)) for (label = exception_handler_labels; label; label = XEXP (label, 1))
{ {
int loop_num; for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
loop; loop = loop->outer)
for (loop_num = uid_loop_num[INSN_UID (XEXP (label, 0))]; loop->invalid = 1;
loop_num != -1;
loop_num = loop_outer_loop[loop_num])
loop_invalid[loop_num] = 1;
} }
/* Now scan all insn's in the function. If any JUMP_INSN branches into a /* Now scan all insn's in the function. If any JUMP_INSN branches into a
...@@ -2794,40 +2719,37 @@ find_and_verify_loops (f) ...@@ -2794,40 +2719,37 @@ find_and_verify_loops (f)
for (insn = f; insn; insn = NEXT_INSN (insn)) for (insn = f; insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{ {
int this_loop_num = uid_loop_num[INSN_UID (insn)]; struct loop *this_loop = uid_loop[INSN_UID (insn)];
if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN) if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{ {
rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX); rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
if (note) if (note)
{ {
int loop_num; for (loop = uid_loop[INSN_UID (XEXP (note, 0))];
loop; loop = loop->outer)
for (loop_num = uid_loop_num[INSN_UID (XEXP (note, 0))]; loop->invalid = 1;
loop_num != -1;
loop_num = loop_outer_loop[loop_num])
loop_invalid[loop_num] = 1;
} }
} }
if (GET_CODE (insn) != JUMP_INSN) if (GET_CODE (insn) != JUMP_INSN)
continue; continue;
mark_loop_jump (PATTERN (insn), this_loop_num); mark_loop_jump (PATTERN (insn), this_loop);
/* See if this is an unconditional branch outside the loop. */ /* See if this is an unconditional branch outside the loop. */
if (this_loop_num != -1 if (this_loop
&& (GET_CODE (PATTERN (insn)) == RETURN && (GET_CODE (PATTERN (insn)) == RETURN
|| (simplejump_p (insn) || (simplejump_p (insn)
&& (uid_loop_num[INSN_UID (JUMP_LABEL (insn))] && (uid_loop[INSN_UID (JUMP_LABEL (insn))]
!= this_loop_num))) != this_loop)))
&& get_max_uid () < max_uid_for_loop) && get_max_uid () < max_uid_for_loop)
{ {
rtx p; rtx p;
rtx our_next = next_real_insn (insn); rtx our_next = next_real_insn (insn);
rtx last_insn_to_move = NEXT_INSN (insn); rtx last_insn_to_move = NEXT_INSN (insn);
int dest_loop; struct loop *dest_loop;
int outer_loop = -1; struct loop *outer_loop = NULL;
/* Go backwards until we reach the start of the loop, a label, /* Go backwards until we reach the start of the loop, a label,
or a JUMP_INSN. */ or a JUMP_INSN. */
...@@ -2844,12 +2766,12 @@ find_and_verify_loops (f) ...@@ -2844,12 +2766,12 @@ find_and_verify_loops (f)
if (JUMP_LABEL (insn)) if (JUMP_LABEL (insn))
{ {
dest_loop = uid_loop_num[INSN_UID (JUMP_LABEL (insn))]; dest_loop = uid_loop[INSN_UID (JUMP_LABEL (insn))];
if (dest_loop != -1) if (dest_loop)
{ {
for (outer_loop = dest_loop; outer_loop != -1; for (outer_loop = dest_loop; outer_loop;
outer_loop = loop_outer_loop[outer_loop]) outer_loop = outer_loop->outer)
if (outer_loop == this_loop_num) if (outer_loop == this_loop)
break; break;
} }
} }
...@@ -2857,8 +2779,8 @@ find_and_verify_loops (f) ...@@ -2857,8 +2779,8 @@ find_and_verify_loops (f)
/* Make sure that the target of P is within the current loop. */ /* Make sure that the target of P is within the current loop. */
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
&& uid_loop_num[INSN_UID (JUMP_LABEL (p))] != this_loop_num) && uid_loop[INSN_UID (JUMP_LABEL (p))] != this_loop)
outer_loop = this_loop_num; outer_loop = this_loop;
/* If we stopped on a JUMP_INSN to the next insn after INSN, /* If we stopped on a JUMP_INSN to the next insn after INSN,
we have a block of code to try to move. we have a block of code to try to move.
...@@ -2869,7 +2791,7 @@ find_and_verify_loops (f) ...@@ -2869,7 +2791,7 @@ find_and_verify_loops (f)
of the block, invert the jump in P and point it to that label, of the block, invert the jump in P and point it to that label,
and move the block of code to the spot we found. */ and move the block of code to the spot we found. */
if (outer_loop == -1 if (! outer_loop
&& GET_CODE (p) == JUMP_INSN && GET_CODE (p) == JUMP_INSN
&& JUMP_LABEL (p) != 0 && JUMP_LABEL (p) != 0
/* Just ignore jumps to labels that were never emitted. /* Just ignore jumps to labels that were never emitted.
...@@ -2885,7 +2807,7 @@ find_and_verify_loops (f) ...@@ -2885,7 +2807,7 @@ find_and_verify_loops (f)
{ {
rtx target rtx target
= JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn (); = JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn ();
int target_loop_num = uid_loop_num[INSN_UID (target)]; struct loop *target_loop = uid_loop[INSN_UID (target)];
rtx loc, loc2; rtx loc, loc2;
for (loc = target; loc; loc = PREV_INSN (loc)) for (loc = target; loc; loc = PREV_INSN (loc))
...@@ -2897,7 +2819,7 @@ find_and_verify_loops (f) ...@@ -2897,7 +2819,7 @@ find_and_verify_loops (f)
|| GET_CODE (loc2) != JUMP_INSN || GET_CODE (loc2) != JUMP_INSN
|| (GET_CODE (PATTERN (loc2)) != ADDR_VEC || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
&& GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC)) && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
&& uid_loop_num[INSN_UID (loc)] == target_loop_num) && uid_loop[INSN_UID (loc)] == target_loop)
break; break;
if (loc == 0) if (loc == 0)
...@@ -2910,7 +2832,7 @@ find_and_verify_loops (f) ...@@ -2910,7 +2832,7 @@ find_and_verify_loops (f)
|| GET_CODE (loc2) != JUMP_INSN || GET_CODE (loc2) != JUMP_INSN
|| (GET_CODE (PATTERN (loc2)) != ADDR_VEC || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
&& GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC)) && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
&& uid_loop_num[INSN_UID (loc)] == target_loop_num) && uid_loop[INSN_UID (loc)] == target_loop)
break; break;
if (loc) if (loc)
...@@ -2921,7 +2843,7 @@ find_and_verify_loops (f) ...@@ -2921,7 +2843,7 @@ find_and_verify_loops (f)
/* Ensure our label doesn't go away. */ /* Ensure our label doesn't go away. */
LABEL_NUSES (cond_label)++; LABEL_NUSES (cond_label)++;
/* Verify that uid_loop_num is large enough and that /* Verify that uid_loop is large enough and that
we can invert P. */ we can invert P. */
if (invert_jump (p, new_label)) if (invert_jump (p, new_label))
{ {
...@@ -2954,23 +2876,21 @@ find_and_verify_loops (f) ...@@ -2954,23 +2876,21 @@ find_and_verify_loops (f)
last_insn_to_move); last_insn_to_move);
reorder_insns (new_label, last_insn_to_move, loc); reorder_insns (new_label, last_insn_to_move, loc);
/* All those insns are now in TARGET_LOOP_NUM. */ /* All those insns are now in TARGET_LOOP. */
for (q = new_label; for (q = new_label;
q != NEXT_INSN (last_insn_to_move); q != NEXT_INSN (last_insn_to_move);
q = NEXT_INSN (q)) q = NEXT_INSN (q))
uid_loop_num[INSN_UID (q)] = target_loop_num; uid_loop[INSN_UID (q)] = target_loop;
/* The label jumped to by INSN is no longer a loop exit. /* The label jumped to by INSN is no longer a loop exit.
Unless INSN does not have a label (e.g., it is a Unless INSN does not have a label (e.g., it is a
RETURN insn), search loop_number_exit_labels to find RETURN insn), search loop->exit_labels to find
its label_ref, and remove it. Also turn off its label_ref, and remove it. Also turn off
LABEL_OUTSIDE_LOOP_P bit. */ LABEL_OUTSIDE_LOOP_P bit. */
if (JUMP_LABEL (insn)) if (JUMP_LABEL (insn))
{ {
int loop_num;
for (q = 0, for (q = 0,
r = loop_number_exit_labels[this_loop_num]; r = this_loop->exit_labels;
r; q = r, r = LABEL_NEXTREF (r)) r; q = r, r = LABEL_NEXTREF (r))
if (XEXP (r, 0) == JUMP_LABEL (insn)) if (XEXP (r, 0) == JUMP_LABEL (insn))
{ {
...@@ -2978,26 +2898,25 @@ find_and_verify_loops (f) ...@@ -2978,26 +2898,25 @@ find_and_verify_loops (f)
if (q) if (q)
LABEL_NEXTREF (q) = LABEL_NEXTREF (r); LABEL_NEXTREF (q) = LABEL_NEXTREF (r);
else else
loop_number_exit_labels[this_loop_num] this_loop->exit_labels = LABEL_NEXTREF (r);
= LABEL_NEXTREF (r);
break; break;
} }
for (loop_num = this_loop_num; for (loop = this_loop; loop && loop != target_loop;
loop_num != -1 && loop_num != target_loop_num; loop = loop->outer)
loop_num = loop_outer_loop[loop_num]) loop->exit_count--;
loop_number_exit_count[loop_num]--;
/* If we didn't find it, then something is wrong. */ /* If we didn't find it, then something is
wrong. */
if (! r) if (! r)
abort (); abort ();
} }
/* P is now a jump outside the loop, so it must be put /* P is now a jump outside the loop, so it must be put
in loop_number_exit_labels, and marked as such. in loop->exit_labels, and marked as such.
The easiest way to do this is to just call The easiest way to do this is to just call
mark_loop_jump again for P. */ mark_loop_jump again for P. */
mark_loop_jump (PATTERN (p), this_loop_num); mark_loop_jump (PATTERN (p), this_loop);
/* If INSN now jumps to the insn after it, /* If INSN now jumps to the insn after it,
delete INSN. */ delete INSN. */
...@@ -3030,12 +2949,12 @@ find_and_verify_loops (f) ...@@ -3030,12 +2949,12 @@ find_and_verify_loops (f)
For speed, we assume that X is part of a pattern of a JUMP_INSN. */ For speed, we assume that X is part of a pattern of a JUMP_INSN. */
static void static void
mark_loop_jump (x, loop_num) mark_loop_jump (x, loop)
rtx x; rtx x;
int loop_num; struct loop *loop;
{ {
int dest_loop; struct loop *dest_loop;
int outer_loop; struct loop *outer_loop;
int i; int i;
switch (GET_CODE (x)) switch (GET_CODE (x))
...@@ -3052,28 +2971,28 @@ mark_loop_jump (x, loop_num) ...@@ -3052,28 +2971,28 @@ mark_loop_jump (x, loop_num)
case CONST: case CONST:
/* There could be a label reference in here. */ /* There could be a label reference in here. */
mark_loop_jump (XEXP (x, 0), loop_num); mark_loop_jump (XEXP (x, 0), loop);
return; return;
case PLUS: case PLUS:
case MINUS: case MINUS:
case MULT: case MULT:
mark_loop_jump (XEXP (x, 0), loop_num); mark_loop_jump (XEXP (x, 0), loop);
mark_loop_jump (XEXP (x, 1), loop_num); mark_loop_jump (XEXP (x, 1), loop);
return; return;
case LO_SUM: case LO_SUM:
/* This may refer to a LABEL_REF or SYMBOL_REF. */ /* This may refer to a LABEL_REF or SYMBOL_REF. */
mark_loop_jump (XEXP (x, 1), loop_num); mark_loop_jump (XEXP (x, 1), loop);
return; return;
case SIGN_EXTEND: case SIGN_EXTEND:
case ZERO_EXTEND: case ZERO_EXTEND:
mark_loop_jump (XEXP (x, 0), loop_num); mark_loop_jump (XEXP (x, 0), loop);
return; return;
case LABEL_REF: case LABEL_REF:
dest_loop = uid_loop_num[INSN_UID (XEXP (x, 0))]; dest_loop = uid_loop[INSN_UID (XEXP (x, 0))];
/* Link together all labels that branch outside the loop. This /* Link together all labels that branch outside the loop. This
is used by final_[bg]iv_value and the loop unrolling code. Also is used by final_[bg]iv_value and the loop unrolling code. Also
...@@ -3082,75 +3001,74 @@ mark_loop_jump (x, loop_num) ...@@ -3082,75 +3001,74 @@ mark_loop_jump (x, loop_num)
/* A check to make sure the label is not in an inner nested loop, /* A check to make sure the label is not in an inner nested loop,
since this does not count as a loop exit. */ since this does not count as a loop exit. */
if (dest_loop != -1) if (dest_loop)
{ {
for (outer_loop = dest_loop; outer_loop != -1; for (outer_loop = dest_loop; outer_loop;
outer_loop = loop_outer_loop[outer_loop]) outer_loop = outer_loop->outer)
if (outer_loop == loop_num) if (outer_loop == loop)
break; break;
} }
else else
outer_loop = -1; outer_loop = NULL;
if (loop_num != -1 && outer_loop == -1) if (loop && ! outer_loop)
{ {
LABEL_OUTSIDE_LOOP_P (x) = 1; LABEL_OUTSIDE_LOOP_P (x) = 1;
LABEL_NEXTREF (x) = loop_number_exit_labels[loop_num]; LABEL_NEXTREF (x) = loop->exit_labels;
loop_number_exit_labels[loop_num] = x; loop->exit_labels = x;
for (outer_loop = loop_num; for (outer_loop = loop;
outer_loop != -1 && outer_loop != dest_loop; outer_loop && outer_loop != dest_loop;
outer_loop = loop_outer_loop[outer_loop]) outer_loop = outer_loop->outer)
loop_number_exit_count[outer_loop]++; outer_loop->exit_count++;
} }
/* If this is inside a loop, but not in the current loop or one enclosed /* If this is inside a loop, but not in the current loop or one enclosed
by it, it invalidates at least one loop. */ by it, it invalidates at least one loop. */
if (dest_loop == -1) if (! dest_loop)
return; return;
/* We must invalidate every nested loop containing the target of this /* We must invalidate every nested loop containing the target of this
label, except those that also contain the jump insn. */ label, except those that also contain the jump insn. */
for (; dest_loop != -1; dest_loop = loop_outer_loop[dest_loop]) for (; dest_loop; dest_loop = dest_loop->outer)
{ {
/* Stop when we reach a loop that also contains the jump insn. */ /* Stop when we reach a loop that also contains the jump insn. */
for (outer_loop = loop_num; outer_loop != -1; for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
outer_loop = loop_outer_loop[outer_loop])
if (dest_loop == outer_loop) if (dest_loop == outer_loop)
return; return;
/* If we get here, we know we need to invalidate a loop. */ /* If we get here, we know we need to invalidate a loop. */
if (loop_dump_stream && ! loop_invalid[dest_loop]) if (loop_dump_stream && ! dest_loop->invalid)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"\nLoop at %d ignored due to multiple entry points.\n", "\nLoop at %d ignored due to multiple entry points.\n",
INSN_UID (loop_number_loop_starts[dest_loop])); INSN_UID (dest_loop->start));
loop_invalid[dest_loop] = 1; dest_loop->invalid = 1;
} }
return; return;
case SET: case SET:
/* If this is not setting pc, ignore. */ /* If this is not setting pc, ignore. */
if (SET_DEST (x) == pc_rtx) if (SET_DEST (x) == pc_rtx)
mark_loop_jump (SET_SRC (x), loop_num); mark_loop_jump (SET_SRC (x), loop);
return; return;
case IF_THEN_ELSE: case IF_THEN_ELSE:
mark_loop_jump (XEXP (x, 1), loop_num); mark_loop_jump (XEXP (x, 1), loop);
mark_loop_jump (XEXP (x, 2), loop_num); mark_loop_jump (XEXP (x, 2), loop);
return; return;
case PARALLEL: case PARALLEL:
case ADDR_VEC: case ADDR_VEC:
for (i = 0; i < XVECLEN (x, 0); i++) for (i = 0; i < XVECLEN (x, 0); i++)
mark_loop_jump (XVECEXP (x, 0, i), loop_num); mark_loop_jump (XVECEXP (x, 0, i), loop);
return; return;
case ADDR_DIFF_VEC: case ADDR_DIFF_VEC:
for (i = 0; i < XVECLEN (x, 1); i++) for (i = 0; i < XVECLEN (x, 1); i++)
mark_loop_jump (XVECEXP (x, 1, i), loop_num); mark_loop_jump (XVECEXP (x, 1, i), loop);
return; return;
default: default:
...@@ -3158,16 +3076,15 @@ mark_loop_jump (x, loop_num) ...@@ -3158,16 +3076,15 @@ mark_loop_jump (x, loop_num)
jump out of the loop. However, we have no way to link the destination jump out of the loop. However, we have no way to link the destination
of this jump onto the list of exit labels. To be safe we mark this of this jump onto the list of exit labels. To be safe we mark this
loop and any containing loops as invalid. */ loop and any containing loops as invalid. */
if (loop_num != -1) if (loop)
{ {
for (outer_loop = loop_num; outer_loop != -1; for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
outer_loop = loop_outer_loop[outer_loop])
{ {
if (loop_dump_stream && ! loop_invalid[outer_loop]) if (loop_dump_stream && ! outer_loop->invalid)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"\nLoop at %d ignored due to unknown exit jump.\n", "\nLoop at %d ignored due to unknown exit jump.\n",
INSN_UID (loop_number_loop_starts[outer_loop])); INSN_UID (outer_loop->start));
loop_invalid[outer_loop] = 1; outer_loop->invalid = 1;
} }
} }
return; return;
...@@ -3313,7 +3230,7 @@ invariant_p (x) ...@@ -3313,7 +3230,7 @@ invariant_p (x)
&& ! current_function_has_nonlocal_goto) && ! current_function_has_nonlocal_goto)
return 1; return 1;
if (this_loop_info.has_call if (loop_info_data.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;
...@@ -3651,7 +3568,7 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs) ...@@ -3651,7 +3568,7 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
} }
/* 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 is entered at SCAN_START, and that is entered at LOOP_SCAN_START,
return 1 if the register set in SET contained in insn INSN is used by return 1 if the register set in SET contained in insn INSN is used by
any insn that precedes INSN in cyclic order starting any insn that precedes INSN in cyclic order starting
from the loop entry point. from the loop entry point.
...@@ -3661,22 +3578,23 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs) ...@@ -3661,22 +3578,23 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
from an inner loop past two loops. */ from an inner loop past two loops. */
static int static int
loop_reg_used_before_p (set, insn, loop_start, scan_start, loop_end) loop_reg_used_before_p (loop, set, insn)
rtx set, insn, loop_start, scan_start, loop_end; const struct loop *loop;
rtx set, insn;
{ {
rtx reg = SET_DEST (set); rtx reg = SET_DEST (set);
rtx p; rtx p;
/* Scan forward checking for register usage. If we hit INSN, we /* Scan forward checking for register usage. If we hit INSN, we
are done. Otherwise, if we hit LOOP_END, wrap around to LOOP_START. */ are done. Otherwise, if we hit LOOP->END, wrap around to LOOP->START. */
for (p = scan_start; p != insn; p = NEXT_INSN (p)) for (p = loop->scan_start; p != insn; p = NEXT_INSN (p))
{ {
if (GET_RTX_CLASS (GET_CODE (p)) == 'i' if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& reg_overlap_mentioned_p (reg, PATTERN (p))) && reg_overlap_mentioned_p (reg, PATTERN (p)))
return 1; return 1;
if (p == loop_end) if (p == loop->end)
p = loop_start; p = loop->start;
} }
return 0; return 0;
...@@ -3761,23 +3679,16 @@ static rtx addr_placeholder; ...@@ -3761,23 +3679,16 @@ static rtx addr_placeholder;
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.
SCAN_START is the first instruction in the loop, as the loop would 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 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 the first instruction in the loop, as it is layed out in the
instruction stream. LOOP_START is the NOTE_INSN_LOOP_BEG. instruction stream. LOOP_START is the NOTE_INSN_LOOP_BEG.
LOOP_CONT is the NOTE_INSN_LOOP_CONT. */ LOOP_CONT is the NOTE_INSN_LOOP_CONT. */
static void static void
strength_reduce (scan_start, end, loop_top, insn_count, strength_reduce (loop, insn_count, unroll_p, bct_p)
loop_start, loop_end, loop_info, loop_cont, unroll_p, bct_p) struct loop *loop;
rtx scan_start;
rtx end;
rtx loop_top;
int insn_count; int insn_count;
rtx loop_start;
rtx loop_end;
struct loop_info *loop_info;
rtx loop_cont;
int unroll_p, bct_p ATTRIBUTE_UNUSED; int unroll_p, bct_p ATTRIBUTE_UNUSED;
{ {
rtx p; rtx p;
...@@ -3797,6 +3708,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3797,6 +3708,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
int past_loop_latch = 0; int past_loop_latch = 0;
/* Temporary list pointers for traversing loop_iv_list. */ /* Temporary list pointers for traversing loop_iv_list. */
struct iv_class *bl, **backbl; struct iv_class *bl, **backbl;
struct loop_info *loop_info = loop->info;
/* Ratio of extra register life span we can justify /* Ratio of extra register life span we can justify
for saving an instruction. More if loop doesn't call subroutines for saving an instruction. More if loop doesn't call subroutines
since in that case saving an insn makes more difference since in that case saving an insn makes more difference
...@@ -3812,11 +3724,16 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3812,11 +3724,16 @@ strength_reduce (scan_start, end, loop_top, insn_count,
int loop_depth = 0; int loop_depth = 0;
int n_extra_increment; int n_extra_increment;
int unrolled_insn_copies = 0; int unrolled_insn_copies = 0;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
rtx loop_scan_start = loop->scan_start;
rtx loop_top = loop->top;
rtx loop_cont = loop->cont;
/* If 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 (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 (scan_start, loop_start, loop_end); maybe_multiple = back_branch_in_range_p (loop_scan_start, loop_start, loop_end);
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");
...@@ -3840,9 +3757,9 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3840,9 +3757,9 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Scan through loop to find all possible bivs. */ /* Scan through loop to find all possible bivs. */
for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top); for (p = next_insn_in_loop (loop, loop_scan_start);
p != NULL_RTX; p != NULL_RTX;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
if (GET_CODE (p) == INSN if (GET_CODE (p) == INSN
&& (set = single_set (p)) && (set = single_set (p))
...@@ -3856,7 +3773,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3856,7 +3773,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
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 (SET_SRC (set), GET_MODE (SET_SRC (set)),
dest_reg, p, &inc_val, &mult_val, dest_reg, p, loop->level,
&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.
...@@ -3890,15 +3808,15 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3890,15 +3808,15 @@ strength_reduce (scan_start, end, loop_top, insn_count,
while (1) while (1)
{ {
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
if (insn == scan_start) if (insn == loop_scan_start)
break; break;
if (insn == end) if (insn == loop_end)
{ {
if (loop_top != 0) if (loop_top != 0)
insn = loop_top; insn = loop_top;
else else
break; break;
if (insn == scan_start) if (insn == loop_scan_start)
break; break;
} }
...@@ -3906,7 +3824,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3906,7 +3824,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& GET_CODE (PATTERN (insn)) != RETURN && GET_CODE (PATTERN (insn)) != RETURN
&& (! condjump_p (insn) && (! condjump_p (insn)
|| (JUMP_LABEL (insn) != 0 || (JUMP_LABEL (insn) != 0
&& JUMP_LABEL (insn) != scan_start && JUMP_LABEL (insn) != loop_scan_start
&& ! loop_insn_first_p (p, JUMP_LABEL (insn))))) && ! loop_insn_first_p (p, JUMP_LABEL (insn)))))
{ {
maybe_multiple = 1; maybe_multiple = 1;
...@@ -3932,9 +3850,9 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3932,9 +3850,9 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* If this is a jump outside the loop, then it also doesn't /* If this is a jump outside the loop, then it also doesn't
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_number_exits_labels list. */ loop->exits_labels list. */
for (label = loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]]; for (label = uid_loop[INSN_UID (loop_start)]->exit_labels;
label; label;
label = LABEL_NEXTREF (label)) label = LABEL_NEXTREF (label))
if (XEXP (label, 0) == JUMP_LABEL (p)) if (XEXP (label, 0) == JUMP_LABEL (p))
...@@ -3970,7 +3888,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3970,7 +3888,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
Note that LOOP_TOP is only set for rotated loops and we need Note that LOOP_TOP is only set for rotated loops and we need
this check for all loops, so compare against the CODE_LABEL this check for all loops, so compare against the CODE_LABEL
which immediately follows LOOP_START. */ which immediately follows LOOP_START. */
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == NEXT_INSN (loop_start)) if (GET_CODE (p) == JUMP_INSN
&& JUMP_LABEL (p) == NEXT_INSN (loop_start))
past_loop_latch = 1; past_loop_latch = 1;
/* Unlike in the code motion pass where MAYBE_NEVER indicates that /* Unlike in the code motion pass where MAYBE_NEVER indicates that
...@@ -4046,8 +3965,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4046,8 +3965,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Can still unroll the loop anyways, but indicate that there is no /* Can still unroll the loop anyways, but indicate that there is no
strength reduction info available. */ strength reduction info available. */
if (unroll_p) if (unroll_p)
unroll_loop (loop_end, insn_count, loop_start, end_insert_before, unroll_loop (loop, insn_count, end_insert_before, 0);
loop_info, 0);
goto egress; goto egress;
} }
...@@ -4188,8 +4106,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4188,8 +4106,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&SET_SRC (single_set (bl->biv->insn)), &SET_SRC (single_set (bl->biv->insn)),
copy_rtx (src), 0)) copy_rtx (src), 0))
{ {
int loop_num = uid_loop_num[INSN_UID (loop_start)]; rtx dominator = uid_loop[INSN_UID (loop_start)]->cont_dominator;
rtx dominator = loop_number_cont_dominator[loop_num];
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);
...@@ -4202,7 +4119,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4202,7 +4119,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* We can get better optimization if we can move the giv setting /* We can get better optimization if we can move the giv setting
before the first giv use. */ before the first giv use. */
if (dominator if (dominator
&& ! loop_insn_first_p (dominator, scan_start) && ! loop_insn_first_p (dominator, loop_scan_start)
&& ! reg_set_between_p (bl2->biv->src_reg, loop_start, && ! reg_set_between_p (bl2->biv->src_reg, loop_start,
dominator) dominator)
&& ! reg_used_between_p (giv, loop_start, dominator) && ! reg_used_between_p (giv, loop_start, dominator)
...@@ -4281,7 +4198,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4281,7 +4198,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
n_extra_increment += bl->biv_count - 1; n_extra_increment += bl->biv_count - 1;
/* If the loop contains volatile memory references do not allow any /* If the loop contains volatile memory references do not allow any
replacements to take place, since this could loose the volatile markers. */ replacements to take place, since this could loose the volatile
markers. */
if (n_extra_increment && ! loop_info->has_volatile) if (n_extra_increment && ! loop_info->has_volatile)
{ {
int nregs = first_increment_giv + n_extra_increment; int nregs = first_increment_giv + n_extra_increment;
...@@ -4295,7 +4213,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4295,7 +4213,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
struct induction **vp, *v, *next; struct induction **vp, *v, *next;
int biv_dead_after_loop = 0; int biv_dead_after_loop = 0;
/* The biv increments lists are in reverse order. Fix this first. */ /* The biv increments lists are in reverse order. Fix this
first. */
for (v = bl->biv, bl->biv = 0; v; v = next) for (v = bl->biv, bl->biv = 0; v; v = next)
{ {
next = v->next_iv; next = v->next_iv;
...@@ -4380,7 +4299,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4380,7 +4299,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
for (last_use_insn = v->insn, p = NEXT_INSN (v->insn); for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
p != next->insn; p != next->insn;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
if (GET_RTX_CLASS (GET_CODE (p)) != 'i') if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
continue; continue;
...@@ -4459,7 +4378,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4459,7 +4378,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
remember the last insn that needed a replacement. */ remember the last insn that needed a replacement. */
for (last_use_insn = v->insn, p = NEXT_INSN (v->insn); for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
p != next->insn; p != next->insn;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
rtx note; rtx note;
...@@ -4504,21 +4423,21 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4504,21 +4423,21 @@ strength_reduce (scan_start, end, loop_top, insn_count,
not_every_iteration = 0; not_every_iteration = 0;
loop_depth = 0; loop_depth = 0;
maybe_multiple = 0; maybe_multiple = 0;
p = scan_start; p = loop_scan_start;
while (1) while (1)
{ {
p = NEXT_INSN (p); p = NEXT_INSN (p);
/* At end of a straight-in loop, we are done. /* At end of a straight-in loop, we are done.
At end of a loop entered at the bottom, scan the top. */ At end of a loop entered at the bottom, scan the top. */
if (p == scan_start) if (p == loop_scan_start)
break; break;
if (p == end) if (p == loop_end)
{ {
if (loop_top != 0) if (loop_top != 0)
p = loop_top; p = loop_top;
else else
break; break;
if (p == scan_start) if (p == loop_scan_start)
break; break;
} }
...@@ -4608,15 +4527,15 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4608,15 +4527,15 @@ strength_reduce (scan_start, end, loop_top, insn_count,
while (1) while (1)
{ {
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
if (insn == scan_start) if (insn == loop_scan_start)
break; break;
if (insn == end) if (insn == loop_end)
{ {
if (loop_top != 0) if (loop_top != 0)
insn = loop_top; insn = loop_top;
else else
break; break;
if (insn == scan_start) if (insn == loop_scan_start)
break; break;
} }
...@@ -4624,7 +4543,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4624,7 +4543,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& GET_CODE (PATTERN (insn)) != RETURN && GET_CODE (PATTERN (insn)) != RETURN
&& (! condjump_p (insn) && (! condjump_p (insn)
|| (JUMP_LABEL (insn) != 0 || (JUMP_LABEL (insn) != 0
&& JUMP_LABEL (insn) != scan_start && JUMP_LABEL (insn) != loop_scan_start
&& (INSN_UID (JUMP_LABEL (insn)) >= max_uid_for_loop && (INSN_UID (JUMP_LABEL (insn)) >= max_uid_for_loop
|| INSN_UID (insn) >= max_uid_for_loop || INSN_UID (insn) >= max_uid_for_loop
|| (INSN_LUID (JUMP_LABEL (insn)) || (INSN_LUID (JUMP_LABEL (insn))
...@@ -4653,9 +4572,9 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4653,9 +4572,9 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* If this is a jump outside the loop, then it also doesn't /* If this is a jump outside the loop, then it also doesn't
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_number_exits_labels list. */ loop->exits_labels list. */
for (label = loop_number_exit_labels[uid_loop_num[INSN_UID (loop_start)]]; for (label = uid_loop[INSN_UID (loop_start)]->exit_labels;
label; label;
label = LABEL_NEXTREF (label)) label = LABEL_NEXTREF (label))
if (XEXP (label, 0) == JUMP_LABEL (p)) if (XEXP (label, 0) == JUMP_LABEL (p))
...@@ -4703,7 +4622,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4703,7 +4622,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
be called after all giv's have been identified, since otherwise it may be called after all giv's have been identified, since otherwise it may
fail if the iteration variable is a giv. */ fail if the iteration variable is a giv. */
loop_iterations (loop_start, loop_end, loop_info); loop_iterations (loop);
/* Now for each giv for which we still don't know whether or not it is /* Now for each giv for which we still don't know whether or not it is
replaceable, check to see if it is replaceable because its final value replaceable, check to see if it is replaceable because its final value
...@@ -4722,7 +4641,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4722,7 +4641,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Try to prove that the loop counter variable (if any) is always /* Try to prove that the loop counter variable (if any) is always
nonnegative; if so, record that fact with a REG_NONNEG note nonnegative; if so, record that fact with a REG_NONNEG note
so that "decrement and branch until zero" insn can be used. */ so that "decrement and branch until zero" insn can be used. */
check_dbra_loop (loop_end, insn_count, loop_start, loop_info); check_dbra_loop (loop, insn_count);
/* Create reg_map to hold substitutions for replaceable giv regs. /* Create reg_map to hold substitutions for replaceable giv regs.
Some givs might have been made from biv increments, so look at Some givs might have been made from biv increments, so look at
...@@ -4771,7 +4690,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4771,7 +4690,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& ! bl->nonneg && ! bl->nonneg
#endif #endif
)) ))
bl->eliminable = maybe_eliminate_biv (bl, loop_start, end, 0, bl->eliminable = maybe_eliminate_biv (bl, loop_start, loop_end, 0,
threshold, insn_count); threshold, insn_count);
else else
{ {
...@@ -5038,11 +4957,11 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5038,11 +4957,11 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Check for case where increment is before the address /* Check for case where increment is before the address
giv. Do this test in "loop order". */ giv. Do this test in "loop order". */
else if ((INSN_LUID (v->insn) > INSN_LUID (bl->biv->insn) else if ((INSN_LUID (v->insn) > INSN_LUID (bl->biv->insn)
&& (INSN_LUID (v->insn) < INSN_LUID (scan_start) && (INSN_LUID (v->insn) < INSN_LUID (loop_scan_start)
|| (INSN_LUID (bl->biv->insn) || (INSN_LUID (bl->biv->insn)
> INSN_LUID (scan_start)))) > INSN_LUID (loop_scan_start))))
|| (INSN_LUID (v->insn) < INSN_LUID (scan_start) || (INSN_LUID (v->insn) < INSN_LUID (loop_scan_start)
&& (INSN_LUID (scan_start) && (INSN_LUID (loop_scan_start)
< INSN_LUID (bl->biv->insn)))) < INSN_LUID (bl->biv->insn))))
auto_inc_opt = -1; auto_inc_opt = -1;
else else
...@@ -5169,7 +5088,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5169,7 +5088,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
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 (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) if (uid_loop[INSN_UID (loop_start)]->exit_count)
insert_before = loop_start; insert_before = loop_start;
else else
insert_before = end_insert_before; insert_before = end_insert_before;
...@@ -5237,7 +5156,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5237,7 +5156,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
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, end, 1, && maybe_eliminate_biv (bl, loop_start, loop_end, 1,
threshold, insn_count)) threshold, insn_count))
{ {
...@@ -5261,7 +5180,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5261,7 +5180,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
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 (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) if (uid_loop[INSN_UID (loop_start)]->exit_count)
insert_before = loop_start; insert_before = loop_start;
else else
insert_before = end_insert_before; insert_before = end_insert_before;
...@@ -5292,7 +5211,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5292,7 +5211,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* Go through all the instructions in the loop, making all the /* Go through all the instructions in the loop, making all the
register substitutions scheduled in REG_MAP. */ register substitutions scheduled in REG_MAP. */
for (p = loop_start; p != end; p = NEXT_INSN (p)) for (p = loop_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)
{ {
...@@ -5335,14 +5254,13 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -5335,14 +5254,13 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (unroll_p if (unroll_p
|| (loop_info->n_iterations > 0 || (loop_info->n_iterations > 0
&& unrolled_insn_copies <= insn_count)) && unrolled_insn_copies <= insn_count))
unroll_loop (loop_end, insn_count, loop_start, end_insert_before, unroll_loop (loop, insn_count, end_insert_before, 1);
loop_info, 1);
#ifdef HAVE_decrement_and_branch_on_count #ifdef HAVE_decrement_and_branch_on_count
/* Instrument the loop with BCT insn. */ /* Instrument the loop with BCT insn. */
if (HAVE_decrement_and_branch_on_count && bct_p if (HAVE_decrement_and_branch_on_count && bct_p
&& flag_branch_on_count_reg) && flag_branch_on_count_reg)
insert_bct (loop_start, loop_end, loop_info); insert_bct (loop);
#endif /* HAVE_decrement_and_branch_on_count */ #endif /* HAVE_decrement_and_branch_on_count */
if (loop_dump_stream) if (loop_dump_stream)
...@@ -6116,12 +6034,13 @@ update_giv_derive (p) ...@@ -6116,12 +6034,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, inc_val, mult_val, location, basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
multi_insn_incr) location, multi_insn_incr)
register rtx x; register rtx x;
enum machine_mode mode; enum machine_mode mode;
rtx p;
rtx dest_reg; rtx dest_reg;
rtx p;
int level;
rtx *inc_val; rtx *inc_val;
rtx *mult_val; rtx *mult_val;
rtx **location; rtx **location;
...@@ -6167,7 +6086,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location, ...@@ -6167,7 +6086,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
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 (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)),
dest_reg, p, inc_val, mult_val, location, dest_reg, p, level,
inc_val, mult_val, location,
multi_insn_incr); multi_insn_incr);
return 0; return 0;
...@@ -6200,7 +6120,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location, ...@@ -6200,7 +6120,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
(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, dest_reg, insn, level,
inc_val, mult_val, location, inc_val, mult_val, location,
multi_insn_incr)) multi_insn_incr))
{ {
...@@ -6223,7 +6143,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location, ...@@ -6223,7 +6143,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
/* 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 (this_loop_info.loops_enclosed == 1 if (level == 0
&& 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)
{ {
...@@ -6237,8 +6157,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location, ...@@ -6237,8 +6157,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
case SIGN_EXTEND: case SIGN_EXTEND:
return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)), return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
dest_reg, p, inc_val, mult_val, location, dest_reg, p, level, inc_val, mult_val,
multi_insn_incr); location, multi_insn_incr);
case ASHIFTRT: case ASHIFTRT:
/* Similar, since this can be a sign extension. */ /* Similar, since this can be a sign extension. */
...@@ -6258,7 +6178,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location, ...@@ -6258,7 +6178,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
&& 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 (XEXP (SET_SRC (set), 0),
GET_MODE (XEXP (x, 0)), GET_MODE (XEXP (x, 0)),
dest_reg, insn, inc_val, mult_val, dest_reg, insn, level, inc_val, mult_val,
location, multi_insn_incr)) location, multi_insn_incr))
{ {
*multi_insn_incr = 1; *multi_insn_incr = 1;
...@@ -7908,11 +7828,9 @@ product_cheap_p (a, b) ...@@ -7908,11 +7828,9 @@ product_cheap_p (a, b)
final_[bg]iv_value. */ final_[bg]iv_value. */
static int static int
check_dbra_loop (loop_end, insn_count, loop_start, loop_info) check_dbra_loop (loop, insn_count)
rtx loop_end; struct loop *loop;
int insn_count; int insn_count;
rtx loop_start;
struct loop_info *loop_info;
{ {
struct iv_class *bl; struct iv_class *bl;
rtx reg; rtx reg;
...@@ -7926,6 +7844,9 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) ...@@ -7926,6 +7844,9 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
rtx jump; rtx jump;
rtx first_compare; rtx first_compare;
int compare_and_branch; int compare_and_branch;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
struct loop_info *loop_info = loop->info;
/* If last insn is a conditional branch, and the insn before tests a /* If last insn is a conditional branch, and the insn before tests a
register value, try to optimize it. Otherwise, we can't do anything. */ register value, try to optimize it. Otherwise, we can't do anything. */
...@@ -8041,7 +7962,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) ...@@ -8041,7 +7962,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
int reversible_mem_store = 1; int reversible_mem_store = 1;
if (bl->giv_count == 0 if (bl->giv_count == 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) && ! uid_loop[INSN_UID (loop_start)]->exit_count)
{ {
rtx bivreg = regno_reg_rtx[bl->regno]; rtx bivreg = regno_reg_rtx[bl->regno];
...@@ -8225,7 +8146,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) ...@@ -8225,7 +8146,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
calculate a giv or has a non-counting use. */ calculate a giv or has a non-counting use. */
#if ! defined (HAVE_decrement_and_branch_until_zero) \ #if ! defined (HAVE_decrement_and_branch_until_zero) \
&& defined (HAVE_decrement_and_branch_on_count) && defined (HAVE_decrement_and_branch_on_count)
&& (! (add_val == 1 && loop_info->vtop && (! (add_val == 1 && loop->vtop
&& (bl->biv_count == 0 && (bl->biv_count == 0
|| no_use_except_counting))) || no_use_except_counting)))
#endif #endif
...@@ -8240,7 +8161,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) ...@@ -8240,7 +8161,7 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
nonneg = 1; nonneg = 1;
cmp_code = GE; cmp_code = GE;
} }
else if (add_val == 1 && loop_info->vtop else if (add_val == 1 && loop->vtop
&& (bl->biv_count == 0 && (bl->biv_count == 0
|| no_use_except_counting)) || no_use_except_counting))
{ {
...@@ -8483,10 +8404,11 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) ...@@ -8483,10 +8404,11 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info)
start of the loop. */ start of the loop. */
static int static int
maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count) maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold,
insn_count)
struct iv_class *bl; struct iv_class *bl;
rtx loop_start; rtx loop_start;
rtx end; rtx loop_end;
int eliminate_p; int eliminate_p;
int threshold, insn_count; int threshold, insn_count;
{ {
...@@ -8496,7 +8418,7 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count) ...@@ -8496,7 +8418,7 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count)
/* 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
biv in a way that we cannot eliminate. */ biv in a way that we cannot eliminate. */
for (p = loop_start; p != end; p = NEXT_INSN (p)) for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
{ {
enum rtx_code code = GET_CODE (p); enum rtx_code code = GET_CODE (p);
rtx where = threshold >= insn_count ? loop_start : p; rtx where = threshold >= insn_count ? loop_start : p;
...@@ -8534,7 +8456,7 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count) ...@@ -8534,7 +8456,7 @@ maybe_eliminate_biv (bl, loop_start, end, eliminate_p, threshold, insn_count)
} }
} }
if (p == end) if (p == loop_end)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "biv %d %s eliminated.\n", fprintf (loop_dump_stream, "biv %d %s eliminated.\n",
...@@ -9337,31 +9259,29 @@ get_condition_for_loop (x) ...@@ -9337,31 +9259,29 @@ get_condition_for_loop (x)
*/ */
static void static void
insert_bct (loop_start, loop_end, loop_info) insert_bct (loop)
rtx loop_start, loop_end; struct loop *loop;
struct loop_info *loop_info;
{ {
int i;
unsigned HOST_WIDE_INT n_iterations; unsigned HOST_WIDE_INT n_iterations;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
struct loop_info *loop_info = loop->info;
int loop_num = loop->num;
#if 0 #if 0
int increment_direction, compare_direction; int increment_direction, compare_direction;
/* If the loop condition is <= or >=, the number of iteration /* If the loop condition is <= or >=, the number of iteration
is 1 more than the range of the bounds of the loop. */ is 1 more than the range of the bounds of the loop. */
int add_iteration = 0; int add_iteration = 0;
enum machine_mode loop_var_mode = word_mode; enum machine_mode loop_var_mode = word_mode;
#endif #endif
int loop_num = uid_loop_num [INSN_UID (loop_start)];
/* It's impossible to instrument a competely unrolled loop. */ /* It's impossible to instrument a competely unrolled loop. */
if (loop_info->unroll_number == loop_info->n_iterations) if (loop_info->unroll_number == loop_info->n_iterations)
return; return;
/* Make sure that the count register is not in use. */ /* Make sure that the count register is not in use. */
if (loop_used_count_register [loop_num]) if (loop_info->used_count_register)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -9435,9 +9355,15 @@ insert_bct (loop_start, loop_end, loop_info) ...@@ -9435,9 +9355,15 @@ insert_bct (loop_start, loop_end, loop_info)
/* Handle the simpler case, where the bounds are known at compile time. */ /* Handle the simpler case, where the bounds are known at compile time. */
if (n_iterations > 0) if (n_iterations > 0)
{ {
struct loop *outer_loop;
struct loop_info *outer_loop_info;
/* Mark all enclosing loops that they cannot use count register. */ /* Mark all enclosing loops that they cannot use count register. */
for (i = loop_num; i != -1; i = loop_outer_loop[i]) for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
loop_used_count_register[i] = 1; {
outer_loop_info = outer_loop->info;
outer_loop_info->used_count_register = 1;
}
instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations)); instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations));
return; return;
} }
...@@ -9707,17 +9633,13 @@ insert_loop_mem (mem, data) ...@@ -9707,17 +9633,13 @@ insert_loop_mem (mem, data)
values after load_mems. */ values after load_mems. */
static void static void
load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start, load_mems_and_recount_loop_regs_set (loop, insn_count)
insn_count) const struct loop *loop;
rtx scan_start;
rtx end;
rtx loop_top;
rtx start;
int *insn_count; int *insn_count;
{ {
int nregs = max_reg_num (); int nregs = max_reg_num ();
load_mems (scan_start, end, loop_top, start); load_mems (loop);
/* Recalculate set_in_loop and friends since load_mems may have /* Recalculate set_in_loop and friends since load_mems may have
created new registers. */ created new registers. */
...@@ -9742,7 +9664,7 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start, ...@@ -9742,7 +9664,7 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start,
bzero ((char *) &may_not_optimize->data, nregs * sizeof (char)); bzero ((char *) &may_not_optimize->data, nregs * sizeof (char));
bzero ((char *) &reg_single_usage->data, nregs * sizeof (rtx)); bzero ((char *) &reg_single_usage->data, nregs * sizeof (rtx));
count_loop_regs_set (loop_top ? loop_top : start, end, count_loop_regs_set (loop->top ? loop->top : loop->start, loop->end,
may_not_optimize, reg_single_usage, may_not_optimize, reg_single_usage,
insn_count, nregs); insn_count, nregs);
...@@ -9767,16 +9689,11 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start, ...@@ -9767,16 +9689,11 @@ load_mems_and_recount_loop_regs_set (scan_start, end, loop_top, start,
} }
} }
/* Move MEMs into registers for the duration of the loop. SCAN_START /* Move MEMs into registers for the duration of the loop. */
is the first instruction in the loop (as it is executed). The
other parameters are as for next_insn_in_loop. */
static void static void
load_mems (scan_start, end, loop_top, start) load_mems (loop)
rtx scan_start; const struct loop *loop;
rtx end;
rtx loop_top;
rtx start;
{ {
int maybe_never = 0; int maybe_never = 0;
int i; int i;
...@@ -9792,9 +9709,9 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9792,9 +9709,9 @@ load_mems (scan_start, end, loop_top, start)
/* Check to see if it's possible that some instructions in the /* Check to see if it's possible that some instructions in the
loop are never executed. */ loop are never executed. */
for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top); for (p = next_insn_in_loop (loop, loop->scan_start);
p != NULL_RTX && !maybe_never; p != NULL_RTX && ! maybe_never;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
if (GET_CODE (p) == CODE_LABEL) if (GET_CODE (p) == CODE_LABEL)
maybe_never = 1; maybe_never = 1;
...@@ -9806,8 +9723,8 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9806,8 +9723,8 @@ load_mems (scan_start, end, loop_top, start)
never be executed. Unconditional jumps are never be executed. Unconditional jumps are
followed a by barrier then loop end. */ followed a by barrier then loop end. */
&& ! (GET_CODE (p) == JUMP_INSN && ! (GET_CODE (p) == JUMP_INSN
&& JUMP_LABEL (p) == loop_top && JUMP_LABEL (p) == loop->top
&& NEXT_INSN (NEXT_INSN (p)) == end && NEXT_INSN (NEXT_INSN (p)) == loop->end
&& simplejump_p (p))) && simplejump_p (p)))
{ {
if (!condjump_p (p)) if (!condjump_p (p))
...@@ -9904,9 +9821,9 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9904,9 +9821,9 @@ load_mems (scan_start, end, loop_top, start)
/* Now, replace all references to the MEM with the /* Now, replace all references to the MEM with the
corresponding pesudos. */ corresponding pesudos. */
maybe_never = 0; maybe_never = 0;
for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top); for (p = next_insn_in_loop (loop, loop->scan_start);
p != NULL_RTX; p != NULL_RTX;
p = next_insn_in_loop (p, scan_start, end, loop_top)) p = next_insn_in_loop (loop, p))
{ {
rtx_and_int ri; rtx_and_int ri;
rtx set; rtx set;
...@@ -9947,7 +9864,7 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9947,7 +9864,7 @@ load_mems (scan_start, end, loop_top, start)
/* Load the memory immediately before START, which is /* Load the memory immediately before 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, start); emit_insn_before (set, loop->start);
if (written) if (written)
{ {
...@@ -9956,9 +9873,9 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9956,9 +9873,9 @@ load_mems (scan_start, end, loop_top, start)
/* We must compute the former /* We must compute the former
right-after-the-end label before we insert right-after-the-end label before we insert
the new one. */ the new one. */
end_label = next_label (end); end_label = next_label (loop->end);
label = gen_label_rtx (); label = gen_label_rtx ();
emit_label_after (label, end); emit_label_after (label, loop->end);
} }
/* Store the memory immediately after END, which is /* Store the memory immediately after END, which is
...@@ -9981,7 +9898,7 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9981,7 +9898,7 @@ load_mems (scan_start, end, loop_top, start)
EXECUTE_IF_SET_IN_REG_SET EXECUTE_IF_SET_IN_REG_SET
(&copies, FIRST_PSEUDO_REGISTER, j, (&copies, FIRST_PSEUDO_REGISTER, j,
{ {
try_copy_prop (scan_start, loop_top, end, loop_mems[i].reg, j); try_copy_prop (loop, loop_mems[i].reg, j);
}); });
CLEAR_REG_SET (&copies); CLEAR_REG_SET (&copies);
} }
...@@ -9995,7 +9912,7 @@ load_mems (scan_start, end, loop_top, start) ...@@ -9995,7 +9912,7 @@ load_mems (scan_start, end, loop_top, start)
rr.r1 = end_label; rr.r1 = end_label;
rr.r2 = label; rr.r2 = label;
for (p = start; p != end; p = NEXT_INSN (p)) for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
{ {
for_each_rtx (&p, replace_label, &rr); for_each_rtx (&p, replace_label, &rr);
...@@ -10036,8 +9953,9 @@ note_reg_stored (x, setter, arg) ...@@ -10036,8 +9953,9 @@ note_reg_stored (x, setter, arg)
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. */ The arguments SCAN_START, LOOP_TOP and END are as in load_mems. */
static void static void
try_copy_prop (scan_start, loop_top, end, replacement, regno) try_copy_prop (loop, replacement, regno)
rtx scan_start, loop_top, end, replacement; const struct loop *loop;
rtx replacement;
int regno; int regno;
{ {
/* This is the reg that we are copying from. */ /* This is the reg that we are copying from. */
...@@ -10048,9 +9966,9 @@ try_copy_prop (scan_start, loop_top, end, replacement, regno) ...@@ -10048,9 +9966,9 @@ try_copy_prop (scan_start, loop_top, end, replacement, regno)
int replaced_last = 0; int replaced_last = 0;
int store_is_first = 0; int store_is_first = 0;
for (insn = next_insn_in_loop (scan_start, scan_start, end, loop_top); for (insn = next_insn_in_loop (loop, loop->scan_start);
insn != NULL_RTX; insn != NULL_RTX;
insn = next_insn_in_loop (insn, scan_start, end, loop_top)) insn = next_insn_in_loop (loop, insn))
{ {
rtx set; rtx set;
...@@ -10214,4 +10132,3 @@ replace_label (x, data) ...@@ -10214,4 +10132,3 @@ replace_label (x, data)
return 0; return 0;
} }
...@@ -19,6 +19,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, ...@@ -19,6 +19,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include "varray.h" #include "varray.h"
#include "basic-block.h"
/* Get the luid of an insn. Catch the error of trying to reference the LUID /* Get the luid of an insn. Catch the error of trying to reference the LUID
of an insn added during loop, since these don't have LUIDs. */ of an insn added during loop, since these don't have LUIDs. */
...@@ -159,10 +160,6 @@ struct iv_class { ...@@ -159,10 +160,6 @@ struct iv_class {
struct loop_info struct loop_info
{ {
/* Loop number. */
int num;
/* Loops enclosed by this loop including itself. */
int loops_enclosed;
/* Nonzero if there is a subroutine call in the current loop. */ /* Nonzero if there is a subroutine call in the current loop. */
int has_call; int has_call;
/* Nonzero if there is a volatile memory reference in the current /* Nonzero if there is a volatile memory reference in the current
...@@ -200,11 +197,7 @@ struct loop_info ...@@ -200,11 +197,7 @@ struct loop_info
unsigned HOST_WIDE_INT n_iterations; unsigned HOST_WIDE_INT n_iterations;
/* The number of times the loop body was unrolled. */ /* The number of times the loop body was unrolled. */
unsigned int unroll_number; unsigned int unroll_number;
/* Non-zero if the loop has a NOTE_INSN_LOOP_VTOP. */ int used_count_register;
rtx vtop;
/* Non-zero if the loop has a NOTE_INSN_LOOP_CONT.
A continue statement will generate a branch to NEXT_INSN (cont). */
rtx cont;
}; };
/* Definitions used by the basic induction variable discovery code. */ /* Definitions used by the basic induction variable discovery code. */
...@@ -215,12 +208,8 @@ enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT, ...@@ -215,12 +208,8 @@ enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT,
extern int *uid_luid; extern int *uid_luid;
extern int max_uid_for_loop; extern int max_uid_for_loop;
extern int *uid_loop_num;
extern int *loop_outer_loop;
extern rtx *loop_number_exit_labels;
extern int *loop_number_exit_count;
extern int max_reg_before_loop; extern int max_reg_before_loop;
extern struct loop **uid_loop;
extern FILE *loop_dump_stream; extern FILE *loop_dump_stream;
extern varray_type reg_iv_type; extern varray_type reg_iv_type;
...@@ -243,9 +232,9 @@ rtx get_condition_for_loop PROTO((rtx)); ...@@ -243,9 +232,9 @@ rtx get_condition_for_loop PROTO((rtx));
void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx)); void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
rtx express_from PROTO((struct induction *, struct induction *)); rtx express_from PROTO((struct induction *, struct induction *));
void unroll_loop PROTO((rtx, int, rtx, rtx, struct loop_info *, int)); void unroll_loop PROTO((struct loop *, int, rtx, int));
rtx biv_total_increment PROTO((struct iv_class *, rtx, rtx)); rtx biv_total_increment PROTO((struct iv_class *, rtx, rtx));
unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx, struct loop_info *)); unsigned HOST_WIDE_INT loop_iterations PROTO((struct loop *));
int precondition_loop_p PROTO((rtx, struct loop_info *, int precondition_loop_p PROTO((rtx, struct loop_info *,
rtx *, rtx *, rtx *, rtx *, rtx *, rtx *,
enum machine_mode *mode)); enum machine_mode *mode));
...@@ -261,4 +250,3 @@ int loop_insn_first_p PROTO((rtx, rtx)); ...@@ -261,4 +250,3 @@ int loop_insn_first_p PROTO((rtx, rtx));
/* Forward declarations for non-static functions declared in stmt.c. */ /* Forward declarations for non-static functions declared in stmt.c. */
void find_loop_tree_blocks PROTO((void)); void find_loop_tree_blocks PROTO((void));
void unroll_block_trees PROTO((void)); void unroll_block_trees PROTO((void));
...@@ -225,13 +225,10 @@ static rtx loop_find_equiv_value PROTO((rtx, rtx)); ...@@ -225,13 +225,10 @@ static rtx loop_find_equiv_value PROTO((rtx, rtx));
in loop.c. */ in loop.c. */
void void
unroll_loop (loop_end, insn_count, loop_start, end_insert_before, unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
loop_info, strength_reduce_p) struct loop *loop;
rtx loop_end;
int insn_count; int insn_count;
rtx loop_start;
rtx end_insert_before; rtx end_insert_before;
struct loop_info *loop_info;
int strength_reduce_p; int strength_reduce_p;
{ {
int i, j; int i, j;
...@@ -257,6 +254,9 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -257,6 +254,9 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
a JUMP_INSN (for conditional jumps) or a BARRIER (for unconditional a JUMP_INSN (for conditional jumps) or a BARRIER (for unconditional
jumps). */ jumps). */
rtx last_loop_insn; rtx last_loop_insn;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
struct loop_info *loop_info = loop->info;
/* Don't bother unrolling huge loops. Since the minimum factor is /* Don't bother unrolling huge loops. Since the minimum factor is
two, loops greater than one half of MAX_UNROLLED_INSNS will never two, loops greater than one half of MAX_UNROLLED_INSNS will never
...@@ -370,10 +370,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -370,10 +370,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
} }
/* Remove the loop notes since this is no longer a loop. */ /* Remove the loop notes since this is no longer a loop. */
if (loop_info->vtop) if (loop->vtop)
delete_insn (loop_info->vtop); delete_insn (loop->vtop);
if (loop_info->cont) if (loop->cont)
delete_insn (loop_info->cont); delete_insn (loop->cont);
if (loop_start) if (loop_start)
delete_insn (loop_start); delete_insn (loop_start);
if (loop_end) if (loop_end)
...@@ -1310,10 +1310,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -1310,10 +1310,10 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
if (unroll_type == UNROLL_COMPLETELY) if (unroll_type == UNROLL_COMPLETELY)
{ {
/* Remove the loop notes since this is no longer a loop. */ /* Remove the loop notes since this is no longer a loop. */
if (loop_info->vtop) if (loop->vtop)
delete_insn (loop_info->vtop); delete_insn (loop->vtop);
if (loop_info->cont) if (loop->cont)
delete_insn (loop_info->cont); delete_insn (loop->cont);
if (loop_start) if (loop_start)
delete_insn (loop_start); delete_insn (loop_start);
if (loop_end) if (loop_end)
...@@ -2600,7 +2600,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2600,7 +2600,7 @@ 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
&& (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]] && (uid_loop[INSN_UID (loop_start)]->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
...@@ -2690,7 +2690,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2690,7 +2690,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 (! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) if (! uid_loop[INSN_UID (loop_start)]->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);
...@@ -2817,7 +2817,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment, ...@@ -2817,7 +2817,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
&& (loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]] && (uid_loop[INSN_UID (loop_start)]->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.
...@@ -3245,25 +3245,24 @@ reg_dead_after_loop (reg, loop_start, loop_end) ...@@ -3245,25 +3245,24 @@ reg_dead_after_loop (reg, loop_start, loop_end)
enum rtx_code code; enum rtx_code code;
int jump_count = 0; int jump_count = 0;
int label_count = 0; int label_count = 0;
int this_loop_num = uid_loop_num[INSN_UID (loop_start)]; 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
have any way to identify those, so we just give up if there are any have any way to identify those, so we just give up if there are any
such inner loop exits. */ such inner loop exits. */
for (label = loop_number_exit_labels[this_loop_num]; label; for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
label = LABEL_NEXTREF (label))
label_count++; label_count++;
if (label_count != loop_number_exit_count[this_loop_num]) if (label_count != loop->exit_count)
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_number_exit_labels[this_loop_num]; LABEL_NEXTREF (label) = loop->exit_labels;
for ( ; label; label = LABEL_NEXTREF (label)) for ( ; label; label = LABEL_NEXTREF (label))
{ {
...@@ -3343,7 +3342,7 @@ final_biv_value (bl, loop_start, loop_end, n_iterations) ...@@ -3343,7 +3342,7 @@ 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
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]] && ! uid_loop[INSN_UID (loop_start)]->exit_count
&& invariant_p (bl->initial_value)) && invariant_p (bl->initial_value))
{ {
increment = biv_total_increment (bl, loop_start, loop_end); increment = biv_total_increment (bl, loop_start, loop_end);
...@@ -3423,7 +3422,7 @@ final_giv_value (v, loop_start, loop_end, n_iterations) ...@@ -3423,7 +3422,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
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) && ! uid_loop[INSN_UID (loop_start)]->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
...@@ -3623,9 +3622,8 @@ find_common_reg_term (op0, op1) ...@@ -3623,9 +3622,8 @@ find_common_reg_term (op0, op1)
iterations if it can be calculated, otherwise returns zero. */ iterations if it can be calculated, otherwise returns zero. */
unsigned HOST_WIDE_INT unsigned HOST_WIDE_INT
loop_iterations (loop_start, loop_end, loop_info) loop_iterations (loop)
rtx loop_start, loop_end; struct loop *loop;
struct loop_info *loop_info;
{ {
rtx comparison, comparison_value; rtx comparison, comparison_value;
rtx iteration_var, initial_value, increment, final_value; rtx iteration_var, initial_value, increment, final_value;
...@@ -3637,6 +3635,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3637,6 +3635,7 @@ loop_iterations (loop_start, loop_end, loop_info)
int unsigned_p, compare_dir, final_larger; int unsigned_p, compare_dir, final_larger;
rtx last_loop_insn; rtx last_loop_insn;
rtx reg_term; rtx reg_term;
struct loop_info *loop_info = loop->info;
loop_info->n_iterations = 0; loop_info->n_iterations = 0;
loop_info->initial_value = 0; loop_info->initial_value = 0;
...@@ -3652,7 +3651,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3652,7 +3651,7 @@ loop_iterations (loop_start, loop_end, loop_info)
accidentally get the branch for a contained loop if the branch for this accidentally get the branch for a contained loop if the branch for this
loop was deleted. We can only trust branches immediately before the loop was deleted. We can only trust branches immediately before the
loop_end. */ loop_end. */
last_loop_insn = PREV_INSN (loop_end); last_loop_insn = PREV_INSN (loop->end);
/* ??? We should probably try harder to find the jump insn /* ??? We should probably try harder to find the jump insn
at the end of the loop. The following code assumes that at the end of the loop. The following code assumes that
...@@ -3703,12 +3702,14 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3703,12 +3702,14 @@ loop_iterations (loop_start, loop_end, loop_info)
return 0; return 0;
} }
/* This can happen due to optimization in load_mems. */ /* The only new registers that care created before loop iterations are
givs made from biv increments, so this should never occur. */
if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements) if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
return 0; abort ();
iteration_info (iteration_var, &initial_value, &increment, iteration_info (iteration_var, &initial_value, &increment,
loop_start, loop_end); 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;
...@@ -3755,7 +3756,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3755,7 +3756,7 @@ loop_iterations (loop_start, loop_end, loop_info)
final_value = comparison_value; final_value = comparison_value;
if (GET_CODE (comparison_value) == REG && invariant_p (comparison_value)) if (GET_CODE (comparison_value) == REG && invariant_p (comparison_value))
{ {
final_value = loop_find_equiv_value (loop_start, comparison_value); final_value = loop_find_equiv_value (loop->start, 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 (!invariant_p (final_value))
...@@ -3815,7 +3816,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3815,7 +3816,7 @@ loop_iterations (loop_start, loop_end, loop_info)
/* 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->start, reg1);
if (find_common_reg_term (temp, reg2)) if (find_common_reg_term (temp, reg2))
initial_value = temp; initial_value = temp;
else else
...@@ -3823,7 +3824,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3823,7 +3824,7 @@ loop_iterations (loop_start, loop_end, loop_info)
/* 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->start, 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)
...@@ -3831,7 +3832,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3831,7 +3832,7 @@ loop_iterations (loop_start, loop_end, loop_info)
? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2); ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
} }
} }
else if (loop_info->vtop && GET_CODE (reg2) == CONST_INT) else if (loop->vtop && GET_CODE (reg2) == CONST_INT)
{ {
rtx temp; rtx temp;
...@@ -3842,10 +3843,10 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3842,10 +3843,10 @@ loop_iterations (loop_start, loop_end, loop_info)
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->start, 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->start, 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);
...@@ -3862,7 +3863,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3862,7 +3863,7 @@ loop_iterations (loop_start, loop_end, loop_info)
??? Without a vtop we could still perform the optimization if we check ??? Without a vtop we could still perform the optimization if we check
the initial and final values carefully. */ the initial and final values carefully. */
if (loop_info->vtop if (loop->vtop
&& (reg_term = find_common_reg_term (initial_value, final_value))) && (reg_term = find_common_reg_term (initial_value, final_value)))
{ {
initial_value = subtract_reg_term (initial_value, reg_term); initial_value = subtract_reg_term (initial_value, reg_term);
...@@ -3892,7 +3893,7 @@ loop_iterations (loop_start, loop_end, loop_info) ...@@ -3892,7 +3893,7 @@ loop_iterations (loop_start, loop_end, loop_info)
/* ??? 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->start, 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