Commit 96a45535 by Michael Hayes Committed by Michael Hayes

hard-reg-set.h: Add multiple include guard.

	* hard-reg-set.h: Add multiple include guard.
	* basic-block.h (struct loop): Add `sink' field.
	* loop.h: Include sbitmap.h, hard-reg-set.h, and basic-block.h.
	(emit_iv_add_mult): Delete.
	(loop_iv_add_mult_hoist, loop_iv_add_mult_sink): Define.
	(loop_iv_add_mult_emit_before, loop_insn_sink): Define.
	(unroll_loop): Remove end_insert_before argument.
	* loop.c (loop_givs_rescan): Remove end_insert_before argument.
	(maybe_eliminate_biv_1): Likewise.
	(emit_iv_add_mult): Delete.
	(gen_add_mult, loop_regs_update): New.
	(loop_insn_emit_after, loop_insn_emit_before): New.
	(loop_insn_sink, loop_insn_sink_or_swim): New.
	(emit_iv_add_mult): Delete.
	(scan_loop): Set loop->sink.
	(loop_givs_reduce): Use loop_insn_sink and its ilk.
	(loop_givs_rescan, strength_reduce, check_dbra_loop): Likewise.
	(maybe_eliminate_biv_1): Likewise.
	(maybe_eliminate_biv_1): Add basic block argument.
	* unroll.c (unroll_loop): Remove end_insert_before argument.
	(find_splittable_regs): Likewise.
	(find_splittable_regs): Use loop_insn_sink and its ilk.
	(find_splittable_givs, final_biv_value, final_giv_value): Likewise.

From-SVN: r38766
parent 804a718a
2001-01-07 Michael Hayes <mhayes@redhat.com> 2001-01-07 Michael Hayes <mhayes@redhat.com>
* hard-reg-set.h: Add multiple include guard.
* basic-block.h (struct loop): Add `sink' field.
* loop.h: Include sbitmap.h, hard-reg-set.h, and basic-block.h.
(emit_iv_add_mult): Delete.
(loop_iv_add_mult_hoist, loop_iv_add_mult_sink): Define.
(loop_iv_add_mult_emit_before, loop_insn_sink): Define.
(unroll_loop): Remove end_insert_before argument.
* loop.c (loop_givs_rescan): Remove end_insert_before argument.
(maybe_eliminate_biv_1): Likewise.
(emit_iv_add_mult): Delete.
(gen_add_mult, loop_regs_update): New.
(loop_insn_emit_after, loop_insn_emit_before): New.
(loop_insn_sink, loop_insn_sink_or_swim): New.
(emit_iv_add_mult): Delete.
(scan_loop): Set loop->sink.
(loop_givs_reduce): Use loop_insn_sink and its ilk.
(loop_givs_rescan, strength_reduce, check_dbra_loop): Likewise.
(maybe_eliminate_biv_1): Likewise.
(maybe_eliminate_biv_1): Add basic block argument.
* unroll.c (unroll_loop): Remove end_insert_before argument.
(find_splittable_regs): Likewise.
(find_splittable_regs): Use loop_insn_sink and its ilk.
(find_splittable_givs, final_biv_value, final_giv_value): Likewise.
2001-01-07 Michael Hayes <mhayes@redhat.com>
* loop.h (loop_insn_hoist): New prototype. * loop.h (loop_insn_hoist): New prototype.
* loop.c (loop_insn_hoist, loop_insn_emit_before): New. * loop.c (loop_insn_hoist, loop_insn_emit_before): New.
(move_movables, loop_givs_rescan): Use loop_insn_hoist. (move_movables, loop_givs_rescan): Use loop_insn_hoist.
......
...@@ -365,6 +365,9 @@ struct loop ...@@ -365,6 +365,9 @@ struct loop
/* Place in the loop where control enters. */ /* Place in the loop where control enters. */
rtx scan_start; rtx scan_start;
/* The position where to sink insns out of the loop. */
rtx sink;
/* List of all LABEL_REFs which refer to code labels outside the /* List of all LABEL_REFs which refer to code labels outside the
loop. Used by routines that need to know all loop exits, such as loop. Used by routines that need to know all loop exits, such as
final_biv_value and final_giv_value. final_biv_value and final_giv_value.
......
...@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to ...@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#ifndef _HARD_REG_SET_H
#define _HARD_REG_SET_H 1
/* Define the type of a set of hard registers. */ /* Define the type of a set of hard registers. */
...@@ -472,3 +474,5 @@ extern int n_non_fixed_regs; ...@@ -472,3 +474,5 @@ extern int n_non_fixed_regs;
/* Vector indexed by hardware reg giving its name. */ /* Vector indexed by hardware reg giving its name. */
extern const char * reg_names[FIRST_PSEUDO_REGISTER]; extern const char * reg_names[FIRST_PSEUDO_REGISTER];
#endif /* _HARD_REG_SET_H */
...@@ -188,7 +188,7 @@ static int loop_giv_reduce_benefit PARAMS((struct loop *, struct iv_class *, ...@@ -188,7 +188,7 @@ static int loop_giv_reduce_benefit PARAMS((struct loop *, struct iv_class *,
static void loop_givs_dead_check PARAMS((struct loop *, struct iv_class *)); static void loop_givs_dead_check PARAMS((struct loop *, struct iv_class *));
static void loop_givs_reduce PARAMS((struct loop *, struct iv_class *)); static void loop_givs_reduce PARAMS((struct loop *, struct iv_class *));
static void loop_givs_rescan PARAMS((struct loop *, struct iv_class *, static void loop_givs_rescan PARAMS((struct loop *, struct iv_class *,
rtx *, rtx)); rtx *));
static void loop_ivs_free PARAMS((struct loop *)); static void loop_ivs_free PARAMS((struct loop *));
static void strength_reduce PARAMS ((struct loop *, int, int)); static void strength_reduce PARAMS ((struct loop *, int, int));
static void find_single_use_in_loop PARAMS ((struct loop_regs *, rtx, rtx)); static void find_single_use_in_loop PARAMS ((struct loop_regs *, rtx, rtx));
...@@ -225,7 +225,8 @@ static int product_cheap_p PARAMS ((rtx, rtx)); ...@@ -225,7 +225,8 @@ static int product_cheap_p PARAMS ((rtx, rtx));
static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *, static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *,
int, int, int)); int, int, int));
static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx, static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx,
struct iv_class *, int, rtx)); struct iv_class *, int,
basic_block, rtx));
static int last_use_this_basic_block PARAMS ((rtx, rtx)); static int last_use_this_basic_block PARAMS ((rtx, rtx));
static void record_initial PARAMS ((rtx, rtx, void *)); static void record_initial PARAMS ((rtx, rtx, void *));
static void update_reg_last_use PARAMS ((rtx, rtx)); static void update_reg_last_use PARAMS ((rtx, rtx));
...@@ -244,10 +245,15 @@ static void try_swap_copy_prop PARAMS ((const struct loop *, rtx, ...@@ -244,10 +245,15 @@ static void try_swap_copy_prop PARAMS ((const struct loop *, rtx,
static int replace_label PARAMS ((rtx *, void *)); static int replace_label PARAMS ((rtx *, void *));
static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int)); static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int));
static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int)); static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
static rtx gen_add_mult PARAMS ((rtx, rtx, rtx, rtx));
static void loop_regs_update PARAMS ((const struct loop *, rtx));
static int iv_add_mult_cost PARAMS ((rtx, rtx, rtx, rtx)); static int iv_add_mult_cost PARAMS ((rtx, rtx, rtx, rtx));
static rtx loop_insn_emit_after PARAMS((const struct loop *, basic_block,
rtx, rtx));
static rtx loop_insn_emit_before PARAMS((const struct loop *, basic_block, static rtx loop_insn_emit_before PARAMS((const struct loop *, basic_block,
rtx, rtx)); rtx, rtx));
static rtx loop_insn_sink_or_swim PARAMS((const struct loop *, rtx));
static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int)); static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
void debug_biv PARAMS ((const struct induction *)); void debug_biv PARAMS ((const struct induction *));
...@@ -568,6 +574,15 @@ scan_loop (loop, flags) ...@@ -568,6 +574,15 @@ scan_loop (loop, flags)
loop->scan_start = p; loop->scan_start = p;
/* If loop end is the end of the current function, then emit a
NOTE_INSN_DELETED after loop_end and set loop->sink to the dummy
note insn. This is the position we use when sinking insns out of
the loop. */
if (NEXT_INSN (loop->end) != 0)
loop->sink = NEXT_INSN (loop->end);
else
loop->sink = emit_note_after (NOTE_INSN_DELETED, loop->end);
/* Set up variables describing this loop. */ /* Set up variables describing this loop. */
prescan_loop (loop); prescan_loop (loop);
threshold = (loop_info->has_call ? 1 : 2) * (1 + n_non_fixed_regs); threshold = (loop_info->has_call ? 1 : 2) * (1 + n_non_fixed_regs);
...@@ -3908,20 +3923,22 @@ loop_givs_reduce (loop, bl) ...@@ -3908,20 +3923,22 @@ loop_givs_reduce (loop, bl)
insert_before = v->insn; insert_before = v->insn;
if (tv->mult_val == const1_rtx) if (tv->mult_val == const1_rtx)
emit_iv_add_mult (tv->add_val, v->mult_val, loop_iv_add_mult_emit_before (loop, tv->add_val, v->mult_val,
v->new_reg, v->new_reg, insert_before); v->new_reg, v->new_reg,
0, insert_before);
else /* tv->mult_val == const0_rtx */ else /* tv->mult_val == const0_rtx */
/* A multiply is acceptable here /* A multiply is acceptable here
since this is presumed to be seldom executed. */ since this is presumed to be seldom executed. */
emit_iv_add_mult (tv->add_val, v->mult_val, loop_iv_add_mult_emit_before (loop, tv->add_val, v->mult_val,
v->add_val, v->new_reg, insert_before); v->add_val, v->new_reg,
0, insert_before);
} }
/* Add code at loop start to initialize giv's reduced reg. */ /* Add code at loop start to initialize giv's reduced reg. */
emit_iv_add_mult (extend_value_for_giv (v, bl->initial_value), loop_iv_add_mult_hoist (loop,
v->mult_val, v->add_val, v->new_reg, extend_value_for_giv (v, bl->initial_value),
loop->start); v->mult_val, v->add_val, v->new_reg);
} }
} }
} }
...@@ -3959,11 +3976,10 @@ loop_givs_dead_check (loop, bl) ...@@ -3959,11 +3976,10 @@ loop_givs_dead_check (loop, bl)
static void static void
loop_givs_rescan (loop, bl, reg_map, end_insert_before) loop_givs_rescan (loop, bl, reg_map)
struct loop *loop; struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
rtx *reg_map; rtx *reg_map;
rtx end_insert_before;
{ {
struct induction *v; struct induction *v;
...@@ -4042,22 +4058,12 @@ loop_givs_rescan (loop, bl, reg_map, end_insert_before) ...@@ -4042,22 +4058,12 @@ loop_givs_rescan (loop, bl, reg_map, end_insert_before)
not replaceable. The correct final value is the same as the not replaceable. The correct final value is the same as the
value that the giv starts the reversed loop with. */ value that the giv starts the reversed loop with. */
if (bl->reversed && ! v->replaceable) if (bl->reversed && ! v->replaceable)
emit_iv_add_mult (extend_value_for_giv (v, bl->initial_value), loop_iv_add_mult_sink (loop,
v->mult_val, v->add_val, v->dest_reg, extend_value_for_giv (v, bl->initial_value),
end_insert_before); v->mult_val, v->add_val, v->dest_reg);
else if (v->final_value) else if (v->final_value)
{ loop_insn_sink_or_swim (loop,
/* If the loop has multiple exits, emit the insn before the
loop to ensure that it will always be executed no matter
how the loop exits. Otherwise, emit the insn after the loop,
since this is slightly more efficient. */
if (loop->exit_count)
loop_insn_hoist (loop,
gen_move_insn (v->dest_reg, v->final_value)); gen_move_insn (v->dest_reg, v->final_value));
else
emit_insn_before (gen_move_insn (v->dest_reg, v->final_value),
end_insert_before);
}
if (loop_dump_stream) if (loop_dump_stream)
{ {
...@@ -4207,24 +4213,11 @@ strength_reduce (loop, insn_count, flags) ...@@ -4207,24 +4213,11 @@ strength_reduce (loop, insn_count, flags)
/* Map of pseudo-register replacements. */ /* Map of pseudo-register replacements. */
rtx *reg_map = NULL; rtx *reg_map = NULL;
int reg_map_size; int reg_map_size;
rtx end_insert_before;
int unrolled_insn_copies = 0; int unrolled_insn_copies = 0;
rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
addr_placeholder = gen_reg_rtx (Pmode); addr_placeholder = gen_reg_rtx (Pmode);
/* Save insn immediately after the loop_end. Insns inserted after loop_end
must be put before this insn, so that they will appear in the right
order (i.e. loop order).
If loop_end is the end of the current function, then emit a
NOTE_INSN_DELETED after loop_end and set end_insert_before to the
dummy note insn. */
if (NEXT_INSN (loop->end) != 0)
end_insert_before = NEXT_INSN (loop->end);
else
end_insert_before = emit_note_after (NOTE_INSN_DELETED, loop->end);
ivs->n_regs = max_reg_before_loop; ivs->n_regs = max_reg_before_loop;
ivs->regs = (struct iv *) xcalloc (ivs->n_regs, sizeof (struct iv)); ivs->regs = (struct iv *) xcalloc (ivs->n_regs, sizeof (struct iv));
...@@ -4237,7 +4230,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4237,7 +4230,7 @@ strength_reduce (loop, insn_count, flags)
/* 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 (flags & LOOP_UNROLL) if (flags & LOOP_UNROLL)
unroll_loop (loop, insn_count, end_insert_before, 0); unroll_loop (loop, insn_count, 0);
loop_ivs_free (loop); loop_ivs_free (loop);
return; return;
...@@ -4366,7 +4359,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4366,7 +4359,7 @@ strength_reduce (loop, insn_count, flags)
For each giv register that can be reduced now: if replaceable, For each giv register that can be reduced now: if replaceable,
substitute reduced reg wherever the old giv occurs; substitute reduced reg wherever the old giv occurs;
else add new move insn "giv_reg = reduced_reg". */ else add new move insn "giv_reg = reduced_reg". */
loop_givs_rescan (loop, bl, reg_map, end_insert_before); loop_givs_rescan (loop, bl, reg_map);
/* All the givs based on the biv bl have been reduced if they /* All the givs based on the biv bl have been reduced if they
merit it. */ merit it. */
...@@ -4420,22 +4413,8 @@ strength_reduce (loop, insn_count, flags) ...@@ -4420,22 +4413,8 @@ strength_reduce (loop, insn_count, flags)
value, so we don't need another one. We can't calculate the value, so we don't need another one. We can't calculate the
proper final value for such a biv here anyways. */ proper final value for such a biv here anyways. */
if (bl->final_value && ! bl->reversed) if (bl->final_value && ! bl->reversed)
{ loop_insn_sink_or_swim (loop, gen_move_insn
rtx insert_before; (bl->biv->dest_reg, bl->final_value));
/* If the loop has multiple exits, emit the insn before the
loop to ensure that it will always be executed no matter
how the loop exits. Otherwise, emit the insn after the
loop, since this is slightly more efficient. */
if (loop->exit_count)
insert_before = loop->start;
else
insert_before = end_insert_before;
emit_insn_before (gen_move_insn (bl->biv->dest_reg,
bl->final_value),
end_insert_before);
}
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv eliminated\n", fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
...@@ -4489,7 +4468,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -4489,7 +4468,7 @@ strength_reduce (loop, insn_count, flags)
if ((flags & LOOP_UNROLL) if ((flags & LOOP_UNROLL)
|| (loop_info->n_iterations > 0 || (loop_info->n_iterations > 0
&& unrolled_insn_copies <= insn_count)) && unrolled_insn_copies <= insn_count))
unroll_loop (loop, insn_count, end_insert_before, 1); unroll_loop (loop, insn_count, 1);
#ifdef HAVE_doloop_end #ifdef HAVE_doloop_end
if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg) if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg)
...@@ -6863,40 +6842,38 @@ restart: ...@@ -6863,40 +6842,38 @@ restart:
free (can_combine); free (can_combine);
} }
/* EMIT code before INSERT_BEFORE to set REG = B * M + A. */ /* Generate sequence for REG = B * M + A. */
void static rtx
emit_iv_add_mult (b, m, a, reg, insert_before) gen_add_mult (b, m, a, reg)
rtx b; /* initial value of basic induction variable */ rtx b; /* initial value of basic induction variable */
rtx m; /* multiplicative constant */ rtx m; /* multiplicative constant */
rtx a; /* additive constant */ rtx a; /* additive constant */
rtx reg; /* destination register */ rtx reg; /* destination register */
rtx insert_before;
{ {
rtx seq; rtx seq;
rtx result; rtx result;
/* Prevent unexpected sharing of these rtx. */
a = copy_rtx (a);
b = copy_rtx (b);
/* Increase the lifetime of any invariants moved further in code. */
update_reg_last_use (a, insert_before);
update_reg_last_use (b, insert_before);
update_reg_last_use (m, insert_before);
start_sequence (); start_sequence ();
/* Use unsigned arithmetic. */
result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1); result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
if (reg != result) if (reg != result)
emit_move_insn (reg, result); emit_move_insn (reg, result);
seq = gen_sequence (); seq = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (seq, insert_before); return seq;
}
/* It is entirely possible that the expansion created lots of new /* Update registers created in insn sequence SEQ. */
registers. Iterate over the sequence we just created and
record them all. */ static void
loop_regs_update (loop, seq)
const struct loop *loop ATTRIBUTE_UNUSED;
rtx seq;
{
/* Update register info for alias analysis. */
if (GET_CODE (seq) == SEQUENCE) if (GET_CODE (seq) == SEQUENCE)
{ {
...@@ -6916,8 +6893,99 @@ emit_iv_add_mult (b, m, a, reg, insert_before) ...@@ -6916,8 +6893,99 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
} }
} }
/* Similar to emit_iv_add_mult, but compute cost rather than emitting
insns. */ /* EMIT code before BEFORE_BB/BEFORE_INSN to set REG = B * M + A. */
void
loop_iv_add_mult_emit_before (loop, b, m, a, reg, before_bb, before_insn)
const struct loop *loop;
rtx b; /* initial value of basic induction variable */
rtx m; /* multiplicative constant */
rtx a; /* additive constant */
rtx reg; /* destination register */
basic_block before_bb;
rtx before_insn;
{
rtx seq;
if (! before_insn)
{
loop_iv_add_mult_hoist (loop, b, m, a, reg);
return;
}
/* Use copy_rtx to prevent unexpected sharing of these rtx. */
seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
/* Increase the lifetime of any invariants moved further in code. */
update_reg_last_use (a, before_insn);
update_reg_last_use (b, before_insn);
update_reg_last_use (m, before_insn);
loop_insn_emit_before (loop, before_bb, before_insn, seq);
/* It is possible that the expansion created lots of new registers.
Iterate over the sequence we just created and record them all. */
loop_regs_update (loop, seq);
}
/* Emit insns in loop pre-header to set REG = B * M + A. */
void
loop_iv_add_mult_sink (loop, b, m, a, reg)
const struct loop *loop;
rtx b; /* initial value of basic induction variable */
rtx m; /* multiplicative constant */
rtx a; /* additive constant */
rtx reg; /* destination register */
{
rtx seq;
/* Use copy_rtx to prevent unexpected sharing of these rtx. */
seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
/* Increase the lifetime of any invariants moved further in code.
???? Is this really necessary? */
update_reg_last_use (a, loop->sink);
update_reg_last_use (b, loop->sink);
update_reg_last_use (m, loop->sink);
loop_insn_sink (loop, seq);
/* It is possible that the expansion created lots of new registers.
Iterate over the sequence we just created and record them all. */
loop_regs_update (loop, seq);
}
/* Emit insns after loop to set REG = B * M + A. */
void
loop_iv_add_mult_hoist (loop, b, m, a, reg)
const struct loop *loop;
rtx b; /* initial value of basic induction variable */
rtx m; /* multiplicative constant */
rtx a; /* additive constant */
rtx reg; /* destination register */
{
rtx seq;
/* Use copy_rtx to prevent unexpected sharing of these rtx. */
seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
loop_insn_hoist (loop, seq);
/* It is possible that the expansion created lots of new registers.
Iterate over the sequence we just created and record them all. */
loop_regs_update (loop, seq);
}
/* Similar to gen_add_mult, but compute cost rather than generating
sequence. */
static int static int
iv_add_mult_cost (b, m, a, reg) iv_add_mult_cost (b, m, a, reg)
rtx b; /* initial value of basic induction variable */ rtx b; /* initial value of basic induction variable */
...@@ -6929,7 +6997,7 @@ iv_add_mult_cost (b, m, a, reg) ...@@ -6929,7 +6997,7 @@ iv_add_mult_cost (b, m, a, reg)
rtx last, result; rtx last, result;
start_sequence (); start_sequence ();
result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 0); result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
if (reg != result) if (reg != result)
emit_move_insn (reg, result); emit_move_insn (reg, result);
last = get_last_insn (); last = get_last_insn ();
...@@ -7517,8 +7585,7 @@ check_dbra_loop (loop, insn_count) ...@@ -7517,8 +7585,7 @@ check_dbra_loop (loop, insn_count)
if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare)) if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
|| ! bl->init_insn || ! bl->init_insn
|| REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn)) || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
emit_insn_after (gen_move_insn (reg, final_value), loop_insn_sink (loop, gen_move_insn (reg, final_value));
loop_end);
/* Delete compare/branch at end of loop. */ /* Delete compare/branch at end of loop. */
delete_insn (PREV_INSN (loop_end)); delete_insn (PREV_INSN (loop_end));
...@@ -7630,17 +7697,16 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count) ...@@ -7630,17 +7697,16 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
{ {
struct loop_ivs *ivs = LOOP_IVS (loop); struct loop_ivs *ivs = LOOP_IVS (loop);
rtx reg = bl->biv->dest_reg; rtx reg = bl->biv->dest_reg;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
rtx p; rtx p;
/* Scan all insns in the loop, stopping if we find one that uses the /* Scan all insns in the loop, stopping if we find one that uses the
biv in a way that we cannot eliminate. */ biv in a way that we cannot eliminate. */
for (p = loop_start; p != loop_end; p = NEXT_INSN (p)) for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
{ {
enum rtx_code code = GET_CODE (p); enum rtx_code code = GET_CODE (p);
rtx where = threshold >= insn_count ? loop_start : p; basic_block where_bb = 0;
rtx where_insn = threshold >= insn_count ? 0 : p;
/* If this is a libcall that sets a giv, skip ahead to its end. */ /* If this is a libcall that sets a giv, skip ahead to its end. */
if (GET_RTX_CLASS (code) == 'i') if (GET_RTX_CLASS (code) == 'i')
...@@ -7666,7 +7732,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count) ...@@ -7666,7 +7732,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
if ((code == INSN || code == JUMP_INSN || code == CALL_INSN) if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
&& reg_mentioned_p (reg, PATTERN (p)) && reg_mentioned_p (reg, PATTERN (p))
&& ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl, && ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl,
eliminate_p, where)) eliminate_p, where_bb, where_insn))
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -7676,7 +7742,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count) ...@@ -7676,7 +7742,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
} }
} }
if (p == loop_end) if (p == loop->end)
{ {
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "biv %d %s eliminated.\n", fprintf (loop_dump_stream, "biv %d %s eliminated.\n",
...@@ -7748,18 +7814,20 @@ biv_elimination_giv_has_0_offset (biv, giv, insn) ...@@ -7748,18 +7814,20 @@ biv_elimination_giv_has_0_offset (biv, giv, insn)
If BIV does not appear in X, return 1. If BIV does not appear in X, return 1.
If ELIMINATE_P is non-zero, actually do the elimination. WHERE indicates If ELIMINATE_P is non-zero, actually do the elimination.
where extra insns should be added. Depending on how many items have been WHERE_INSN/WHERE_BB indicate where extra insns should be added.
moved out of the loop, it will either be before INSN or at the start of Depending on how many items have been moved out of the loop, it
the loop. */ will either be before INSN (when WHERE_INSN is non-zero) or at the
start of the loop (when WHERE_INSN is zero). */
static int static int
maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
const struct loop *loop; const struct loop *loop;
rtx x, insn; rtx x, insn;
struct iv_class *bl; struct iv_class *bl;
int eliminate_p; int eliminate_p;
rtx where; basic_block where_bb;
rtx where_insn;
{ {
enum rtx_code code = GET_CODE (x); enum rtx_code code = GET_CODE (x);
rtx reg = bl->biv->dest_reg; rtx reg = bl->biv->dest_reg;
...@@ -7870,7 +7938,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -7870,7 +7938,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
tem = gen_reg_rtx (GET_MODE (v->new_reg)); tem = gen_reg_rtx (GET_MODE (v->new_reg));
emit_insn_before (gen_move_insn (tem, copy_rtx (v->add_val)), emit_insn_before (gen_move_insn (tem, copy_rtx (v->add_val)),
where); where_insn);
/* Substitute the new register for its invariant value in /* Substitute the new register for its invariant value in
the compare expression. */ the compare expression. */
...@@ -7936,7 +8004,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -7936,7 +8004,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
{ {
/* Otherwise, load it into a register. */ /* Otherwise, load it into a register. */
tem = gen_reg_rtx (mode); tem = gen_reg_rtx (mode);
emit_iv_add_mult (arg, v->mult_val, v->add_val, tem, where); loop_iv_add_mult_emit_before (loop, arg,
v->mult_val, v->add_val,
tem, where_bb, where_insn);
validate_change (insn, &XEXP (x, arg_operand), tem, 1); validate_change (insn, &XEXP (x, arg_operand), tem, 1);
} }
if (apply_change_group ()) if (apply_change_group ())
...@@ -7969,7 +8039,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -7969,7 +8039,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
v->new_reg, 1); v->new_reg, 1);
/* Compute value to compare against. */ /* Compute value to compare against. */
emit_iv_add_mult (arg, v->mult_val, v->add_val, tem, where); loop_iv_add_mult_emit_before (loop, arg,
v->mult_val, v->add_val,
tem, where_bb, where_insn);
/* Use it in this insn. */ /* Use it in this insn. */
validate_change (insn, &XEXP (x, arg_operand), tem, 1); validate_change (insn, &XEXP (x, arg_operand), tem, 1);
if (apply_change_group ()) if (apply_change_group ())
...@@ -8005,8 +8077,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -8005,8 +8077,9 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
v->new_reg, 1); v->new_reg, 1);
/* Compute value to compare against. */ /* Compute value to compare against. */
emit_iv_add_mult (arg, v->mult_val, v->add_val, loop_iv_add_mult_emit_before (loop, arg,
tem, where); v->mult_val, v->add_val,
tem, where_bb, where_insn);
validate_change (insn, &XEXP (x, arg_operand), tem, 1); validate_change (insn, &XEXP (x, arg_operand), tem, 1);
if (apply_change_group ()) if (apply_change_group ())
return 1; return 1;
...@@ -8087,14 +8160,14 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where) ...@@ -8087,14 +8160,14 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
{ {
case 'e': case 'e':
if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl, if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl,
eliminate_p, where)) eliminate_p, where_bb, where_insn))
return 0; return 0;
break; break;
case 'E': case 'E':
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (! maybe_eliminate_biv_1 (loop, XVECEXP (x, i, j), insn, bl, if (! maybe_eliminate_biv_1 (loop, XVECEXP (x, i, j), insn, bl,
eliminate_p, where)) eliminate_p, where_bb, where_insn))
return 0; return 0;
break; break;
} }
...@@ -8152,7 +8225,7 @@ record_initial (dest, set, data) ...@@ -8152,7 +8225,7 @@ record_initial (dest, set, data)
/* If any of the registers in X are "old" and currently have a last use earlier /* If any of the registers in X are "old" and currently have a last use earlier
than INSN, update them to have a last use of INSN. Their actual last use than INSN, update them to have a last use of INSN. Their actual last use
will be the previous insn but it will not have a valid uid_luid so we can't will be the previous insn but it will not have a valid uid_luid so we can't
use it. */ use it. X must be a source expression only. */
static void static void
update_reg_last_use (x, insn) update_reg_last_use (x, insn)
...@@ -8162,11 +8235,15 @@ update_reg_last_use (x, insn) ...@@ -8162,11 +8235,15 @@ update_reg_last_use (x, insn)
/* Check for the case where INSN does not have a valid luid. In this case, /* Check for the case where INSN does not have a valid luid. In this case,
there is no need to modify the regno_last_uid, as this can only happen there is no need to modify the regno_last_uid, as this can only happen
when code is inserted after the loop_end to set a pseudo's final value, when code is inserted after the loop_end to set a pseudo's final value,
and hence this insn will never be the last use of x. */ and hence this insn will never be the last use of x.
???? This comment is not correct. See for example loop_givs_reduce.
This may insert an insn before another new insn. */
if (GET_CODE (x) == REG && REGNO (x) < max_reg_before_loop if (GET_CODE (x) == REG && REGNO (x) < max_reg_before_loop
&& INSN_UID (insn) < max_uid_for_loop && INSN_UID (insn) < max_uid_for_loop
&& REGNO_LAST_LUID (REGNO (x)) < INSN_LUID (insn)) && REGNO_LAST_LUID (REGNO (x)) < INSN_LUID (insn))
{
REGNO_LAST_UID (REGNO (x)) = INSN_UID (insn); REGNO_LAST_UID (REGNO (x)) = INSN_UID (insn);
}
else else
{ {
register int i, j; register int i, j;
...@@ -9360,6 +9437,20 @@ replace_label (x, data) ...@@ -9360,6 +9437,20 @@ replace_label (x, data)
return 0; return 0;
} }
/* Emit insn for PATTERN after WHERE_INSN in basic block WHERE_BB
(ignored in the interim). */
static rtx
loop_insn_emit_after (loop, where_bb, where_insn, pattern)
const struct loop *loop ATTRIBUTE_UNUSED;
basic_block where_bb ATTRIBUTE_UNUSED;
rtx where_insn;
rtx pattern;
{
return emit_insn_after (pattern, where_insn);
}
/* If WHERE_INSN is non-zero emit insn for PATTERN before WHERE_INSN /* If WHERE_INSN is non-zero emit insn for PATTERN before WHERE_INSN
in basic block WHERE_BB (ignored in the interim) within the loop in basic block WHERE_BB (ignored in the interim) within the loop
otherwise hoist PATTERN into the loop pre-header. */ otherwise hoist PATTERN into the loop pre-header. */
...@@ -9387,6 +9478,34 @@ loop_insn_hoist (loop, pattern) ...@@ -9387,6 +9478,34 @@ loop_insn_hoist (loop, pattern)
return loop_insn_emit_before (loop, 0, loop->start, pattern); return loop_insn_emit_before (loop, 0, loop->start, pattern);
} }
/* Sink insn for PATTERN after the loop end. */
rtx
loop_insn_sink (loop, pattern)
const struct loop *loop;
rtx pattern;
{
return loop_insn_emit_before (loop, 0, loop->sink, pattern);
}
/* If the loop has multiple exits, emit insn for PATTERN before the
loop to ensure that it will always be executed no matter how the
loop exits. Otherwise, emit the insn for PATTERN after the loop,
since this is slightly more efficient. */
static rtx
loop_insn_sink_or_swim (loop, pattern)
const struct loop *loop;
rtx pattern;
{
if (loop->exit_count)
return loop_insn_hoist (loop, pattern);
else
return loop_insn_sink (loop, pattern);
}
static void static void
loop_biv_dump (v, file, verbose) loop_biv_dump (v, file, verbose)
const struct induction *v; const struct induction *v;
......
...@@ -19,6 +19,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330, ...@@ -19,6 +19,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
#include "bitmap.h" #include "bitmap.h"
#include "sbitmap.h"
#include "hard-reg-set.h"
#include "basic-block.h"
/* Flags passed to loop_optimize. */ /* Flags passed to loop_optimize. */
#define LOOP_UNROLL 1 #define LOOP_UNROLL 1
...@@ -386,11 +389,15 @@ extern FILE *loop_dump_stream; ...@@ -386,11 +389,15 @@ extern FILE *loop_dump_stream;
unroll.c. */ unroll.c. */
int loop_invariant_p PARAMS ((const struct loop *, rtx)); int loop_invariant_p PARAMS ((const struct loop *, rtx));
rtx get_condition_for_loop PARAMS ((const struct loop *, rtx)); rtx get_condition_for_loop PARAMS ((const struct loop *, rtx));
void emit_iv_add_mult PARAMS ((rtx, rtx, rtx, rtx, rtx)); void loop_iv_add_mult_hoist PARAMS ((const struct loop *, rtx, rtx, rtx, rtx));
void loop_iv_add_mult_sink PARAMS ((const struct loop *, rtx, rtx, rtx, rtx));
void loop_iv_add_mult_emit_before PARAMS ((const struct loop *, rtx,
rtx, rtx, rtx,
basic_block, rtx));
rtx express_from PARAMS ((struct induction *, struct induction *)); rtx express_from PARAMS ((struct induction *, struct induction *));
rtx extend_value_for_giv PARAMS ((struct induction *, rtx)); rtx extend_value_for_giv PARAMS ((struct induction *, rtx));
void unroll_loop PARAMS ((struct loop *, int, rtx, int)); void unroll_loop PARAMS ((struct loop *, int, int));
rtx biv_total_increment PARAMS ((struct iv_class *)); rtx biv_total_increment PARAMS ((struct iv_class *));
unsigned HOST_WIDE_INT loop_iterations PARAMS ((struct loop *)); unsigned HOST_WIDE_INT loop_iterations PARAMS ((struct loop *));
int precondition_loop_p PARAMS ((const struct loop *, int precondition_loop_p PARAMS ((const struct loop *,
...@@ -404,6 +411,7 @@ int back_branch_in_range_p PARAMS ((const struct loop *, rtx)); ...@@ -404,6 +411,7 @@ int back_branch_in_range_p PARAMS ((const struct loop *, rtx));
int loop_insn_first_p PARAMS ((rtx, rtx)); int loop_insn_first_p PARAMS ((rtx, rtx));
typedef rtx (*loop_insn_callback) PARAMS ((struct loop *, rtx, int, int)); typedef rtx (*loop_insn_callback) PARAMS ((struct loop *, rtx, int, int));
void for_each_insn_in_loop PARAMS ((struct loop *, loop_insn_callback)); void for_each_insn_in_loop PARAMS ((struct loop *, loop_insn_callback));
rtx loop_insn_sink PARAMS((const struct loop *, rtx));
rtx loop_insn_hoist PARAMS((const struct loop *, rtx)); rtx loop_insn_hoist PARAMS((const struct loop *, rtx));
/* Forward declarations for non-static functions declared in doloop.c. */ /* Forward declarations for non-static functions declared in doloop.c. */
......
...@@ -206,7 +206,7 @@ static void copy_loop_body PARAMS ((struct loop *, rtx, rtx, ...@@ -206,7 +206,7 @@ static void copy_loop_body PARAMS ((struct loop *, rtx, rtx,
struct inline_remap *, rtx, int, struct inline_remap *, rtx, int,
enum unroll_types, rtx, rtx, rtx, rtx)); enum unroll_types, rtx, 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, int));
static int find_splittable_givs PARAMS ((const struct loop *, static int find_splittable_givs PARAMS ((const struct loop *,
struct iv_class *, enum unroll_types, struct iv_class *, enum unroll_types,
rtx, int)); rtx, int));
...@@ -222,19 +222,16 @@ static rtx ujump_to_loop_cont PARAMS ((rtx, rtx)); ...@@ -222,19 +222,16 @@ static rtx ujump_to_loop_cont PARAMS ((rtx, rtx));
/* Try to unroll one loop and split induction variables in the loop. /* Try to unroll one loop and split induction variables in the loop.
The loop is described by the arguments LOOP and INSN_COUNT. The loop is described by the arguments LOOP and INSN_COUNT.
END_INSERT_BEFORE indicates where insns should be added which need STRENGTH_REDUCTION_P indicates whether information generated in the
to be executed when the loop falls through. STRENGTH_REDUCTION_P strength reduction pass is available.
indicates whether information generated in the strength reduction
pass is available.
This function is intended to be called from within `strength_reduce' This function is intended to be called from within `strength_reduce'
in loop.c. */ in loop.c. */
void void
unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) unroll_loop (loop, insn_count, strength_reduce_p)
struct loop *loop; struct loop *loop;
int insn_count; int insn_count;
rtx end_insert_before;
int strength_reduce_p; int strength_reduce_p;
{ {
struct loop_info *loop_info = LOOP_INFO (loop); struct loop_info *loop_info = LOOP_INFO (loop);
...@@ -1045,7 +1042,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1045,7 +1042,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
sequence = gen_sequence (); sequence = gen_sequence ();
end_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 /* Only the last copy of the loop body here needs the exit
test, so set copy_end to exclude the compare/branch here, test, so set copy_end to exclude the compare/branch here,
...@@ -1163,8 +1160,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p) ...@@ -1163,8 +1160,7 @@ unroll_loop (loop, insn_count, end_insert_before, strength_reduce_p)
if (splitting_not_safe) if (splitting_not_safe)
temp = 0; temp = 0;
else else
temp = find_splittable_regs (loop, unroll_type, temp = find_splittable_regs (loop, unroll_type, unroll_number);
end_insert_before, unroll_number);
/* 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
...@@ -2431,10 +2427,9 @@ biv_total_increment (bl) ...@@ -2431,10 +2427,9 @@ biv_total_increment (bl)
times, since multiplies by small integers (1,2,3,4) are very cheap. */ times, since multiplies by small integers (1,2,3,4) are very cheap. */
static int 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; const struct loop *loop;
enum unroll_types unroll_type; enum unroll_types unroll_type;
rtx end_insert_before;
int unroll_number; int unroll_number;
{ {
struct loop_ivs *ivs = LOOP_IVS (loop); struct loop_ivs *ivs = LOOP_IVS (loop);
...@@ -2444,8 +2439,6 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2444,8 +2439,6 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx biv_final_value; rtx biv_final_value;
int biv_splittable; int biv_splittable;
int result = 0; int result = 0;
rtx loop_start = loop->start;
rtx loop_end = loop->end;
for (bl = ivs->list; bl; bl = bl->next) for (bl = ivs->list; bl; bl = bl->next)
{ {
...@@ -2469,7 +2462,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2469,7 +2462,7 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
biv_final_value = 0; biv_final_value = 0;
if (unroll_type != UNROLL_COMPLETELY if (unroll_type != UNROLL_COMPLETELY
&& (loop->exit_count || unroll_type == UNROLL_NAIVE) && (loop->exit_count || unroll_type == UNROLL_NAIVE)
&& (REGNO_LAST_LUID (bl->regno) >= INSN_LUID (loop_end) && (REGNO_LAST_LUID (bl->regno) >= INSN_LUID (loop->end)
|| ! bl->init_insn || ! bl->init_insn
|| INSN_UID (bl->init_insn) >= max_uid_for_loop || INSN_UID (bl->init_insn) >= max_uid_for_loop
|| (REGNO_FIRST_LUID (bl->regno) || (REGNO_FIRST_LUID (bl->regno)
...@@ -2512,8 +2505,8 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2512,8 +2505,8 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx tem = gen_reg_rtx (bl->biv->mode); rtx 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_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_insn_hoist (loop,
loop_start); gen_move_insn (tem, bl->biv->src_reg));
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -2558,9 +2551,8 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2558,9 +2551,8 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
how the loop exits. Otherwise emit the insn after the loop, how the loop exits. Otherwise emit the insn after the loop,
since this is slightly more efficient. */ since this is slightly more efficient. */
if (! loop->exit_count) if (! loop->exit_count)
emit_insn_before (gen_move_insn (bl->biv->src_reg, loop_insn_sink (loop, gen_move_insn (bl->biv->src_reg,
biv_final_value), biv_final_value));
end_insert_before);
else else
{ {
/* Create a new register to hold the value of the biv, and then /* Create a new register to hold the value of the biv, and then
...@@ -2571,11 +2563,9 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number) ...@@ -2571,11 +2563,9 @@ find_splittable_regs (loop, unroll_type, end_insert_before, unroll_number)
rtx tem = gen_reg_rtx (bl->biv->mode); rtx 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_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
loop_start); loop_insn_hoist (loop, gen_move_insn (bl->biv->src_reg,
emit_insn_before (gen_move_insn (bl->biv->src_reg, biv_final_value));
biv_final_value),
loop_start);
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n", fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n",
...@@ -2717,9 +2707,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2717,9 +2707,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
to its final value before loop start to ensure that this insn to its final value before loop start to ensure that this insn
will always be executed, no matter how we exit. */ will always be executed, no matter how we exit. */
tem = gen_reg_rtx (v->mode); tem = gen_reg_rtx (v->mode);
emit_insn_before (gen_move_insn (tem, v->dest_reg), loop_start); loop_insn_hoist (loop, gen_move_insn (tem, v->dest_reg));
emit_insn_before (gen_move_insn (v->dest_reg, final_value), loop_insn_hoist (loop, gen_move_insn (v->dest_reg, final_value));
loop_start);
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n", fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
...@@ -2752,8 +2741,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2752,8 +2741,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
rtx tem = gen_reg_rtx (bl->biv->mode); rtx 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_insn_before (gen_move_insn (tem, bl->biv->src_reg), loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
loop->start);
biv_initial_value = tem; biv_initial_value = tem;
} }
biv_initial_value = extend_value_for_giv (v, biv_initial_value); biv_initial_value = extend_value_for_giv (v, biv_initial_value);
...@@ -2795,8 +2783,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2795,8 +2783,8 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
{ {
rtx tem = gen_reg_rtx (v->mode); rtx tem = gen_reg_rtx (v->mode);
record_base_value (REGNO (tem), v->add_val, 0); record_base_value (REGNO (tem), v->add_val, 0);
emit_iv_add_mult (bl->initial_value, v->mult_val, loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
v->add_val, tem, loop->start); v->add_val, tem);
value = tem; value = tem;
} }
...@@ -2923,17 +2911,15 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2923,17 +2911,15 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
instruction on machines with complex addressing modes. instruction on machines with complex addressing modes.
If we can't recognize it, then delete it and emit insns If we can't recognize it, then delete it and emit insns
to calculate the value from scratch. */ to calculate the value from scratch. */
emit_insn_before (gen_rtx_SET (VOIDmode, tem, loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
copy_rtx (v->new_reg)), copy_rtx (v->new_reg)));
loop->start);
if (recog_memoized (PREV_INSN (loop->start)) < 0) if (recog_memoized (PREV_INSN (loop->start)) < 0)
{ {
rtx sequence, ret; rtx sequence, ret;
/* We can't use bl->initial_value to compute the initial /* We can't use bl->initial_value to compute the initial
value, because the loop may have been preconditioned. value, because the loop may have been preconditioned.
We must calculate it from NEW_REG. Try using We must calculate it from NEW_REG. */
force_operand instead of emit_iv_add_mult. */
delete_insn (PREV_INSN (loop->start)); delete_insn (PREV_INSN (loop->start));
start_sequence (); start_sequence ();
...@@ -2942,7 +2928,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number) ...@@ -2942,7 +2928,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
emit_move_insn (tem, ret); emit_move_insn (tem, ret);
sequence = gen_sequence (); sequence = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (sequence, loop->start); loop_insn_hoist (loop, sequence);
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3140,7 +3126,6 @@ final_biv_value (loop, bl) ...@@ -3140,7 +3126,6 @@ final_biv_value (loop, bl)
const struct loop *loop; const struct loop *loop;
struct iv_class *bl; struct iv_class *bl;
{ {
rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations; unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
rtx increment, tem; rtx increment, tem;
...@@ -3182,11 +3167,8 @@ final_biv_value (loop, bl) ...@@ -3182,11 +3167,8 @@ final_biv_value (loop, bl)
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);
/* Make sure loop_end is not the last insn. */ loop_iv_add_mult_sink (loop, increment, GEN_INT (n_iterations),
if (NEXT_INSN (loop_end) == 0) bl->initial_value, tem);
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));
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
...@@ -3222,7 +3204,7 @@ final_giv_value (loop, v) ...@@ -3222,7 +3204,7 @@ final_giv_value (loop, v)
struct iv_class *bl; struct iv_class *bl;
rtx insn; rtx insn;
rtx increment, tem; rtx increment, tem;
rtx insert_before, seq; rtx seq;
rtx loop_end = loop->end; rtx loop_end = loop->end;
unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations; unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
...@@ -3279,15 +3261,13 @@ final_giv_value (loop, v) ...@@ -3279,15 +3261,13 @@ final_giv_value (loop, v)
We must search from the insn that sets the giv to the end We must search from the insn that sets the giv to the end
of the loop to calculate this value. */ of the loop to calculate this value. */
insert_before = NEXT_INSN (loop_end);
/* Put the final biv value in tem. */ /* Put the final biv value in tem. */
tem = gen_reg_rtx (v->mode); tem = gen_reg_rtx (v->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 (extend_value_for_giv (v, increment), loop_iv_add_mult_sink (loop, extend_value_for_giv (v, increment),
GEN_INT (n_iterations), GEN_INT (n_iterations),
extend_value_for_giv (v, bl->initial_value), extend_value_for_giv (v, bl->initial_value),
tem, insert_before); tem);
/* Subtract off extra increments as we find them. */ /* Subtract off extra increments as we find them. */
for (insn = NEXT_INSN (v->insn); insn != loop_end; for (insn = NEXT_INSN (v->insn); insn != loop_end;
...@@ -3304,12 +3284,12 @@ final_giv_value (loop, v) ...@@ -3304,12 +3284,12 @@ final_giv_value (loop, v)
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
seq = gen_sequence (); seq = gen_sequence ();
end_sequence (); end_sequence ();
emit_insn_before (seq, insert_before); loop_insn_sink (loop, seq);
} }
} }
/* Now calculate the giv's final value. */ /* 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) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
......
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