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
This commit is contained in:
Michael Hayes 1998-11-25 21:19:21 +00:00 committed by Michael Hayes
parent a70603680e
commit 302670f3f0
4 changed files with 183 additions and 133 deletions

View File

@ -1,3 +1,32 @@
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>
* loop.c (check_dbra_loop): Update JUMP_LABEL field of jump insn

View File

@ -88,14 +88,6 @@ int *loop_outer_loop;
int *loop_used_count_register;
#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
really a loop (an insn outside the loop branches into it). */
@ -118,14 +110,6 @@ rtx *loop_number_exit_labels;
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. */
static int loop_has_call;
@ -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 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 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 update_giv_derive PROTO((rtx));
static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *));
@ -365,7 +350,7 @@ typedef struct rtx_pair {
#ifdef HAVE_decrement_and_branch_on_count
/* 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. */
static void instrument_loop_bct PROTO((rtx, rtx, rtx));
@ -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_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
/* Allocate for BCT optimization */
loop_used_count_register = (int *) alloca (max_loop_num * sizeof (int));
@ -3573,6 +3552,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
rtx test;
rtx end_insert_before;
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
* sizeof (enum iv_mode));
@ -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
strength reduction info available. */
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;
}
@ -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
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
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,
for (v = bl->giv; v; v = v->next_iv)
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
@ -4099,7 +4081,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& ! bl->nonneg
#endif
&& ! 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
&& ! bl->nonneg
#endif
@ -4562,13 +4545,14 @@ strength_reduce (scan_start, end, loop_top, insn_count,
collected. */
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
/* Instrument the loop with BCT insn. */
if (HAVE_decrement_and_branch_on_count && bct_p
&& 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 */
if (loop_dump_stream)
@ -5058,9 +5042,10 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
have been identified. */
static void
check_final_value (v, loop_start, loop_end)
check_final_value (v, loop_start, loop_end, n_iterations)
struct induction *v;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
rtx final_value = 0;
@ -5087,7 +5072,7 @@ check_final_value (v, loop_start, loop_end)
v->replaceable = 0;
#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)))
{
int biv_increment_seen = 0;
@ -7965,8 +7950,9 @@ get_condition_for_loop (x)
*/
static void
insert_bct (loop_start, loop_end)
insert_bct (loop_start, loop_end, loop_info)
rtx loop_start, loop_end;
struct loop_info *loop_info;
{
int i;
unsigned HOST_WIDE_INT n_iterations;
@ -7982,7 +7968,7 @@ insert_bct (loop_start, loop_end)
int loop_num = uid_loop_num [INSN_UID (loop_start)];
/* It's impossible to instrument a competely unrolled loop. */
if (loop_unroll_factor [loop_num] == -1)
if (loop_info->unroll_number == -1)
return;
/* Make sure that the count register is not in use. */
@ -8040,10 +8026,10 @@ insert_bct (loop_start, loop_end)
}
/* Account for loop unrolling in instrumented iteration count. */
if (loop_unroll_factor [loop_num] > 1)
n_iterations = loop_n_iterations / loop_unroll_factor [loop_num];
if (loop_info->unroll_number > 1)
n_iterations = loop_info->n_iterations / loop_info->unroll_number;
else
n_iterations = loop_n_iterations;
n_iterations = loop_info->n_iterations;
if (n_iterations != 0 && n_iterations < 3)
{
@ -8071,7 +8057,7 @@ insert_bct (loop_start, loop_end)
at compile time. In this case we generate run_time calculation
of the number of iterations. */
if (loop_iteration_var == 0)
if (loop_info->iteration_var == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -8080,8 +8066,8 @@ insert_bct (loop_start, loop_end)
return;
}
if (GET_MODE_CLASS (GET_MODE (loop_iteration_var)) != MODE_INT
|| GET_MODE_SIZE (GET_MODE (loop_iteration_var)) != UNITS_PER_WORD)
if (GET_MODE_CLASS (GET_MODE (loop_info->iteration_var)) != MODE_INT
|| GET_MODE_SIZE (GET_MODE (loop_info->iteration_var)) != UNITS_PER_WORD)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -8091,7 +8077,7 @@ insert_bct (loop_start, loop_end)
}
/* 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)
fprintf (loop_dump_stream,

View File

@ -143,6 +143,43 @@ struct iv_class {
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. */
enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT,
GENERAL_INDUCT };
@ -155,7 +192,6 @@ extern int *uid_loop_num;
extern int *loop_outer_loop;
extern rtx *loop_number_exit_labels;
extern int *loop_number_exit_count;
extern unsigned HOST_WIDE_INT loop_n_iterations;
extern int max_reg_before_loop;
extern FILE *loop_dump_stream;
@ -175,21 +211,18 @@ void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
void find_loop_tree_blocks 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));
unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx));
rtx final_biv_value PROTO((struct iv_class *, rtx, rtx));
rtx final_giv_value PROTO((struct induction *, rtx, rtx));
unsigned HOST_WIDE_INT loop_iterations PROTO((rtx, rtx, struct loop_info *));
int precondition_loop_p PROTO((rtx, struct loop_info *,
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));
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 */

