Commit 302670f3 by Michael Hayes Committed by Michael Hayes

loop.h (struct loop_info): Define new structure.

	* loop.h (struct loop_info): Define new structure.
	(precondition_loop_p): Added prototype.
	(unroll_loop): Added new argument loop_info to prototype.
	(final_biv_value, final_giv_value): Added new argument n_iterations
	to prototype.
	* loop.c (strength_reduce): Declare new structure loop_iteration_info
	and new pointer loop_info.
	(loop_n_iterations): Replace global variable by element in
	loop_info structure.
	(check_final_value): New argument n_iterations.
	(insert_bct): New argument loop_info.
	(loop_unroll_factor): Replace global array by element in
	loop_info structure.
	(loop_optimize): Remove code to allocate and initialise
	loop_unroll_factor_array.
	* unroll.c (precondition_loop_p):  No longer static since
	used by branch on count optimization.
	(precondition_loop_p, unroll_loop): New argument loop_info.
	(final_biv_value, final_giv_value, find_splittable_regs): New
	argument n_iterations.
	(loop_iteration_var, loop_initial_value, loop_increment,
	loop_final_value, loop_comparison_code, loop_unroll_factor):
	Replaced global variables by loop_info structure.
	(loop_unroll_factor): Replace global array by element in
	loop_info structure.

