unroll.c (iteration_info): Subsume into loop_iterations.

* unroll.c (iteration_info): Subsume into loop_iterations.
	* loop.h (loop_info): New field iv.

From-SVN: r36334
This commit is contained in:
Michael Hayes 2000-09-11 21:44:21 +00:00 committed by Michael Hayes
parent 5d6a16e27e
commit 0a5b41f256
3 changed files with 122 additions and 125 deletions

View File

@ -1,3 +1,8 @@
2000-09-12 Michael Hayes <mhayes@cygnus.com>
* unroll.c (iteration_info): Subsume into loop_iterations.
* loop.h (loop_info): New field iv.
2000-09-12 Michael Hayes <mhayes@cygnus.com> 2000-09-12 Michael Hayes <mhayes@cygnus.com>
* basic-block.h (LOOP_TREE, LOOP_PRE_HEADER, LOOP_EDGES): New. * basic-block.h (LOOP_TREE, LOOP_PRE_HEADER, LOOP_EDGES): New.

View File

@ -216,6 +216,8 @@ struct loop_info
/* The number of times the loop body was unrolled. */ /* The number of times the loop body was unrolled. */
unsigned int unroll_number; unsigned int unroll_number;
int used_count_register; int used_count_register;
/* The loop iterator induction variable. */
struct iv_class *iv;
/* List of MEMs that are stored in this loop. */ /* List of MEMs that are stored in this loop. */
rtx store_mems; rtx store_mems;
/* Array of MEMs that are used (read or written) in this loop, but /* Array of MEMs that are used (read or written) in this loop, but

View File

@ -203,7 +203,6 @@ static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *)); static void final_reg_note_copy PARAMS ((rtx, struct inline_remap *));
static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int, static void copy_loop_body PARAMS ((rtx, rtx, struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx)); enum unroll_types, rtx, rtx, rtx, rtx));
static void iteration_info PARAMS ((const struct loop *, rtx, rtx *, rtx *));
static int find_splittable_regs PARAMS ((const struct loop *, static int find_splittable_regs PARAMS ((const struct loop *,
enum unroll_types, rtx, int)); enum unroll_types, rtx, int));
static int find_splittable_givs PARAMS ((const struct loop *, static int find_splittable_givs PARAMS ((const struct loop *,
@ -1477,7 +1476,7 @@ precondition_loop_p (loop, initial_value, final_value, increment, mode)
return 0; return 0;
} }
/* Note that iteration_info biases the initial value for GIV iterators /* Note that loop_iterations biases the initial value for GIV iterators
such as "while (i-- > 0)" so that we can calculate the number of such as "while (i-- > 0)" so that we can calculate the number of
iterations just like for BIV iterators. iterations just like for BIV iterators.
@ -2427,125 +2426,6 @@ biv_total_increment (bl)
return result; return result;
} }
/* Determine the initial value of the iteration variable, and the amount
that it is incremented each loop. Use the tables constructed by
the strength reduction pass to calculate these values.
Initial_value and/or increment are set to zero if their values could not
be calculated. */
static void
iteration_info (loop, iteration_var, initial_value, increment)
const struct loop *loop ATTRIBUTE_UNUSED;
rtx iteration_var, *initial_value, *increment;
{
struct iv_class *bl;
/* Clear the result values, in case no answer can be found. */
*initial_value = 0;
*increment = 0;
/* The iteration variable can be either a giv or a biv. Check to see
which it is, and compute the variable's initial value, and increment
value if possible. */
/* If this is a new register, can't handle it since we don't have any
reg_iv_type entry for it. */
if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: No reg_iv_type entry for iteration var.\n");
return;
}
/* 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_info->n_iterations. */
else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
> HOST_BITS_PER_WIDE_INT))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Iteration var rejected because mode too large.\n");
return;
}
else if (GET_MODE_CLASS (GET_MODE (iteration_var)) != MODE_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Iteration var not an integer.\n");
return;
}
else if (REG_IV_TYPE (REGNO (iteration_var)) == BASIC_INDUCT)
{
/* When reg_iv_type / reg_iv_info is resized for biv increments
that are turned into givs, reg_biv_class is not resized.
So check here that we don't make an out-of-bounds access. */
if (REGNO (iteration_var) >= max_reg_before_loop)
abort ();
/* Grab initial value, only useful if it is a constant. */
bl = reg_biv_class[REGNO (iteration_var)];
*initial_value = bl->initial_value;
*increment = biv_total_increment (bl);
}
else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT)
{
HOST_WIDE_INT offset = 0;
struct induction *v = REG_IV_INFO (REGNO (iteration_var));
rtx biv_initial_value;
if (REGNO (v->src_reg) >= max_reg_before_loop)
abort ();
bl = reg_biv_class[REGNO (v->src_reg)];
/* Increment value is mult_val times the increment value of the biv. */
*increment = biv_total_increment (bl);
if (*increment)
{
struct induction *biv_inc;
*increment
= fold_rtx_mult_add (v->mult_val, *increment, const0_rtx, v->mode);
/* The caller assumes that one full increment has occured at the
first loop test. But that's not true when the biv is incremented
after the giv is set (which is the usual case), e.g.:
i = 6; do {;} while (i++ < 9) .
Therefore, we bias the initial value by subtracting the amount of
the increment that occurs between the giv set and the giv test. */
for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
{
if (loop_insn_first_p (v->insn, biv_inc->insn))
offset -= INTVAL (biv_inc->add_val);
}
offset *= INTVAL (v->mult_val);
}
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Giv iterator, initial value bias %ld.\n",
(long) offset);
/* Initial value is mult_val times the biv's initial value plus
add_val. Only useful if it is a constant. */
biv_initial_value = extend_value_for_giv (v, bl->initial_value);
*initial_value
= fold_rtx_mult_add (v->mult_val,
plus_constant (biv_initial_value, offset),
v->add_val, v->mode);
}
else
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop unrolling: Not basic or general induction var.\n");
return;
}
}
/* 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
a different variable for each unrolled copy of the loop body. If it a different variable for each unrolled copy of the loop body. If it
@ -3631,8 +3511,10 @@ find_common_reg_term (op0, op1)
return NULL_RTX; return NULL_RTX;
} }
/* Calculate the number of loop iterations. Returns the exact number of loop
iterations if it can be calculated, otherwise returns zero. */ /* Determine the loop iterator and calculate the number of loop
iterations. Returns the exact number of loop iterations if it can
be calculated, otherwise returns zero. */
unsigned HOST_WIDE_INT unsigned HOST_WIDE_INT
loop_iterations (loop) loop_iterations (loop)
@ -3649,6 +3531,7 @@ loop_iterations (loop)
rtx last_loop_insn; rtx last_loop_insn;
rtx reg_term; rtx reg_term;
struct loop_info *loop_info = LOOP_INFO (loop); struct loop_info *loop_info = LOOP_INFO (loop);
struct iv_class *bl;
loop_info->n_iterations = 0; loop_info->n_iterations = 0;
loop_info->initial_value = 0; loop_info->initial_value = 0;
@ -3659,6 +3542,7 @@ loop_iterations (loop)
loop_info->increment = 0; loop_info->increment = 0;
loop_info->iteration_var = 0; loop_info->iteration_var = 0;
loop_info->unroll_number = 1; loop_info->unroll_number = 1;
loop_info->iv = 0;
/* We used to use prev_nonnote_insn here, but that fails because it might /* We used to use prev_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
@ -3725,10 +3609,115 @@ loop_iterations (loop)
&& ! REG_USERVAR_P (iteration_var)) && ! REG_USERVAR_P (iteration_var))
abort (); abort ();
iteration_info (loop, iteration_var, &initial_value, &increment); /* Determine the initial value of the iteration variable, and the amount
that it is incremented each loop. Use the tables constructed by
the strength reduction pass to calculate these values. */
/* Clear the result values, in case no answer can be found. */
initial_value = 0;
increment = 0;
/* The iteration variable can be either a giv or a biv. Check to see
which it is, and compute the variable's initial value, and increment
value if possible. */
/* If this is a new register, can't handle it since we don't have any
reg_iv_type entry for it. */
if ((unsigned) REGNO (iteration_var) >= reg_iv_type->num_elements)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop iterations: No reg_iv_type entry for iteration var.\n");
return 0;
}
/* 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_info->n_iterations. */
else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
> HOST_BITS_PER_WIDE_INT))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop iterations: Iteration var rejected because mode too large.\n");
return 0;
}
else if (GET_MODE_CLASS (GET_MODE (iteration_var)) != MODE_INT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop iterations: Iteration var not an integer.\n");
return 0;
}
else if (REG_IV_TYPE (REGNO (iteration_var)) == BASIC_INDUCT)
{
/* When reg_iv_type / reg_iv_info is resized for biv increments
that are turned into givs, reg_biv_class is not resized.
So check here that we don't make an out-of-bounds access. */
if (REGNO (iteration_var) >= max_reg_before_loop)
abort ();
/* Grab initial value, only useful if it is a constant. */
bl = reg_biv_class[REGNO (iteration_var)];
initial_value = bl->initial_value;
increment = biv_total_increment (bl);
}
else if (REG_IV_TYPE (REGNO (iteration_var)) == GENERAL_INDUCT)
{
HOST_WIDE_INT offset = 0;
struct induction *v = REG_IV_INFO (REGNO (iteration_var));
rtx biv_initial_value;
if (REGNO (v->src_reg) >= max_reg_before_loop)
abort ();
bl = reg_biv_class[REGNO (v->src_reg)];
/* Increment value is mult_val times the increment value of the biv. */
increment = biv_total_increment (bl);
if (increment)
{
struct induction *biv_inc;
increment
= fold_rtx_mult_add (v->mult_val, increment, const0_rtx, v->mode);
/* The caller assumes that one full increment has occured at the
first loop test. But that's not true when the biv is incremented
after the giv is set (which is the usual case), e.g.:
i = 6; do {;} while (i++ < 9) .
Therefore, we bias the initial value by subtracting the amount of
the increment that occurs between the giv set and the giv test. */
for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
{
if (loop_insn_first_p (v->insn, biv_inc->insn))
offset -= INTVAL (biv_inc->add_val);
}
offset *= INTVAL (v->mult_val);
}
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop iterations: Giv iterator, initial value bias %ld.\n",
(long) offset);
/* Initial value is mult_val times the biv's initial value plus
add_val. Only useful if it is a constant. */
biv_initial_value = extend_value_for_giv (v, bl->initial_value);
initial_value
= fold_rtx_mult_add (v->mult_val,
plus_constant (biv_initial_value, offset),
v->add_val, v->mode);
}
else
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
"Loop iterations: Not basic or general induction var.\n");
return 0;
}
if (initial_value == 0) if (initial_value == 0)
/* iteration_info already printed a message. */
return 0; return 0;
unsigned_p = 0; unsigned_p = 0;
@ -3809,6 +3798,7 @@ loop_iterations (loop)
loop_info->increment = increment; loop_info->increment = increment;
loop_info->iteration_var = iteration_var; loop_info->iteration_var = iteration_var;
loop_info->comparison_code = comparison_code; loop_info->comparison_code = comparison_code;
loop_info->iv = bl;
/* Try to determine the iteration count for loops such /* Try to determine the iteration count for loops such
as (for i = init; i < init + const; i++). When running the as (for i = init; i < init + const; i++). When running the