View File

@ -186,19 +186,9 @@ static rtx *splittable_regs;
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. */
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 initial_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,
enum unroll_types, 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 int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int));
static int find_splittable_givs PROTO((struct iv_class *,enum unroll_types,
static int find_splittable_regs PROTO((enum unroll_types, rtx, rtx, rtx, int,
unsigned HOST_WIDE_INT));
static int find_splittable_givs PROTO((struct iv_class *, enum unroll_types,
rtx, rtx, rtx, int));
static int reg_dead_after_loop PROTO((rtx, rtx, rtx));
static rtx fold_rtx_mult_add PROTO((rtx, rtx, rtx, enum machine_mode));
@ -227,11 +218,12 @@ static rtx remap_split_bivs PROTO((rtx));
void
unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
strength_reduce_p)
loop_info, strength_reduce_p)
rtx loop_end;
int insn_count;
rtx loop_start;
rtx end_insert_before;
struct loop_info *loop_info;
int strength_reduce_p;
{
int i, j, temp;
@ -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
and the size of the loop. */
/* If there is no strength reduce info, then set loop_n_iterations to zero.
This can happen if strength_reduce can't find any bivs in the loop.
A value of zero indicates that the number of iterations could not be
calculated. */
/* If there is no strength reduce info, then set
loop_info->n_iterations to zero. This can happen if
strength_reduce can't find any bivs in the loop. A value of zero
indicates that the number of iterations could not be calculated. */
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);
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);
}
@ -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
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
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,
}
return;
}
else if (loop_n_iterations > 0
&& loop_n_iterations * insn_count < MAX_UNROLLED_INSNS)
else if (loop_info->n_iterations > 0
&& loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
{
unroll_number = loop_n_iterations;
unroll_number = loop_info->n_iterations;
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
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,
for (i = 0; i < NUM_FACTORS; i++)
factors[i].count = 0;
temp = loop_n_iterations;
temp = loop_info->n_iterations;
for (i = NUM_FACTORS - 1; i >= 0; i--)
while (temp % factors[i].factor == 0)
{
@ -857,8 +850,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
{
rtx initial_value, final_value, increment;
if (precondition_loop_p (&initial_value, &final_value, &increment,
loop_start))
if (precondition_loop_p (loop_start, loop_info,
&initial_value, &final_value, &increment))
{
register rtx diff ;
enum machine_mode mode;
@ -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
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,
NULL_RTX, mode, 0, 0);
@ -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. */
/* Keep track of the unroll factor for each loop. */
/* Keep track of the unroll factor for the loop. */
if (unroll_type == UNROLL_COMPLETELY)
loop_unroll_factor [uid_loop_num [INSN_UID (loop_start)]] = -1;
loop_info->unroll_number = -1;
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
@ -1160,7 +1153,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
temp = 0;
else
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
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,
when the increment is not a power of 2. Use RTX_COST to compute
whether divide is cheap. */
static int
precondition_loop_p (initial_value, final_value, increment, loop_start)
rtx *initial_value, *final_value, *increment;
int
precondition_loop_p (loop_start, loop_info,
initial_value, final_value, increment)
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;
*increment = const1_rtx;
*final_value = GEN_INT (loop_n_iterations);
*final_value = GEN_INT (loop_info->n_iterations);
if (loop_dump_stream)
{
fputs ("Preconditioning: Success, number of iterations known, ",
loop_dump_stream);
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
loop_n_iterations);
loop_info->n_iterations);
fputs (".\n", loop_dump_stream);
}
return 1;
}
if (loop_initial_value == 0)
if (loop_info->initial_value == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Could not find initial value.\n");
return 0;
}
else if (loop_increment == 0)
else if (loop_info->increment == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Could not find increment value.\n");
return 0;
}
else if (GET_CODE (loop_increment) != CONST_INT)
else if (GET_CODE (loop_info->increment) != CONST_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Preconditioning: Increment not a constant.\n");
return 0;
}
else if ((exact_log2 (INTVAL (loop_increment)) < 0)
&& (exact_log2 (- INTVAL (loop_increment)) < 0))
else if ((exact_log2 (INTVAL (loop_info->increment)) < 0)
&& (exact_log2 (- INTVAL (loop_info->increment)) < 0))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -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
not matter for preconditioning. */
if (loop_final_value == 0)
if (loop_info->final_value == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -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.
If it isn't, then it is most likely a biv/giv which by definition are
not invariant. */
if ((GET_CODE (loop_final_value) == REG
&& REGNO (loop_final_value) >= max_reg_before_loop)
|| (GET_CODE (loop_final_value) == PLUS
&& REGNO (XEXP (loop_final_value, 0)) >= max_reg_before_loop)
|| ! invariant_p (loop_final_value))
if ((GET_CODE (loop_info->final_value) == REG
&& REGNO (loop_info->final_value) >= max_reg_before_loop)
|| (GET_CODE (loop_info->final_value) == PLUS
&& REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
|| ! invariant_p (loop_info->final_value))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -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
does not have code to deal with them. */
if (GET_MODE_CLASS (GET_MODE (loop_final_value)) == MODE_FLOAT
|| GET_MODE_CLASS (GET_MODE (loop_initial_value)) == MODE_FLOAT)
if (GET_MODE_CLASS (GET_MODE (loop_info->final_value)) == MODE_FLOAT
|| GET_MODE_CLASS (GET_MODE (loop_info->initial_value)) == MODE_FLOAT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
@ -1410,10 +1406,10 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
return 0;
}
/* Fail if loop_iteration_var is not live before loop_start, since we need
to test its value in the preconditioning code. */
/* Fail if loop_info->iteration_var is not live before loop_start,
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))
{
if (loop_dump_stream)
@ -1430,9 +1426,9 @@ precondition_loop_p (initial_value, final_value, increment, loop_start)
Also note that the absolute values of initial_value and
final_value are unimportant as only their difference is used for
calculating the number of loop iterations. */
*initial_value = loop_initial_value;
*increment = loop_increment;
*final_value = loop_final_value;
*initial_value = loop_info->initial_value;
*increment = loop_info->increment;
*final_value = loop_info->final_value;
/* Success! */
if (loop_dump_stream)
@ -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
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))
> HOST_BITS_PER_WIDE_INT))
{
@ -2506,11 +2502,12 @@ approx_final_value (comparison_code, comparison_value, unsigned_p, compare_dir)
static int
find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
unroll_number)
unroll_number, n_iterations)
enum unroll_types unroll_type;
rtx loop_start, loop_end;
rtx end_insert_before;
int unroll_number;
unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
struct induction *v;
@ -2548,7 +2545,8 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
|| (uid_luid[REGNO_FIRST_UID (bl->regno)]
< INSN_LUID (bl->init_insn))
|| 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;
/* 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)
the end of the loop. If we can do it, return that value. */
rtx
final_biv_value (bl, loop_start, loop_end)
final_biv_value (bl, loop_start, loop_end, n_iterations)
struct iv_class *bl;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{
rtx increment, tem;
@ -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
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)]]
&& invariant_p (bl->initial_value))
{
@ -3248,7 +3247,7 @@ final_biv_value (bl, loop_start, loop_end)
/* Make sure loop_end is not the last insn. */
if (NEXT_INSN (loop_end) == 0)
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));
if (loop_dump_stream)
@ -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. */
rtx
final_giv_value (v, loop_start, loop_end)
final_giv_value (v, loop_start, loop_end, n_iterations)
struct induction *v;
rtx loop_start, loop_end;
unsigned HOST_WIDE_INT n_iterations;
{
struct iv_class *bl;
rtx insn;
@ -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
to be known. */
if (loop_n_iterations != 0
if (n_iterations != 0
&& ! 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
@ -3330,7 +3330,7 @@ final_giv_value (v, loop_start, loop_end)
&& invariant_p (bl->initial_value))
{
/* 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
(final_biv_value - extra increments) * mult_val + add_val.
@ -3344,7 +3344,7 @@ final_giv_value (v, loop_start, loop_end)
/* Put the final biv value in tem. */
tem = gen_reg_rtx (bl->biv->mode);
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);
/* Subtract off extra increments as we find them. */
@ -3402,8 +3402,9 @@ final_giv_value (v, loop_start, loop_end)
iterations if it can be calculated, otherwise returns zero. */
unsigned HOST_WIDE_INT
loop_iterations (loop_start, loop_end)
loop_iterations (loop_start, loop_end, loop_info)
rtx loop_start, loop_end;
struct loop_info *loop_info;
{
rtx comparison, comparison_value;
rtx iteration_var, initial_value, increment, final_value;
@ -3418,10 +3419,11 @@ loop_iterations (loop_start, loop_end)
branch, and the insn before tests a register value, make that the
iteration variable. */
loop_initial_value = 0;
loop_increment = 0;
loop_final_value = 0;
loop_iteration_var = 0;
loop_info->initial_value = 0;
loop_info->increment = 0;
loop_info->final_value = 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
accidentally get the branch for a contained loop if the branch for this
@ -3508,11 +3510,11 @@ loop_iterations (loop_start, loop_end)
recalculated inside precondition_loop_p because strength reduction
optimizations may obscure the loop's structure. */
loop_iteration_var = iteration_var;
loop_initial_value = initial_value;
loop_increment = increment;
loop_final_value = final_value;
loop_comparison_code = comparison_code;
loop_info->iteration_var = iteration_var;
loop_info->initial_value = initial_value;
loop_info->increment = increment;
loop_info->final_value = final_value;
loop_info->comparison_code = comparison_code;
if (increment == 0)
{
@ -3617,7 +3619,7 @@ loop_iterations (loop_start, loop_end)
}
/* 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. */
i = INTVAL (increment);