From-SVN: r23884
parent a7060368
Thu Nov 26 18:05:04 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* loop.h (struct loop_info): Define new structure.
(precondition_loop_p): Added prototype.
(unroll_loop): Added new argument loop_info to prototype.
(final_biv_value, final_giv_value): Added new argument n_iterations
to prototype.
* loop.c (strength_reduce): Declare new structure loop_iteration_info
and new pointer loop_info.
(loop_n_iterations): Replace global variable by element in
loop_info structure.
(check_final_value): New argument n_iterations.
(insert_bct): New argument loop_info.
(loop_unroll_factor): Replace global array by element in
loop_info structure.
(loop_optimize): Remove code to allocate and initialise
loop_unroll_factor_array.
* unroll.c (precondition_loop_p): No longer static since
used by branch on count optimization.
(precondition_loop_p, unroll_loop): New argument loop_info.
(final_biv_value, final_giv_value, find_splittable_regs): New
argument n_iterations.
(loop_iteration_var, loop_initial_value, loop_increment,
loop_final_value, loop_comparison_code, loop_unroll_factor):
Replaced global variables by loop_info structure.
(loop_unroll_factor): Replace global array by element in
loop_info structure.
Thu Nov 26 17:49:29 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz> Thu Nov 26 17:49:29 1998 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* loop.c (check_dbra_loop): Update JUMP_LABEL field of jump insn * loop.c (check_dbra_loop): Update JUMP_LABEL field of jump insn
......
...@@ -88,14 +88,6 @@ int *loop_outer_loop; ...@@ -88,14 +88,6 @@ int *loop_outer_loop;
int *loop_used_count_register; int *loop_used_count_register;
#endif /* HAVE_decrement_and_branch_on_count */ #endif /* HAVE_decrement_and_branch_on_count */
/* For each loop, keep track of its unrolling factor.
Potential values:
0: unrolled
1: not unrolled.
-1: completely unrolled
>0: holds the unroll exact factor. */
int *loop_unroll_factor;
/* Indexed by loop number, contains a nonzero value if the "loop" isn't /* Indexed by loop number, contains a nonzero value if the "loop" isn't
really a loop (an insn outside the loop branches into it). */ really a loop (an insn outside the loop branches into it). */
...@@ -118,14 +110,6 @@ rtx *loop_number_exit_labels; ...@@ -118,14 +110,6 @@ rtx *loop_number_exit_labels;
int *loop_number_exit_count; int *loop_number_exit_count;
/* Holds the number of loop iterations. It is zero if the number could not be
calculated. Must be unsigned since the number of iterations can
be as high as 2^wordsize-1. For loops with a wider iterator, this number
will be zero if the number of loop iterations is too large for an
unsigned integer to hold. */
unsigned HOST_WIDE_INT loop_n_iterations;
/* Nonzero if there is a subroutine call in the current loop. */ /* Nonzero if there is a subroutine call in the current loop. */
static int loop_has_call; static int loop_has_call;
...@@ -320,7 +304,8 @@ static void find_single_use_in_loop PROTO((rtx, rtx, varray_type)); ...@@ -320,7 +304,8 @@ static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
static int valid_initial_value_p PROTO((rtx, rtx, int, rtx)); static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx)); static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx));
static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, int, int)); static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, int, int));
static void check_final_value PROTO((struct induction *, rtx, rtx)); static void check_final_value PROTO((struct induction *, rtx, rtx,
unsigned HOST_WIDE_INT));
static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, rtx *, rtx, rtx)); static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, 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 *)); static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *));
...@@ -365,7 +350,7 @@ typedef struct rtx_pair { ...@@ -365,7 +350,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)); static void insert_bct PROTO((rtx, rtx, struct loop_info *));
/* 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));
...@@ -478,12 +463,6 @@ loop_optimize (f, dumpfile, unroll_p, bct_p) ...@@ -478,12 +463,6 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx)); loop_number_exit_labels = (rtx *) alloca (max_loop_num * sizeof (rtx));
loop_number_exit_count = (int *) alloca (max_loop_num * sizeof (int)); loop_number_exit_count = (int *) alloca (max_loop_num * sizeof (int));
/* This is initialized by the unrolling code, so we go ahead
and clear them just in case we are not performing loop
unrolling. */
loop_unroll_factor = (int *) alloca (max_loop_num *sizeof (int));
bzero ((char *) loop_unroll_factor, max_loop_num * sizeof (int));
#ifdef HAVE_decrement_and_branch_on_count #ifdef HAVE_decrement_and_branch_on_count
/* Allocate for BCT optimization */ /* Allocate for BCT optimization */
loop_used_count_register = (int *) alloca (max_loop_num * sizeof (int)); loop_used_count_register = (int *) alloca (max_loop_num * sizeof (int));
...@@ -3573,6 +3552,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3573,6 +3552,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
rtx test; rtx test;
rtx end_insert_before; rtx end_insert_before;
int loop_depth = 0; int loop_depth = 0;
struct loop_info loop_iteration_info;
struct loop_info *loop_info = &loop_iteration_info;
reg_iv_type = (enum iv_mode *) alloca (max_reg_before_loop reg_iv_type = (enum iv_mode *) alloca (max_reg_before_loop
* sizeof (enum iv_mode)); * sizeof (enum iv_mode));
...@@ -3771,7 +3752,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -3771,7 +3752,8 @@ 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, 0); unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
loop_info, 0);
return; return;
} }
...@@ -4040,7 +4022,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4040,7 +4022,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_n_iterations = loop_iterations (loop_start, loop_end); loop_iterations (loop_start, loop_end, loop_info);
/* 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
...@@ -4053,7 +4035,7 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4053,7 +4035,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
for (v = bl->giv; v; v = v->next_iv) for (v = bl->giv; v; v = v->next_iv)
if (! v->replaceable && ! v->not_replaceable) if (! v->replaceable && ! v->not_replaceable)
check_final_value (v, loop_start, loop_end); check_final_value (v, loop_start, loop_end, loop_info->n_iterations);
} }
/* Try to prove that the loop counter variable (if any) is always /* Try to prove that the loop counter variable (if any) is always
...@@ -4099,7 +4081,8 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4099,7 +4081,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& ! bl->nonneg && ! bl->nonneg
#endif #endif
&& ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
|| ((final_value = final_biv_value (bl, loop_start, loop_end)) || ((final_value = final_biv_value (bl, loop_start, loop_end,
loop_info->n_iterations))
#ifdef HAVE_decrement_and_branch_until_zero #ifdef HAVE_decrement_and_branch_until_zero
&& ! bl->nonneg && ! bl->nonneg
#endif #endif
...@@ -4562,13 +4545,14 @@ strength_reduce (scan_start, end, loop_top, insn_count, ...@@ -4562,13 +4545,14 @@ strength_reduce (scan_start, end, loop_top, insn_count,
collected. */ collected. */
if (unroll_p) if (unroll_p)
unroll_loop (loop_end, insn_count, loop_start, end_insert_before, 1); unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
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); insert_bct (loop_start, loop_end, loop_info);
#endif /* HAVE_decrement_and_branch_on_count */ #endif /* HAVE_decrement_and_branch_on_count */
if (loop_dump_stream) if (loop_dump_stream)
...@@ -5058,9 +5042,10 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit, ...@@ -5058,9 +5042,10 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
have been identified. */ have been identified. */
static void static void
check_final_value (v, loop_start, loop_end) check_final_value (v, loop_start, loop_end, n_iterations)
struct induction *v; struct induction *v;
rtx loop_start, loop_end; rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
rtx final_value = 0; rtx final_value = 0;
...@@ -5087,7 +5072,7 @@ check_final_value (v, loop_start, loop_end) ...@@ -5087,7 +5072,7 @@ check_final_value (v, loop_start, loop_end)
v->replaceable = 0; v->replaceable = 0;
#endif #endif
if ((final_value = final_giv_value (v, loop_start, loop_end)) if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations))
&& (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn))) && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
{ {
int biv_increment_seen = 0; int biv_increment_seen = 0;
...@@ -7965,8 +7950,9 @@ get_condition_for_loop (x) ...@@ -7965,8 +7950,9 @@ get_condition_for_loop (x)
*/ */
static void static void
insert_bct (loop_start, loop_end) insert_bct (loop_start, loop_end, loop_info)
rtx loop_start, loop_end; rtx loop_start, loop_end;
struct loop_info *loop_info;
{ {
int i; int i;
unsigned HOST_WIDE_INT n_iterations; unsigned HOST_WIDE_INT n_iterations;
...@@ -7982,7 +7968,7 @@ insert_bct (loop_start, loop_end) ...@@ -7982,7 +7968,7 @@ insert_bct (loop_start, loop_end)
int loop_num = uid_loop_num [INSN_UID (loop_start)]; 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_unroll_factor [loop_num] == -1) if (loop_info->unroll_number == -1)
return; return;
/* Make sure that the count register is not in use. */ /* Make sure that the count register is not in use. */
...@@ -8040,10 +8026,10 @@ insert_bct (loop_start, loop_end) ...@@ -8040,10 +8026,10 @@ insert_bct (loop_start, loop_end)
} }
/* Account for loop unrolling in instrumented iteration count. */ /* Account for loop unrolling in instrumented iteration count. */
if (loop_unroll_factor [loop_num] > 1) if (loop_info->unroll_number > 1)
n_iterations = loop_n_iterations / loop_unroll_factor [loop_num]; n_iterations = loop_info->n_iterations / loop_info->unroll_number;
else else
n_iterations = loop_n_iterations; n_iterations = loop_info->n_iterations;
if (n_iterations != 0 && n_iterations < 3) if (n_iterations != 0 && n_iterations < 3)
{ {
...@@ -8071,7 +8057,7 @@ insert_bct (loop_start, loop_end) ...@@ -8071,7 +8057,7 @@ insert_bct (loop_start, loop_end)
at compile time. In this case we generate run_time calculation at compile time. In this case we generate run_time calculation
of the number of iterations. */ of the number of iterations. */
if (loop_iteration_var == 0) if (loop_info->iteration_var == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -8080,8 +8066,8 @@ insert_bct (loop_start, loop_end) ...@@ -8080,8 +8066,8 @@ insert_bct (loop_start, loop_end)
return; return;
} }
if (GET_MODE_CLASS (GET_MODE (loop_iteration_var)) != MODE_INT if (GET_MODE_CLASS (GET_MODE (loop_info->iteration_var)) != MODE_INT
|| GET_MODE_SIZE (GET_MODE (loop_iteration_var)) != UNITS_PER_WORD) || GET_MODE_SIZE (GET_MODE (loop_info->iteration_var)) != UNITS_PER_WORD)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -8091,7 +8077,7 @@ insert_bct (loop_start, loop_end) ...@@ -8091,7 +8077,7 @@ insert_bct (loop_start, loop_end)
} }
/* With runtime bounds, if the compare is of the form '!=' we give up */ /* With runtime bounds, if the compare is of the form '!=' we give up */
if (loop_comparison_code == NE) if (loop_info->comparison_code == NE)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
......
...@@ -143,6 +143,43 @@ struct iv_class { ...@@ -143,6 +143,43 @@ struct iv_class {
biv controls. */ biv controls. */
}; };
/* Information required to calculate the number of loop iterations.
This is set by loop_iterations. */
struct loop_info
{
/* Register or constant initial loop value. */
rtx initial_value;
/* Register or constant value used for comparison test. */
rtx comparison_value;
/* Register or constant approximate final value. */
rtx final_value;
/* Register or constant initial loop value with term common to
final_value removed. */
rtx initial_equiv_value;
/* Register or constant final loop value with term common to
initial_value removed. */
rtx final_equiv_value;
/* Register corresponding to iteration variable. */
rtx iteration_var;
/* Constant loop increment. */
rtx increment;
enum rtx_code comparison_code;
/* Holds the number of loop iterations. It is zero if the number
could not be calculated. Must be unsigned since the number of
iterations can be as high as 2^wordsize - 1. For loops with a
wider iterator, this number will be zero if the number of loop
iterations is too large for an unsigned integer to hold. */
unsigned HOST_WIDE_INT n_iterations;
/* The loop unrolling factor.
Potential values:
0: unrolled
1: not unrolled.
-1: completely unrolled
>0: holds the unroll exact factor. */
int unroll_number;
};
/* Definitions used by the basic induction variable discovery code. */ /* Definitions used by the basic induction variable discovery code. */
enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT, enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT,
GENERAL_INDUCT }; GENERAL_INDUCT };
...@@ -155,7 +192,6 @@ extern int *uid_loop_num; ...@@ -155,7 +192,6 @@ extern int *uid_loop_num;
extern int *loop_outer_loop; extern int *loop_outer_loop;
extern rtx *loop_number_exit_labels; extern rtx *loop_number_exit_labels;
extern int *loop_number_exit_count; extern int *loop_number_exit_count;
extern unsigned HOST_WIDE_INT loop_n_iterations;
extern int max_reg_before_loop; extern int max_reg_before_loop;
extern FILE *loop_dump_stream; extern FILE *loop_dump_stream;
...@@ -175,21 +211,18 @@ void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx)); ...@@ -175,21 +211,18 @@ void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
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));
void unroll_loop PROTO((rtx, int, rtx, rtx, int)); void unroll_loop PROTO((rtx, int, rtx, rtx, struct loop_info *, 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)); unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx, struct loop_info *));
rtx final_biv_value PROTO((struct iv_class *, rtx, rtx)); int precondition_loop_p PROTO((rtx, struct loop_info *,
rtx final_giv_value PROTO((struct induction *, rtx, rtx)); rtx *, rtx *, rtx *));
rtx final_biv_value PROTO((struct iv_class *, rtx, rtx,
unsigned HOST_WIDE_INT));
rtx final_giv_value PROTO((struct induction *, rtx, rtx,
unsigned HOST_WIDE_INT));
void emit_unrolled_add PROTO((rtx, rtx, rtx)); void emit_unrolled_add PROTO((rtx, rtx, rtx));
int back_branch_in_range_p PROTO((rtx, rtx, rtx)); int back_branch_in_range_p PROTO((rtx, rtx, rtx));
extern int *loop_unroll_factor; extern int *loop_unroll_number;
#ifdef HAVE_decrement_and_branch_on_count
extern rtx loop_iteration_var;
extern rtx loop_initial_value;
extern rtx loop_increment;
extern rtx loop_final_value;
extern enum rtx_code loop_comparison_code;
#endif /* HAVE_decrement_and_branch_on_count */
...@@ -186,19 +186,9 @@ static rtx *splittable_regs; ...@@ -186,19 +186,9 @@ static rtx *splittable_regs;
static int *splittable_regs_updates; static int *splittable_regs_updates;
/* Values describing the current loop's iteration variable. These are set up
by loop_iterations, and used by precondition_loop_p. */
rtx loop_iteration_var;
rtx loop_initial_value;
rtx loop_increment;
rtx loop_final_value;
enum rtx_code loop_comparison_code;
/* Forward declarations. */ /* Forward declarations. */
static void init_reg_map PROTO((struct inline_remap *, int)); static void init_reg_map PROTO((struct inline_remap *, int));
static int precondition_loop_p PROTO((rtx *, rtx *, rtx *, rtx));
static rtx calculate_giv_inc PROTO((rtx, rtx, int)); static rtx calculate_giv_inc PROTO((rtx, rtx, int));
static rtx initial_reg_note_copy PROTO((rtx, struct inline_remap *)); static rtx initial_reg_note_copy PROTO((rtx, struct inline_remap *));
static void final_reg_note_copy PROTO((rtx, struct inline_remap *)); static void final_reg_note_copy PROTO((rtx, struct inline_remap *));
...@@ -206,8 +196,9 @@ static void copy_loop_body PROTO((rtx, rtx, struct inline_remap *, rtx, int, ...@@ -206,8 +196,9 @@ static void copy_loop_body PROTO((rtx, rtx, struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx)); enum unroll_types, rtx, rtx, rtx, rtx));
void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx)); void iteration_info PROTO((rtx, rtx *, rtx *, rtx, rtx));
static rtx approx_final_value PROTO((enum rtx_code, rtx, int *, int *)); static rtx approx_final_value PROTO((enum rtx_code, rtx, int *, int *));
static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int)); static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int,
static int find_splittable_givs PROTO((struct iv_class *,enum unroll_types, unsigned HOST_WIDE_INT));
static int find_splittable_givs PROTO((struct iv_class *, enum unroll_types,
rtx, rtx, rtx, int)); rtx, rtx, rtx, int));
static int reg_dead_after_loop PROTO((rtx, rtx, rtx)); static int reg_dead_after_loop PROTO((rtx, rtx, rtx));
static rtx fold_rtx_mult_add PROTO((rtx, rtx, rtx, enum machine_mode)); static rtx fold_rtx_mult_add PROTO((rtx, rtx, rtx, enum machine_mode));
...@@ -227,11 +218,12 @@ static rtx remap_split_bivs PROTO((rtx)); ...@@ -227,11 +218,12 @@ static rtx remap_split_bivs PROTO((rtx));
void void
unroll_loop (loop_end, insn_count, loop_start, end_insert_before, unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
strength_reduce_p) loop_info, strength_reduce_p)
rtx loop_end; rtx loop_end;
int insn_count; int insn_count;
rtx loop_start; 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, temp; int i, j, temp;
...@@ -304,18 +296,19 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -304,18 +296,19 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* Determine type of unroll to perform. Depends on the number of iterations /* Determine type of unroll to perform. Depends on the number of iterations
and the size of the loop. */ and the size of the loop. */
/* If there is no strength reduce info, then set loop_n_iterations to zero. /* If there is no strength reduce info, then set
This can happen if strength_reduce can't find any bivs in the loop. loop_info->n_iterations to zero. This can happen if
A value of zero indicates that the number of iterations could not be strength_reduce can't find any bivs in the loop. A value of zero
calculated. */ indicates that the number of iterations could not be calculated. */
if (! strength_reduce_p) if (! strength_reduce_p)
loop_n_iterations = 0; loop_info->n_iterations = 0;
if (loop_dump_stream && loop_n_iterations > 0) if (loop_dump_stream && loop_info->n_iterations > 0)
{ {
fputs ("Loop unrolling: ", loop_dump_stream); fputs ("Loop unrolling: ", loop_dump_stream);
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, loop_n_iterations); fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
loop_info->n_iterations);
fputs (" iterations.\n", loop_dump_stream); fputs (" iterations.\n", loop_dump_stream);
} }
...@@ -326,7 +319,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -326,7 +319,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* Calculate how many times to unroll the loop. Indicate whether or /* Calculate how many times to unroll the loop. Indicate whether or
not the loop is being completely unrolled. */ not the loop is being completely unrolled. */
if (loop_n_iterations == 1) if (loop_info->n_iterations == 1)
{ {
/* If number of iterations is exactly 1, then eliminate the compare and /* If number of iterations is exactly 1, then eliminate the compare and
branch at the end of the loop since they will never be taken. branch at the end of the loop since they will never be taken.
...@@ -355,13 +348,13 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -355,13 +348,13 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
} }
return; return;
} }
else if (loop_n_iterations > 0 else if (loop_info->n_iterations > 0
&& loop_n_iterations * insn_count < MAX_UNROLLED_INSNS) && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
{ {
unroll_number = loop_n_iterations; unroll_number = loop_info->n_iterations;
unroll_type = UNROLL_COMPLETELY; unroll_type = UNROLL_COMPLETELY;
} }
else if (loop_n_iterations > 0) else if (loop_info->n_iterations > 0)
{ {
/* Try to factor the number of iterations. Don't bother with the /* Try to factor the number of iterations. Don't bother with the
general case, only using 2, 3, 5, and 7 will get 75% of all general case, only using 2, 3, 5, and 7 will get 75% of all
...@@ -370,7 +363,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -370,7 +363,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
for (i = 0; i < NUM_FACTORS; i++) for (i = 0; i < NUM_FACTORS; i++)
factors[i].count = 0; factors[i].count = 0;
temp = loop_n_iterations; temp = loop_info->n_iterations;
for (i = NUM_FACTORS - 1; i >= 0; i--) for (i = NUM_FACTORS - 1; i >= 0; i--)
while (temp % factors[i].factor == 0) while (temp % factors[i].factor == 0)
{ {
...@@ -857,8 +850,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -857,8 +850,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
{ {
rtx initial_value, final_value, increment; rtx initial_value, final_value, increment;
if (precondition_loop_p (&initial_value, &final_value, &increment, if (precondition_loop_p (loop_start, loop_info,
loop_start)) &initial_value, &final_value, &increment))
{ {
register rtx diff ; register rtx diff ;
enum machine_mode mode; enum machine_mode mode;
...@@ -939,7 +932,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -939,7 +932,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
case. This check does not apply if the loop has a NE case. This check does not apply if the loop has a NE
comparison at the end. */ comparison at the end. */
if (loop_comparison_code != NE) if (loop_info->comparison_code != NE)
{ {
emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE, emit_cmp_insn (initial_value, final_value, neg_inc ? LE : GE,
NULL_RTX, mode, 0, 0); NULL_RTX, mode, 0, 0);
...@@ -1141,11 +1134,11 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -1141,11 +1134,11 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
/* At this point, we are guaranteed to unroll the loop. */ /* At this point, we are guaranteed to unroll the loop. */
/* Keep track of the unroll factor for each loop. */ /* Keep track of the unroll factor for the loop. */
if (unroll_type == UNROLL_COMPLETELY) if (unroll_type == UNROLL_COMPLETELY)
loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = -1; loop_info->unroll_number = -1;
else else
loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = unroll_number; loop_info->unroll_number = unroll_number;
/* For each biv and giv, determine whether it can be safely split into /* For each biv and giv, determine whether it can be safely split into
...@@ -1160,7 +1153,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -1160,7 +1153,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
temp = 0; temp = 0;
else else
temp = find_splittable_regs (unroll_type, loop_start, loop_end, temp = find_splittable_regs (unroll_type, loop_start, loop_end,
end_insert_before, unroll_number); end_insert_before, unroll_number,
loop_info->n_iterations);
/* find_splittable_regs may have created some new registers, so must /* find_splittable_regs may have created some new registers, so must
reallocate the reg_map with the new larger size, and must realloc reallocate the reg_map with the new larger size, and must realloc
...@@ -1318,52 +1312,54 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before, ...@@ -1318,52 +1312,54 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
when the increment is not a power of 2. Use RTX_COST to compute when the increment is not a power of 2. Use RTX_COST to compute
whether divide is cheap. */ whether divide is cheap. */
static int int
precondition_loop_p (initial_value, final_value, increment, loop_start) precondition_loop_p (loop_start, loop_info,
rtx *initial_value, *final_value, *increment; initial_value, final_value, increment)
rtx loop_start; rtx loop_start;
struct loop_info *loop_info;
rtx *initial_value, *final_value, *increment;
{ {
if (loop_n_iterations > 0) if (loop_info->n_iterations > 0)
{ {
*initial_value = const0_rtx; *initial_value = const0_rtx;
*increment = const1_rtx; *increment = const1_rtx;
*final_value = GEN_INT (loop_n_iterations); *final_value = GEN_INT (loop_info->n_iterations);
if (loop_dump_stream) if (loop_dump_stream)
{ {
fputs ("Preconditioning: Success, number of iterations known, ", fputs ("Preconditioning: Success, number of iterations known, ",
loop_dump_stream); loop_dump_stream);
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
loop_n_iterations); loop_info->n_iterations);
fputs (".\n", loop_dump_stream); fputs (".\n", loop_dump_stream);
} }
return 1; return 1;
} }
if (loop_initial_value == 0) if (loop_info->initial_value == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"Preconditioning: Could not find initial value.\n"); "Preconditioning: Could not find initial value.\n");
return 0; return 0;
} }
else if (loop_increment == 0) else if (loop_info->increment == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"Preconditioning: Could not find increment value.\n"); "Preconditioning: Could not find increment value.\n");
return 0; return 0;
} }
else if (GET_CODE (loop_increment) != CONST_INT) else if (GET_CODE (loop_info->increment) != CONST_INT)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"Preconditioning: Increment not a constant.\n"); "Preconditioning: Increment not a constant.\n");
return 0; return 0;
} }
else if ((exact_log2 (INTVAL (loop_increment)) < 0) else if ((exact_log2 (INTVAL (loop_info->increment)) < 0)
&& (exact_log2 (- INTVAL (loop_increment)) < 0)) && (exact_log2 (- INTVAL (loop_info->increment)) < 0))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -1374,7 +1370,7 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) ...@@ -1374,7 +1370,7 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
/* Unsigned_compare and compare_dir can be ignored here, since they do /* Unsigned_compare and compare_dir can be ignored here, since they do
not matter for preconditioning. */ not matter for preconditioning. */
if (loop_final_value == 0) if (loop_info->final_value == 0)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -1387,11 +1383,11 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) ...@@ -1387,11 +1383,11 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
to make sure that the register is in the range covered by invariant_p. to make sure that the register is in the range covered by invariant_p.
If it isn't, then it is most likely a biv/giv which by definition are If it isn't, then it is most likely a biv/giv which by definition are
not invariant. */ not invariant. */
if ((GET_CODE (loop_final_value) == REG if ((GET_CODE (loop_info->final_value) == REG
&& REGNO (loop_final_value) >= max_reg_before_loop) && REGNO (loop_info->final_value) >= max_reg_before_loop)
|| (GET_CODE (loop_final_value) == PLUS || (GET_CODE (loop_info->final_value) == PLUS
&& REGNO (XEXP (loop_final_value, 0)) >= max_reg_before_loop) && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
|| ! invariant_p (loop_final_value)) || ! invariant_p (loop_info->final_value))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -1401,8 +1397,8 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) ...@@ -1401,8 +1397,8 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
/* Fail for floating point values, since the caller of this function /* Fail for floating point values, since the caller of this function
does not have code to deal with them. */ does not have code to deal with them. */
if (GET_MODE_CLASS (GET_MODE (loop_final_value)) == MODE_FLOAT if (GET_MODE_CLASS (GET_MODE (loop_info->final_value)) == MODE_FLOAT
|| GET_MODE_CLASS (GET_MODE (loop_initial_value)) == MODE_FLOAT) || GET_MODE_CLASS (GET_MODE (loop_info->initial_value)) == MODE_FLOAT)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -1410,10 +1406,10 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) ...@@ -1410,10 +1406,10 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
return 0; return 0;
} }
/* Fail if loop_iteration_var is not live before loop_start, since we need /* Fail if loop_info->iteration_var is not live before loop_start,
to test its value in the preconditioning code. */ since we need to test its value in the preconditioning code. */
if (uid_luid[REGNO_FIRST_UID (REGNO (loop_iteration_var))] if (uid_luid[REGNO_FIRST_UID (REGNO (loop_info->iteration_var))]
> INSN_LUID (loop_start)) > INSN_LUID (loop_start))
{ {
if (loop_dump_stream) if (loop_dump_stream)
...@@ -1430,9 +1426,9 @@ precondition_loop_p (initial_value, final_value, increment, loop_start) ...@@ -1430,9 +1426,9 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
Also note that the absolute values of initial_value and Also note that the absolute values of initial_value and
final_value are unimportant as only their difference is used for final_value are unimportant as only their difference is used for
calculating the number of loop iterations. */ calculating the number of loop iterations. */
*initial_value = loop_initial_value; *initial_value = loop_info->initial_value;
*increment = loop_increment; *increment = loop_info->increment;
*final_value = loop_final_value; *final_value = loop_info->final_value;
/* Success! */ /* Success! */
if (loop_dump_stream) if (loop_dump_stream)
...@@ -2361,7 +2357,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end) ...@@ -2361,7 +2357,7 @@ iteration_info (iteration_var, initial_value, increment, loop_start, loop_end)
/* Reject iteration variables larger than the host wide int size, since they /* Reject iteration variables larger than the host wide int size, since they
could result in a number of iterations greater than the range of our could result in a number of iterations greater than the range of our
`unsigned HOST_WIDE_INT' variable loop_n_iterations. */ `unsigned HOST_WIDE_INT' variable loop_info->n_iterations. */
else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var)) else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
> HOST_BITS_PER_WIDE_INT)) > HOST_BITS_PER_WIDE_INT))
{ {
...@@ -2506,11 +2502,12 @@ approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir) ...@@ -2506,11 +2502,12 @@ approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir)
static int static int
find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
unroll_number) unroll_number, n_iterations)
enum unroll_types unroll_type; enum unroll_types unroll_type;
rtx loop_start, loop_end; rtx loop_start, loop_end;
rtx end_insert_before; rtx end_insert_before;
int unroll_number; int unroll_number;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
struct induction *v; struct induction *v;
...@@ -2548,7 +2545,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before, ...@@ -2548,7 +2545,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
|| (uid_luid[REGNO_FIRST_UID (bl->regno)] || (uid_luid[REGNO_FIRST_UID (bl->regno)]
< INSN_LUID (bl->init_insn)) < INSN_LUID (bl->init_insn))
|| reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set))) || reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
&& ! (biv_final_value = final_biv_value (bl, loop_start, loop_end))) && ! (biv_final_value = final_biv_value (bl, loop_start, loop_end,
n_iterations)))
biv_splittable = 0; biv_splittable = 0;
/* If any of the insns setting the BIV don't do so with a simple /* If any of the insns setting the BIV don't do so with a simple
...@@ -3201,9 +3199,10 @@ reg_dead_after_loop (reg, loop_start, loop_end) ...@@ -3201,9 +3199,10 @@ reg_dead_after_loop (reg, loop_start, loop_end)
the end of the loop. If we can do it, return that value. */ the end of the loop. If we can do it, return that value. */
rtx rtx
final_biv_value (bl, loop_start, loop_end) final_biv_value (bl, loop_start, loop_end, n_iterations)
struct iv_class *bl; struct iv_class *bl;
rtx loop_start, loop_end; rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
rtx increment, tem; rtx increment, tem;
...@@ -3231,7 +3230,7 @@ final_biv_value (bl, loop_start, loop_end) ...@@ -3231,7 +3230,7 @@ final_biv_value (bl, loop_start, loop_end)
it may not have its final value when the loop exits), and the initial it may not have its final value when the loop exits), and the initial
value of the biv must be invariant. */ value of the biv must be invariant. */
if (loop_n_iterations != 0 if (n_iterations != 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]] && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]
&& invariant_p (bl->initial_value)) && invariant_p (bl->initial_value))
{ {
...@@ -3248,7 +3247,7 @@ final_biv_value (bl, loop_start, loop_end) ...@@ -3248,7 +3247,7 @@ final_biv_value (bl, loop_start, loop_end)
/* Make sure loop_end is not the last insn. */ /* Make sure loop_end is not the last insn. */
if (NEXT_INSN (loop_end) == 0) if (NEXT_INSN (loop_end) == 0)
emit_note_after (NOTE_INSN_DELETED, loop_end); emit_note_after (NOTE_INSN_DELETED, loop_end);
emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), emit_iv_add_mult (increment, GEN_INT (n_iterations),
bl->initial_value, tem, NEXT_INSN (loop_end)); bl->initial_value, tem, NEXT_INSN (loop_end));
if (loop_dump_stream) if (loop_dump_stream)
...@@ -3277,9 +3276,10 @@ final_biv_value (bl, loop_start, loop_end) ...@@ -3277,9 +3276,10 @@ final_biv_value (bl, loop_start, loop_end)
the end of the loop. If we can do it, return that value. */ the end of the loop. If we can do it, return that value. */
rtx rtx
final_giv_value (v, loop_start, loop_end) final_giv_value (v, loop_start, loop_end, n_iterations)
struct induction *v; struct induction *v;
rtx loop_start, loop_end; rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{ {
struct iv_class *bl; struct iv_class *bl;
rtx insn; rtx insn;
...@@ -3310,7 +3310,7 @@ final_giv_value (v, loop_start, loop_end) ...@@ -3310,7 +3310,7 @@ final_giv_value (v, loop_start, loop_end)
only one exit for this to work, but the loop iterations does not need only one exit for this to work, but the loop iterations does not need
to be known. */ to be known. */
if (loop_n_iterations != 0 if (n_iterations != 0
&& ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]]) && ! loop_number_exit_count[uid_loop_num[INSN_UID (loop_start)]])
{ {
/* ?? 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
...@@ -3330,7 +3330,7 @@ final_giv_value (v, loop_start, loop_end) ...@@ -3330,7 +3330,7 @@ final_giv_value (v, loop_start, loop_end)
&& invariant_p (bl->initial_value)) && invariant_p (bl->initial_value))
{ {
/* Can calculate the loop exit value of its biv as /* Can calculate the loop exit value of its biv as
(loop_n_iterations * increment) + initial_value */ (n_iterations * increment) + initial_value */
/* The loop exit value of the giv is then /* The loop exit value of the giv is then
(final_biv_value - extra increments) * mult_val + add_val. (final_biv_value - extra increments) * mult_val + add_val.
...@@ -3344,7 +3344,7 @@ final_giv_value (v, loop_start, loop_end) ...@@ -3344,7 +3344,7 @@ final_giv_value (v, loop_start, loop_end)
/* Put the final biv value in tem. */ /* Put the final biv value in tem. */
tem = gen_reg_rtx (bl->biv->mode); tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0); record_base_value (REGNO (tem), bl->biv->add_val, 0);
emit_iv_add_mult (increment, GEN_INT (loop_n_iterations), emit_iv_add_mult (increment, GEN_INT (n_iterations),
bl->initial_value, tem, insert_before); bl->initial_value, tem, insert_before);
/* Subtract off extra increments as we find them. */ /* Subtract off extra increments as we find them. */
...@@ -3402,8 +3402,9 @@ final_giv_value (v, loop_start, loop_end) ...@@ -3402,8 +3402,9 @@ final_giv_value (v, loop_start, loop_end)
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_iterations (loop_start, loop_end, loop_info)
rtx loop_start, loop_end; rtx loop_start, loop_end;
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;
...@@ -3418,10 +3419,11 @@ loop_iterations (loop_start, loop_end) ...@@ -3418,10 +3419,11 @@ loop_iterations (loop_start, loop_end)
branch, and the insn before tests a register value, make that the branch, and the insn before tests a register value, make that the
iteration variable. */ iteration variable. */
loop_initial_value = 0; loop_info->initial_value = 0;
loop_increment = 0; loop_info->increment = 0;
loop_final_value = 0; loop_info->final_value = 0;
loop_iteration_var = 0; loop_info->iteration_var = 0;
loop_info->unroll_number = 2;
/* We used to use pren_nonnote_insn here, but that fails because it might /* We used to use pren_nonnote_insn here, but that fails because it might
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
...@@ -3508,11 +3510,11 @@ loop_iterations (loop_start, loop_end) ...@@ -3508,11 +3510,11 @@ loop_iterations (loop_start, loop_end)
recalculated inside precondition_loop_p because strength reduction recalculated inside precondition_loop_p because strength reduction
optimizations may obscure the loop's structure. */ optimizations may obscure the loop's structure. */
loop_iteration_var = iteration_var; loop_info->iteration_var = iteration_var;
loop_initial_value = initial_value; loop_info->initial_value = initial_value;
loop_increment = increment; loop_info->increment = increment;
loop_final_value = final_value; loop_info->final_value = final_value;
loop_comparison_code = comparison_code; loop_info->comparison_code = comparison_code;
if (increment == 0) if (increment == 0)
{ {
...@@ -3617,7 +3619,7 @@ loop_iterations (loop_start, loop_end) ...@@ -3617,7 +3619,7 @@ loop_iterations (loop_start, loop_end)
} }
/* Calculate the number of iterations, final_value is only an approximation, /* Calculate the number of iterations, final_value is only an approximation,
so correct for that. Note that tempu and loop_n_iterations are so correct for that. Note that tempu and loop_info->n_iterations are
unsigned, because they can be as large as 2^n - 1. */ unsigned, because they can be as large as 2^n - 1. */
i = INTVAL (increment); i = INTVAL (increment);
......
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