aboutsummaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/loop.c')
-rw-r--r--gcc/loop.c151
1 files changed, 105 insertions, 46 deletions
diff --git a/gcc/loop.c b/gcc/loop.c
index 59628fd..97265fa 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -301,11 +301,11 @@ static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx,
struct loop_info *, rtx, int, int));
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, rtx, 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 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, rtx *, rtx, rtx));
+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 rtx simplify_giv_expr PROTO((rtx, int *));
@@ -2356,12 +2356,15 @@ constant_high_bytes (p, loop_start)
/* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...)))
to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...). */
- new = gen_rtx_SET (VOIDmode,
- gen_rtx_STRICT_LOW_PART (VOIDmode,
- gen_rtx_SUBREG (GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),
- SET_DEST (PATTERN (p)),
- 0)),
- XEXP (SET_SRC (PATTERN (p)), 0));
+ new
+ = gen_rtx_SET
+ (VOIDmode,
+ gen_rtx_STRICT_LOW_PART
+ (VOIDmode,
+ gen_rtx_SUBREG (GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),
+ SET_DEST (PATTERN (p)), 0)),
+ XEXP (SET_SRC (PATTERN (p)), 0));
+
insn_code_number = recog (new, p);
if (insn_code_number)
@@ -2369,8 +2372,8 @@ constant_high_bytes (p, loop_start)
register int i;
/* Clear destination register before the loop. */
- emit_insn_before (gen_rtx_SET (VOIDmode, SET_DEST (PATTERN (p)),
- const0_rtx),
+ emit_insn_before (gen_rtx_SET (VOIDmode,
+ SET_DEST (PATTERN (p)), const0_rtx),
loop_start);
/* Inside the loop, just load the low part. */
@@ -4377,6 +4380,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
not_every_iteration = 0;
loop_depth = 0;
+ maybe_multiple = 0;
p = scan_start;
while (1)
{
@@ -4445,8 +4449,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
p = last_consec_insn;
record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit,
- DEST_REG, not_every_iteration, NULL_PTR, loop_start,
- loop_end);
+ DEST_REG, not_every_iteration, maybe_multiple,
+ NULL_PTR, loop_start, loop_end);
}
}
@@ -4456,8 +4460,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
/* This resulted in worse code on a VAX 8600. I wonder if it
still does. */
if (GET_CODE (p) == INSN)
- find_mem_givs (PATTERN (p), p, not_every_iteration, loop_start,
- loop_end);
+ find_mem_givs (PATTERN (p), p, not_every_iteration, maybe_multiple,
+ loop_start, loop_end);
#endif
/* Update the status of whether giv can derive other givs. This can
@@ -4466,6 +4470,49 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|| GET_CODE (p) == CODE_LABEL)
update_giv_derive (p);
+ /* Past CODE_LABEL, we get to insns that may be executed multiple
+ times. The only way we can be sure that they can't is if every
+ every jump insn between here and the end of the loop either
+ returns, exits the loop, is a forward jump, or is a jump
+ to the loop start. */
+
+ if (GET_CODE (p) == CODE_LABEL)
+ {
+ rtx insn = p;
+
+ maybe_multiple = 0;
+
+ while (1)
+ {
+ insn = NEXT_INSN (insn);
+ if (insn == scan_start)
+ break;
+ if (insn == end)
+ {
+ if (loop_top != 0)
+ insn = loop_top;
+ else
+ break;
+ if (insn == scan_start)
+ break;
+ }
+
+ if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) != RETURN
+ && (! condjump_p (insn)
+ || (JUMP_LABEL (insn) != 0
+ && JUMP_LABEL (insn) != scan_start
+ && (INSN_UID (JUMP_LABEL (insn)) >= max_uid_for_loop
+ || INSN_UID (insn) >= max_uid_for_loop
+ || (INSN_LUID (JUMP_LABEL (insn))
+ < INSN_LUID (insn))))))
+ {
+ maybe_multiple = 1;
+ break;
+ }
+ }
+ }
+
/* Past a jump, we get to insns for which we can't count
on whether they will be executed during each iteration. */
/* This code appears twice in strength_reduce. There is also similar
@@ -5224,13 +5271,15 @@ valid_initial_value_p (x, insn, call_seen, loop_start)
/* Scan X for memory refs and check each memory address
as a possible giv. INSN is the insn whose pattern X comes from.
NOT_EVERY_ITERATION is 1 if the insn might not be executed during
- every loop iteration. */
+ every loop iteration. MAYBE_MULTIPLE is 1 if the insn might be executed
+ more thanonce in each loop iteration. */
static void
-find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
+find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
+ loop_end)
rtx x;
rtx insn;
- int not_every_iteration;
+ int not_every_iteration, maybe_multiple;
rtx loop_start, loop_end;
{
register int i, j;
@@ -5278,7 +5327,7 @@ find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
record_giv (v, insn, src_reg, addr_placeholder, mult_val,
add_val, benefit, DEST_ADDR, not_every_iteration,
- &XEXP (x, 0), loop_start, loop_end);
+ maybe_multiple, &XEXP (x, 0), loop_start, loop_end);
v->mem_mode = GET_MODE (x);
}
@@ -5294,12 +5343,12 @@ find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
- find_mem_givs (XEXP (x, i), insn, not_every_iteration, loop_start,
- loop_end);
+ find_mem_givs (XEXP (x, i), insn, not_every_iteration, maybe_multiple,
+ loop_start, loop_end);
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
find_mem_givs (XVECEXP (x, i, j), insn, not_every_iteration,
- loop_start, loop_end);
+ maybe_multiple, loop_start, loop_end);
}
/* Fill in the data about one biv update.
@@ -5421,7 +5470,8 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
static void
record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
- type, not_every_iteration, location, loop_start, loop_end)
+ type, not_every_iteration, maybe_multiple, location, loop_start,
+ loop_end)
struct induction *v;
rtx insn;
rtx src_reg;
@@ -5429,7 +5479,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
rtx mult_val, add_val;
int benefit;
enum g_types type;
- int not_every_iteration;
+ int not_every_iteration, maybe_multiple;
rtx *location;
rtx loop_start, loop_end;
{
@@ -5447,7 +5497,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
v->location = location;
v->cant_derive = 0;
v->combined_with = 0;
- v->maybe_multiple = 0;
+ v->maybe_multiple = maybe_multiple;
v->maybe_dead = 0;
v->derive_adjustment = 0;
v->same = 0;
@@ -5882,9 +5932,10 @@ update_giv_derive (p)
&dummy);
if (tem && giv->derive_adjustment)
- tem = simplify_giv_expr (gen_rtx_PLUS (giv->mode, tem,
- giv->derive_adjustment),
- &dummy);
+ tem = simplify_giv_expr
+ (gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment),
+ &dummy);
+
if (tem)
giv->derive_adjustment = tem;
else
@@ -6274,10 +6325,13 @@ simplify_giv_expr (x, benefit)
case PLUS:
/* (a + invar_1) + invar_2. Associate. */
- return simplify_giv_expr (
- gen_rtx_PLUS (mode, XEXP (arg0, 0),
- gen_rtx_PLUS (mode, XEXP (arg0, 1), arg1)),
- benefit);
+ return
+ simplify_giv_expr (gen_rtx_PLUS (mode,
+ XEXP (arg0, 0),
+ gen_rtx_PLUS (mode,
+ XEXP (arg0, 1),
+ arg1)),
+ benefit);
default:
abort ();
@@ -6297,11 +6351,12 @@ simplify_giv_expr (x, benefit)
tem = arg0, arg0 = arg1, arg1 = tem;
if (GET_CODE (arg1) == PLUS)
- return simplify_giv_expr (gen_rtx_PLUS (mode,
- gen_rtx_PLUS (mode, arg0,
- XEXP (arg1, 0)),
- XEXP (arg1, 1)),
- benefit);
+ return
+ simplify_giv_expr (gen_rtx_PLUS (mode,
+ gen_rtx_PLUS (mode, arg0,
+ XEXP (arg1, 0)),
+ XEXP (arg1, 1)),
+ benefit);
/* Now must have MULT + MULT. Distribute if same biv, else not giv. */
if (GET_CODE (arg0) != MULT || GET_CODE (arg1) != MULT)
@@ -6321,7 +6376,8 @@ simplify_giv_expr (x, benefit)
/* Handle "a - b" as "a + b * (-1)". */
return simplify_giv_expr (gen_rtx_PLUS (mode,
XEXP (x, 0),
- gen_rtx_MULT (mode, XEXP (x, 1),
+ gen_rtx_MULT (mode,
+ XEXP (x, 1),
constm1_rtx)),
benefit);
@@ -6380,7 +6436,8 @@ simplify_giv_expr (x, benefit)
case MULT:
/* (a * invar_1) * invar_2. Associate. */
- return simplify_giv_expr (gen_rtx_MULT (mode, XEXP (arg0, 0),
+ return simplify_giv_expr (gen_rtx_MULT (mode,
+ XEXP (arg0, 0),
gen_rtx_MULT (mode,
XEXP (arg0, 1),
arg1)),
@@ -6406,11 +6463,12 @@ simplify_giv_expr (x, benefit)
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return 0;
- return simplify_giv_expr (gen_rtx_MULT (mode,
- XEXP (x, 0),
- GEN_INT ((HOST_WIDE_INT) 1
- << INTVAL (XEXP (x, 1)))),
- benefit);
+ return
+ simplify_giv_expr (gen_rtx_MULT (mode,
+ XEXP (x, 0),
+ GEN_INT ((HOST_WIDE_INT) 1
+ << INTVAL (XEXP (x, 1)))),
+ benefit);
case NEG:
/* "-a" is "a * (-1)" */
@@ -6448,9 +6506,10 @@ simplify_giv_expr (x, benefit)
if (v->cant_derive)
return 0;
- tem = gen_rtx_PLUS (mode, gen_rtx_MULT (mode, v->src_reg,
- v->mult_val),
- v->add_val);
+ tem = gen_rtx_PLUS (mode, gen_rtx_MULT (mode,
+ v->src_reg, v->mult_val),
+ v->add_val);
+
if (v->derive_adjustment)
tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment);
return simplify_giv_expr (tem, benefit);