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:
parent
a70603680e
commit
302670f3f0
@ -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
|
||||
|
68
gcc/loop.c
68
gcc/loop.c
@ -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,
|
||||
|
59
gcc/loop.h
59
gcc/loop.h
@ -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 */
|
||||
|
||||
|
160
gcc/unroll.c
160
gcc/unroll.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user