aboutsummaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1999-12-07 19:22:33 -0800
committerRichard Henderson <rth@gcc.gnu.org>1999-12-07 19:22:33 -0800
commit60fb6df968b2ed5ee054874052371f08b59cb712 (patch)
tree9c8c66c576241096238da778fd7a4457cc1fb503 /gcc/loop.c
parent3043b30ec807350898618ba9ea7d7fe1787f866f (diff)
downloadgcc-60fb6df968b2ed5ee054874052371f08b59cb712.zip
gcc-60fb6df968b2ed5ee054874052371f08b59cb712.tar.gz
gcc-60fb6df968b2ed5ee054874052371f08b59cb712.tar.bz2
loop.h (struct induction): Add multi_insn_incr.
* loop.h (struct induction): Add multi_insn_incr. * loop.c (basic_induction_var): New multi_insn_incr argument. Set it if we search back through previous insns for the biv. (record_biv): New multi_insn_incr argument; fill in struct induction. (strength_reduce): Discard an iv with multiple bivs, any of which require multiple insns to increment. From-SVN: r30820
Diffstat (limited to 'gcc/loop.c')
-rw-r--r--gcc/loop.c66
1 files changed, 50 insertions, 16 deletions
diff --git a/gcc/loop.c b/gcc/loop.c
index 5921e5e..90e6c44 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -310,12 +310,12 @@ static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx,
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, int, rtx, rtx));
-static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int));
+static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int, int));
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, 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 *, rtx **));
+static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **, int *));
static rtx simplify_giv_expr PROTO((rtx, int *));
static int general_induction_var PROTO((rtx, rtx *, rtx *, rtx *, int, int *));
static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
@@ -3837,9 +3837,11 @@ strength_reduce (scan_start, end, loop_top, insn_count,
&& REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
&& REG_IV_TYPE (REGNO (dest_reg)) != NOT_BASIC_INDUCT)
{
+ int multi_insn_incr = 0;
+
if (basic_induction_var (SET_SRC (set), GET_MODE (SET_SRC (set)),
dest_reg, p, &inc_val, &mult_val,
- &location))
+ &location, &multi_insn_incr))
{
/* It is a possible basic induction variable.
Create and initialize an induction structure for it. */
@@ -3848,7 +3850,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
= (struct induction *) alloca (sizeof (struct induction));
record_biv (v, p, dest_reg, inc_val, mult_val, location,
- not_every_iteration, maybe_multiple);
+ not_every_iteration, maybe_multiple,
+ multi_insn_incr);
REG_IV_TYPE (REGNO (dest_reg)) = BASIC_INDUCT;
}
else if (REGNO (dest_reg) < max_reg_before_loop)
@@ -3976,6 +3979,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
Make a sanity check against n_times_set. */
for (backbl = &loop_iv_list, bl = *backbl; bl; bl = bl->next)
{
+ int fail = 0;
+
if (REG_IV_TYPE (bl->regno) != BASIC_INDUCT
/* Above happens if register modified by subreg, etc. */
/* Make sure it is not recognized as a basic induction var: */
@@ -3983,6 +3988,21 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* If never incremented, it is invariant that we decided not to
move. So leave it alone. */
|| ! bl->incremented)
+ fail = 1;
+ else if (bl->biv_count > 1)
+ {
+ /* ??? If we have multiple increments for this BIV, and any of
+ them take multiple insns to perform the increment, drop the
+ BIV, since the bit below that converts the extra increments
+ into GIVs can't handle the multiple insn increment. */
+
+ struct induction *v;
+ for (v = bl->biv; v ; v = v->next_iv)
+ if (v->multi_insn_incr)
+ fail = 1;
+ }
+
+ if (fail)
{
if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
@@ -4453,7 +4473,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Increment %d of biv %d converted to giv %d.\n\n",
+ "Increment %d of biv %d converted to giv %d.\n",
INSN_UID (v->insn), old_regno, new_regno);
}
}
@@ -5460,7 +5480,7 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
static void
record_biv (v, insn, dest_reg, inc_val, mult_val, location,
- not_every_iteration, maybe_multiple)
+ not_every_iteration, maybe_multiple, multi_insn_incr)
struct induction *v;
rtx insn;
rtx dest_reg;
@@ -5482,6 +5502,7 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
v->always_computable = ! not_every_iteration;
v->always_executed = ! not_every_iteration;
v->maybe_multiple = maybe_multiple;
+ v->multi_insn_incr = multi_insn_incr;
/* Add this to the reg's iv_class, creating a class
if this is the first incrementation of the reg. */
@@ -5589,6 +5610,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
v->cant_derive = 0;
v->combined_with = 0;
v->maybe_multiple = maybe_multiple;
+ v->multi_insn_incr = 0;
v->maybe_dead = 0;
v->derive_adjustment = 0;
v->same = 0;
@@ -6077,7 +6099,8 @@ update_giv_derive (p)
If we cannot find a biv, we return 0. */
static int
-basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
+basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location,
+ multi_insn_incr)
register rtx x;
enum machine_mode mode;
rtx p;
@@ -6085,6 +6108,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
rtx *inc_val;
rtx *mult_val;
rtx **location;
+ int *multi_insn_incr;
{
register enum rtx_code code;
rtx *argp, arg;
@@ -6126,7 +6150,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
value. */
if (SUBREG_PROMOTED_VAR_P (x))
return basic_induction_var (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)),
- dest_reg, p, inc_val, mult_val, location);
+ dest_reg, p, inc_val, mult_val, location,
+ multi_insn_incr);
return 0;
case REG:
@@ -6159,8 +6184,12 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
? GET_MODE (x)
: GET_MODE (SET_SRC (set))),
dest_reg, insn,
- inc_val, mult_val, location))
- return 1;
+ inc_val, mult_val, location,
+ multi_insn_incr))
+ {
+ *multi_insn_incr = 1;
+ return 1;
+ }
}
/* ... fall through ... */
@@ -6191,7 +6220,8 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
case SIGN_EXTEND:
return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
- dest_reg, p, inc_val, mult_val, location);
+ dest_reg, p, inc_val, mult_val, location,
+ multi_insn_incr);
case ASHIFTRT:
/* Similar, since this can be a sign extension. */
@@ -6208,11 +6238,15 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) >= 0
&& GET_CODE (SET_SRC (set)) == ASHIFT
- && XEXP (x, 1) == XEXP (SET_SRC (set), 1))
- return basic_induction_var (XEXP (SET_SRC (set), 0),
- GET_MODE (XEXP (x, 0)),
- dest_reg, insn, inc_val, mult_val,
- location);
+ && XEXP (x, 1) == XEXP (SET_SRC (set), 1)
+ && basic_induction_var (XEXP (SET_SRC (set), 0),
+ GET_MODE (XEXP (x, 0)),
+ dest_reg, insn, inc_val, mult_val,
+ location, multi_insn_incr))
+ {
+ *multi_insn_incr = 1;
+ return 1;
+ }
return 0;
default: