/* Try to unroll loops, and split induction variables.
- Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000
+ Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx));
static int find_splittable_regs PARAMS ((const struct loop *,
- enum unroll_types, rtx, int));
+ enum unroll_types, int));
static int find_splittable_givs PARAMS ((const struct loop *,
struct iv_class *, enum unroll_types,
rtx, int));
/* Try to unroll one loop and split induction variables in the loop.
The loop is described by the arguments LOOP and INSN_COUNT.
- END_INSERT_BEFORE indicates where insns should be added which need
- to be executed when the loop falls through. STRENGTH_REDUCTION_P
- indicates whether information generated in the strength reduction
- pass is available.
+ STRENGTH_REDUCTION_P indicates whether information generated in the
+ strength reduction pass is available.
This function is intended to be called from within `strength_reduce'
in loop.c. */
void
-unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
+unroll_loop (loop, insn_count, strength_reduce_p)
struct loop *loop;
int insn_count;
- rtx end_insert_before;
int strength_reduce_p;
{
struct loop_info *loop_info = LOOP_INFO (loop);
}
}
}
- else if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)))
+ if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)))
set_label_in_map (map, CODE_LABEL_NUMBER (XEXP (note, 0)),
XEXP (note, 0));
}
these pseudo registers have valid regno_first_uid info. */
for (r = FIRST_PSEUDO_REGISTER; r < max_reg_before_loop; ++r)
if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) <= max_uid_for_loop
- && uid_luid[REGNO_FIRST_UID (r)] >= copy_start_luid
+ && REGNO_FIRST_LUID (r) >= copy_start_luid
&& REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) <= max_uid_for_loop
- && uid_luid[REGNO_LAST_UID (r)] <= copy_end_luid)
+ && REGNO_LAST_LUID (r) <= copy_end_luid)
{
/* However, we must also check for loop-carried dependencies.
If the value the pseudo has at the end of iteration X is
sequence = gen_sequence ();
end_sequence ();
- emit_insn_before (sequence, loop_start);
+ loop_insn_hoist (loop, sequence);
/* Only the last copy of the loop body here needs the exit
test, so set copy_end to exclude the compare/branch here,
if (splitting_not_safe)
temp = 0;
else
- temp = find_splittable_regs (loop, unroll_type,
- end_insert_before, unroll_number);
+ temp = find_splittable_regs (loop, unroll_type, unroll_number);
/* find_splittable_regs may have created some new registers, so must
reallocate the reg_map with the new larger size, and must realloc
/* Search the list of bivs and givs to find ones which need to be remapped
when split, and set their reg_map entry appropriately. */
- for (bl = ivs->loop_iv_list; bl; bl = bl->next)
+ for (bl = ivs->list; bl; bl = bl->next)
{
if (REGNO (bl->biv->src_reg) != bl->regno)
map->reg_map[bl->regno] = bl->biv->src_reg;
}
/* Use our current register alignment and pointer flags. */
- map->regno_pointer_flag = cfun->emit->regno_pointer_flag;
map->regno_pointer_align = cfun->emit->regno_pointer_align;
+ map->x_regno_reg_rtx = cfun->emit->x_regno_reg_rtx;
/* If the loop is being partially unrolled, and the iteration variables
are being split, and are being renamed for the split, then must fix up
return 1;
}
- if (loop_info->initial_value == 0)
+ if (loop_info->iteration_var == 0)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Preconditioning: Could not find iteration variable.\n");
+ return 0;
+ }
+ else if (loop_info->initial_value == 0)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
/* 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_info->iteration_var))]
+ if (REGNO_FIRST_LUID (REGNO (loop_info->iteration_var))
> INSN_LUID (loop_start))
{
if (loop_dump_stream)
unsigned int regno = REGNO (SET_DEST (set));
v = addr_combined_regs[REGNO (SET_DEST (set))];
- bl = ivs->reg_biv_class[REGNO (v->src_reg)];
+ bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
/* Although the giv_inc amount is not needed here, we must call
calculate_giv_inc here since it might try to delete the
for the biv was stored in the biv's first struct
induction entry by find_splittable_regs. */
- if (regno < max_reg_before_loop
+ if (regno < ivs->n_regs
&& REG_IV_TYPE (ivs, regno) == BASIC_INDUCT)
{
- giv_src_reg = ivs->reg_biv_class[regno]->biv->src_reg;
+ giv_src_reg = REG_IV_CLASS (ivs, regno)->biv->src_reg;
giv_dest_reg = giv_src_reg;
}
tem = gen_sequence ();
end_sequence ();
- emit_insn_before (tem, insert_before);
+ loop_insn_emit_before (loop, 0, insert_before, tem);
}
\f
/* Emit an insn, using the expand_binop to ensure that a valid insn is
rtx
biv_total_increment (bl)
- struct iv_class *bl;
+ const struct iv_class *bl;
{
struct induction *v;
rtx result;
times, since multiplies by small integers (1,2,3,4) are very cheap. */
static int
-find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
+find_splittable_regs (loop, unroll_type, unroll_number)
const struct loop *loop;
enum unroll_types unroll_type;
- rtx end_insert_before;
int unroll_number;
{
struct loop_ivs *ivs = LOOP_IVS (loop);
rtx biv_final_value;
int biv_splittable;
int result = 0;
- rtx loop_start = loop->start;
- rtx loop_end = loop->end;
- for (bl = ivs->loop_iv_list; bl; bl = bl->next)
+ for (bl = ivs->list; bl; bl = bl->next)
{
/* Biv_total_increment must return a constant value,
otherwise we can not calculate the split values. */
biv_final_value = 0;
if (unroll_type != UNROLL_COMPLETELY
&& (loop->exit_count || unroll_type == UNROLL_NAIVE)
- && (uid_luid[REGNO_LAST_UID (bl->regno)] >= INSN_LUID (loop_end)
+ && (REGNO_LAST_LUID (bl->regno) >= INSN_LUID (loop->end)
|| ! bl->init_insn
|| INSN_UID (bl->init_insn) >= max_uid_for_loop
- || (uid_luid[REGNO_FIRST_UID (bl->regno)]
+ || (REGNO_FIRST_LUID (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 (loop, bl)))
rtx tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
- loop_start);
+ loop_insn_hoist (loop,
+ gen_move_insn (tem, bl->biv->src_reg));
if (loop_dump_stream)
fprintf (loop_dump_stream,
how the loop exits. Otherwise emit the insn after the loop,
since this is slightly more efficient. */
if (! loop->exit_count)
- emit_insn_before (gen_move_insn (bl->biv->src_reg,
- biv_final_value),
- end_insert_before);
+ loop_insn_sink (loop, gen_move_insn (bl->biv->src_reg,
+ biv_final_value));
else
{
/* Create a new register to hold the value of the biv, and then
rtx tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
- loop_start);
- emit_insn_before (gen_move_insn (bl->biv->src_reg,
- biv_final_value),
- loop_start);
+ loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
+ loop_insn_hoist (loop, gen_move_insn (bl->biv->src_reg,
+ biv_final_value));
if (loop_dump_stream)
fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n",
|| (REGNO_FIRST_UID (REGNO (v->dest_reg))
!= INSN_UID (XEXP (tem, 0)))))
/* Line above always fails if INSN was moved by loop opt. */
- || (uid_luid[REGNO_LAST_UID (REGNO (v->dest_reg))]
+ || (REGNO_LAST_LUID (REGNO (v->dest_reg))
>= INSN_LUID (loop->end)))
&& ! (final_value = v->final_value))
continue;
to its final value before loop start to ensure that this insn
will always be executed, no matter how we exit. */
tem = gen_reg_rtx (v->mode);
- emit_insn_before (gen_move_insn (tem, v->dest_reg), loop_start);
- emit_insn_before (gen_move_insn (v->dest_reg, final_value),
- loop_start);
+ loop_insn_hoist (loop, gen_move_insn (tem, v->dest_reg));
+ loop_insn_hoist (loop, gen_move_insn (v->dest_reg, final_value));
if (loop_dump_stream)
fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
rtx tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
- loop->start);
+ loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
biv_initial_value = tem;
}
biv_initial_value = extend_value_for_giv (v, biv_initial_value);
{
rtx tem = gen_reg_rtx (v->mode);
record_base_value (REGNO (tem), v->add_val, 0);
- emit_iv_add_mult (bl->initial_value, v->mult_val,
- v->add_val, tem, loop->start);
+ loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
+ v->add_val, tem);
value = tem;
}
instruction on machines with complex addressing modes.
If we can't recognize it, then delete it and emit insns
to calculate the value from scratch. */
- emit_insn_before (gen_rtx_SET (VOIDmode, tem,
- copy_rtx (v->new_reg)),
- loop->start);
+ loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
+ copy_rtx (v->new_reg)));
if (recog_memoized (PREV_INSN (loop->start)) < 0)
{
rtx sequence, ret;
/* We can't use bl->initial_value to compute the initial
value, because the loop may have been preconditioned.
- We must calculate it from NEW_REG. Try using
- force_operand instead of emit_iv_add_mult. */
+ We must calculate it from NEW_REG. */
delete_insn (PREV_INSN (loop->start));
start_sequence ();
emit_move_insn (tem, ret);
sequence = gen_sequence ();
end_sequence ();
- emit_insn_before (sequence, loop->start);
+ loop_insn_hoist (loop, sequence);
if (loop_dump_stream)
fprintf (loop_dump_stream,
{
int count = 1;
if (! v->ignore)
- count = ivs->reg_biv_class[REGNO (v->src_reg)]->biv_count;
+ count = REG_IV_CLASS (ivs, REGNO (v->src_reg))->biv_count;
splittable_regs_updates[REGNO (v->new_reg)] = count;
}
const struct loop *loop;
struct iv_class *bl;
{
- rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
rtx increment, tem;
tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- /* 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 (n_iterations),
- bl->initial_value, tem, NEXT_INSN (loop_end));
+ loop_iv_add_mult_sink (loop, increment, GEN_INT (n_iterations),
+ bl->initial_value, tem);
if (loop_dump_stream)
fprintf (loop_dump_stream,
struct iv_class *bl;
rtx insn;
rtx increment, tem;
- rtx insert_before, seq;
+ rtx seq;
rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
- bl = ivs->reg_biv_class[REGNO (v->src_reg)];
+ bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
/* The final value for givs which depend on reversed bivs must be calculated
differently than for ordinary givs. In this case, there is already an
We must search from the insn that sets the giv to the end
of the loop to calculate this value. */
- insert_before = NEXT_INSN (loop_end);
-
/* Put the final biv value in tem. */
tem = gen_reg_rtx (v->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- emit_iv_add_mult (extend_value_for_giv (v, increment),
- GEN_INT (n_iterations),
- extend_value_for_giv (v, bl->initial_value),
- tem, insert_before);
+ loop_iv_add_mult_sink (loop, extend_value_for_giv (v, increment),
+ GEN_INT (n_iterations),
+ extend_value_for_giv (v, bl->initial_value),
+ tem);
/* Subtract off extra increments as we find them. */
for (insn = NEXT_INSN (v->insn); insn != loop_end;
OPTAB_LIB_WIDEN);
seq = gen_sequence ();
end_sequence ();
- emit_insn_before (seq, insert_before);
+ loop_insn_sink (loop, seq);
}
}
/* Now calculate the giv's final value. */
- emit_iv_add_mult (tem, v->mult_val, v->add_val, tem, insert_before);
+ loop_iv_add_mult_sink (loop, tem, v->mult_val, v->add_val, tem);
if (loop_dump_stream)
fprintf (loop_dump_stream,
will propagate a new pseudo into the old iteration register but
this will be marked by having the REG_USERVAR_P bit set. */
- if ((unsigned) REGNO (iteration_var) >= ivs->reg_iv_type->num_elements
+ if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
&& ! REG_USERVAR_P (iteration_var))
abort ();
/* 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) >= ivs->reg_iv_type->num_elements)
+ if ((unsigned) REGNO (iteration_var) >= ivs->n_regs)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
}
else if (REG_IV_TYPE (ivs, 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)
+ if (REGNO (iteration_var) >= ivs->n_regs)
abort ();
/* Grab initial value, only useful if it is a constant. */
- bl = ivs->reg_biv_class[REGNO (iteration_var)];
+ bl = REG_IV_CLASS (ivs, REGNO (iteration_var));
initial_value = bl->initial_value;
+ if (!bl->biv->always_executed || bl->biv->maybe_multiple)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Loop iterations: Basic induction var not set once in each iteration.\n");
+ return 0;
+ }
increment = biv_total_increment (bl);
}
struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
rtx biv_initial_value;
- if (REGNO (v->src_reg) >= max_reg_before_loop)
+ if (REGNO (v->src_reg) >= ivs->n_regs)
abort ();
- bl = ivs->reg_biv_class[REGNO (v->src_reg)];
+ if (!v->always_executed || v->maybe_multiple)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Loop iterations: General induction var not set once in each iteration.\n");
+ return 0;
+ }
+
+ bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
/* Increment value is mult_val times the increment value of the biv. */
{
fprintf (loop_dump_stream,
"Loop iterations: Increment value not constant ");
- print_rtl (loop_dump_stream, increment);
+ print_simple_rtl (loop_dump_stream, increment);
fprintf (loop_dump_stream, ".\n");
}
return 0;
{
fprintf (loop_dump_stream,
"Loop iterations: Initial value not constant ");
- print_rtl (loop_dump_stream, initial_value);
+ print_simple_rtl (loop_dump_stream, initial_value);
fprintf (loop_dump_stream, ".\n");
}
return 0;
{
fprintf (loop_dump_stream,
"Loop iterations: Final value not constant ");
- print_rtl (loop_dump_stream, final_value);
+ print_simple_rtl (loop_dump_stream, final_value);
fprintf (loop_dump_stream, ".\n");
}
return 0;
/* If non-reduced/final-value givs were split, then this would also
have to remap those givs also. */
#endif
- if (REGNO (x) < max_reg_before_loop
+ if (REGNO (x) < ivs->n_regs
&& REG_IV_TYPE (ivs, REGNO (x)) == BASIC_INDUCT)
- return ivs->reg_biv_class[REGNO (x)]->biv->src_reg;
+ return REG_IV_CLASS (ivs, REGNO (x))->biv->src_reg;
break;
default: