diff options
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 66 |
1 files changed, 50 insertions, 16 deletions
@@ -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: |