aboutsummaryrefslogtreecommitdiff
path: root/gcc/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/loop.c')
-rw-r--r--gcc/loop.c268
1 files changed, 165 insertions, 103 deletions
diff --git a/gcc/loop.c b/gcc/loop.c
index 87d5ccf532e..4d27b8a7ee9 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
while to do these things. */
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "rtl.h"
#include "obstack.h"
#include "expr.h"
@@ -305,9 +305,9 @@ void
init_loop ()
{
char *free_point = (char *) oballoc (1);
- rtx reg = gen_rtx (REG, word_mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
- add_cost = rtx_cost (gen_rtx (PLUS, word_mode, reg, reg), SET);
+ add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
/* We multiply by 2 to reconcile the difference in scale between
these two ways of computing costs. Otherwise the cost of a copy
@@ -1008,7 +1008,7 @@ record_excess_regs (in_this, not_in_this, output)
case REG:
if (REGNO (in_this) >= FIRST_PSEUDO_REGISTER
&& ! reg_mentioned_p (in_this, not_in_this))
- *output = gen_rtx (EXPR_LIST, VOIDmode, in_this, *output);
+ *output = gen_rtx_EXPR_LIST (VOIDmode, in_this, *output);
return;
default:
@@ -1515,8 +1515,8 @@ add_label_notes (x, insns)
{
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (reg_mentioned_p (XEXP (x, 0), insn))
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, XEXP (x, 0),
- REG_NOTES (insn));
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL, XEXP (x, 0),
+ REG_NOTES (insn));
}
return;
}
@@ -1667,9 +1667,10 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
REG_NOTES (i1) = REG_NOTES (m->insn);
r1 = SET_DEST (PATTERN (m->insn));
r2 = SET_DEST (PATTERN (m1->insn));
- regs_may_share = gen_rtx (EXPR_LIST, VOIDmode, r1,
- gen_rtx (EXPR_LIST, VOIDmode, r2,
- regs_may_share));
+ regs_may_share
+ = gen_rtx_EXPR_LIST (VOIDmode, r1,
+ gen_rtx_EXPR_LIST (VOIDmode, r2,
+ regs_may_share));
delete_insn (m->insn);
if (new_start == 0)
@@ -1719,9 +1720,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
i1 = emit_insns_before (temp, loop_start);
if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
REG_NOTES (i1)
- = gen_rtx (EXPR_LIST,
- m->is_equiv ? REG_EQUIV : REG_EQUAL,
- m->set_src, REG_NOTES (i1));
+ = gen_rtx_EXPR_LIST (m->is_equiv ? REG_EQUIV : REG_EQUAL,
+ m->set_src, REG_NOTES (i1));
if (loop_dump_stream)
fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
@@ -1887,13 +1887,16 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
/* This isn't needed because REG_NOTES is copied
below and is wrong since P might be a PARALLEL. */
if (REG_NOTES (i1) == 0
- && ! m->partial /* But not if it's a zero-extend clr. */
+ && ! m->partial /* But not if it's a zero-extend
+ clear. */
&& ! m->global /* and not if used outside the loop
- (since it might get set outside). */
+ (since it might get set
+ outside). */
&& CONSTANT_P (SET_SRC (PATTERN (p))))
REG_NOTES (i1)
- = gen_rtx (EXPR_LIST, REG_EQUAL,
- SET_SRC (PATTERN (p)), REG_NOTES (i1));
+ = gen_rtx_EXPR_LIST (REG_EQUAL,
+ SET_SRC (PATTERN (p)),
+ REG_NOTES (i1));
#endif
/* If library call, now fix the REG_NOTES that contain
@@ -2142,12 +2145,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)
@@ -2155,9 +2161,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. */
@@ -3535,8 +3540,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
if (GET_CODE (test) == NE)
{
bl->init_insn = p;
- bl->init_set = gen_rtx (SET, VOIDmode,
- XEXP (test, 0), XEXP (test, 1));
+ bl->init_set = gen_rtx_SET (VOIDmode,
+ XEXP (test, 0), XEXP (test, 1));
}
else
bl->initial_test = test;
@@ -3603,6 +3608,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)
{
@@ -3683,8 +3689,8 @@ strength_reduce (scan_start, end, loop_top, insn_count,
}
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);
}
}
@@ -3694,8 +3700,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
@@ -3704,6 +3710,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
@@ -4331,13 +4380,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;
@@ -4384,7 +4435,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);
}
@@ -4400,12 +4451,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.
@@ -4522,7 +4573,8 @@ record_biv (v, insn, dest_reg, inc_val, mult_val,
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;
@@ -4530,7 +4582,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;
{
@@ -4549,7 +4601,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;
@@ -4946,15 +4998,16 @@ update_giv_derive (p)
tem = 0;
if (biv->mult_val == const1_rtx)
- tem = simplify_giv_expr (gen_rtx (MULT, giv->mode,
- biv->add_val,
- giv->mult_val),
+ tem = simplify_giv_expr (gen_rtx_MULT (giv->mode,
+ biv->add_val,
+ giv->mult_val),
&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
@@ -5292,7 +5345,7 @@ simplify_giv_expr (x, benefit)
{
tem = plus_constant (arg0, INTVAL (arg1));
if (GET_CODE (tem) != CONST_INT)
- tem = gen_rtx (USE, mode, tem);
+ tem = gen_rtx_USE (mode, tem);
}
return tem;
@@ -5300,15 +5353,17 @@ simplify_giv_expr (x, benefit)
case REG:
case MULT:
/* biv + invar or mult + invar. Return sum. */
- return gen_rtx (PLUS, mode, arg0, arg1);
+ return gen_rtx_PLUS (mode, arg0, arg1);
case PLUS:
/* (a + invar_1) + invar_2. Associate. */
- return simplify_giv_expr (gen_rtx (PLUS, mode,
+ return
+ simplify_giv_expr (gen_rtx_PLUS (mode,
XEXP (arg0, 0),
- gen_rtx (PLUS, mode,
- XEXP (arg0, 1), arg1)),
- benefit);
+ gen_rtx_PLUS (mode,
+ XEXP (arg0, 1),
+ arg1)),
+ benefit);
default:
abort ();
@@ -5317,9 +5372,9 @@ simplify_giv_expr (x, benefit)
/* Each argument must be either REG, PLUS, or MULT. Convert REG to
MULT to reduce cases. */
if (GET_CODE (arg0) == REG)
- arg0 = gen_rtx (MULT, mode, arg0, const1_rtx);
+ arg0 = gen_rtx_MULT (mode, arg0, const1_rtx);
if (GET_CODE (arg1) == REG)
- arg1 = gen_rtx (MULT, mode, arg1, const1_rtx);
+ arg1 = gen_rtx_MULT (mode, arg1, const1_rtx);
/* Now have PLUS + PLUS, PLUS + MULT, MULT + PLUS, or MULT + MULT.
Put a MULT first, leaving PLUS + PLUS, MULT + PLUS, or MULT + MULT.
@@ -5328,11 +5383,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)),
+ return
+ simplify_giv_expr (gen_rtx_PLUS (mode,
+ gen_rtx_PLUS (mode, arg0,
+ XEXP (arg1, 0)),
XEXP (arg1, 1)),
- benefit);
+ benefit);
/* Now must have MULT + MULT. Distribute if same biv, else not giv. */
if (GET_CODE (arg0) != MULT || GET_CODE (arg1) != MULT)
@@ -5341,19 +5397,20 @@ simplify_giv_expr (x, benefit)
if (XEXP (arg0, 0) != XEXP (arg1, 0))
return 0;
- return simplify_giv_expr (gen_rtx (MULT, mode,
- XEXP (arg0, 0),
- gen_rtx (PLUS, mode,
- XEXP (arg0, 1),
- XEXP (arg1, 1))),
+ return simplify_giv_expr (gen_rtx_MULT (mode,
+ XEXP (arg0, 0),
+ gen_rtx_PLUS (mode,
+ XEXP (arg0, 1),
+ XEXP (arg1, 1))),
benefit);
case MINUS:
/* 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), constm1_rtx)),
+ return simplify_giv_expr (gen_rtx_PLUS (mode,
+ XEXP (x, 0),
+ gen_rtx_MULT (mode,
+ XEXP (x, 1),
+ constm1_rtx)),
benefit);
case MULT:
@@ -5382,7 +5439,7 @@ simplify_giv_expr (x, benefit)
{
case REG:
/* biv * invar. Done. */
- return gen_rtx (MULT, mode, arg0, arg1);
+ return gen_rtx_MULT (mode, arg0, arg1);
case CONST_INT:
/* Product of two constants. */
@@ -5394,19 +5451,22 @@ simplify_giv_expr (x, benefit)
case MULT:
/* (a * invar_1) * invar_2. Associate. */
- return simplify_giv_expr (gen_rtx (MULT, mode,
- XEXP (arg0, 0),
- gen_rtx (MULT, mode,
- XEXP (arg0, 1), arg1)),
+ return simplify_giv_expr (gen_rtx_MULT (mode,
+ XEXP (arg0, 0),
+ gen_rtx_MULT (mode,
+ XEXP (arg0, 1),
+ arg1)),
benefit);
case PLUS:
/* (a + invar_1) * invar_2. Distribute. */
- return simplify_giv_expr (gen_rtx (PLUS, mode,
- gen_rtx (MULT, mode,
- XEXP (arg0, 0), arg1),
- gen_rtx (MULT, mode,
- XEXP (arg0, 1), arg1)),
+ return simplify_giv_expr (gen_rtx_PLUS (mode,
+ gen_rtx_MULT (mode,
+ XEXP (arg0, 0),
+ arg1),
+ gen_rtx_MULT (mode,
+ XEXP (arg0, 1),
+ arg1)),
benefit);
default:
@@ -5418,22 +5478,23 @@ simplify_giv_expr (x, benefit)
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return 0;
- return simplify_giv_expr (gen_rtx (MULT, mode,
+ return
+ simplify_giv_expr (gen_rtx_MULT (mode,
XEXP (x, 0),
GEN_INT ((HOST_WIDE_INT) 1
<< INTVAL (XEXP (x, 1)))),
- benefit);
+ benefit);
case NEG:
/* "-a" is "a * (-1)" */
- return simplify_giv_expr (gen_rtx (MULT, mode, XEXP (x, 0), constm1_rtx),
+ return simplify_giv_expr (gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx),
benefit);
case NOT:
/* "~a" is "-a - 1". Silly, but easy. */
- return simplify_giv_expr (gen_rtx (MINUS, mode,
- gen_rtx (NEG, mode, XEXP (x, 0)),
- const1_rtx),
+ return simplify_giv_expr (gen_rtx_MINUS (mode,
+ gen_rtx_NEG (mode, XEXP (x, 0)),
+ const1_rtx),
benefit);
case USE:
@@ -5460,11 +5521,12 @@ 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);
+ tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment);
return simplify_giv_expr (tem, benefit);
}
@@ -5484,7 +5546,7 @@ simplify_giv_expr (x, benefit)
if (GET_CODE (x) == CONST_INT)
return x;
else
- return gen_rtx (USE, mode, x);
+ return gen_rtx_USE (mode, x);
}
else
return 0;
@@ -5632,12 +5694,12 @@ express_from (g1, g2)
else if (mult == const1_rtx)
mult = g1->dest_reg;
else
- mult = gen_rtx (MULT, g2->mode, g1->dest_reg, mult);
+ mult = gen_rtx_MULT (g2->mode, g1->dest_reg, mult);
if (add == const0_rtx)
return mult;
else
- return gen_rtx (PLUS, g2->mode, mult, add);
+ return gen_rtx_PLUS (g2->mode, mult, add);
}
#endif
@@ -5963,8 +6025,8 @@ check_dbra_loop (loop_end, insn_count, loop_start)
{
/* register always nonnegative, add REG_NOTE to branch */
REG_NOTES (PREV_INSN (loop_end))
- = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX,
- REG_NOTES (PREV_INSN (loop_end)));
+ = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
+ REG_NOTES (PREV_INSN (loop_end)));
bl->nonneg = 1;
return 1;
@@ -5988,8 +6050,8 @@ check_dbra_loop (loop_end, insn_count, loop_start)
&& INTVAL (bl->biv->add_val) == -1)
{
REG_NOTES (PREV_INSN (loop_end))
- = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX,
- REG_NOTES (PREV_INSN (loop_end)));
+ = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
+ REG_NOTES (PREV_INSN (loop_end)));
bl->nonneg = 1;
return 1;
@@ -6192,8 +6254,8 @@ check_dbra_loop (loop_end, insn_count, loop_start)
/* Increment of LABEL_NUSES done above. */
/* Register is now always nonnegative,
so add REG_NONNEG note to the branch. */
- REG_NOTES (tem) = gen_rtx (EXPR_LIST, REG_NONNEG, NULL_RTX,
- REG_NOTES (tem));
+ REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
+ REG_NOTES (tem));
}
bl->nonneg = 1;
@@ -6347,8 +6409,8 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
/* If the giv has the opposite direction of change,
then reverse the comparison. */
if (INTVAL (v->mult_val) < 0)
- new = gen_rtx (COMPARE, GET_MODE (v->new_reg),
- const0_rtx, v->new_reg);
+ new = gen_rtx_COMPARE (GET_MODE (v->new_reg),
+ const0_rtx, v->new_reg);
else
new = v->new_reg;
@@ -6390,11 +6452,11 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
/* If the giv has the opposite direction of change,
then reverse the comparison. */
if (INTVAL (v->mult_val) < 0)
- new = gen_rtx (COMPARE, VOIDmode, copy_rtx (v->add_val),
- v->new_reg);
+ new = gen_rtx_COMPARE (VOIDmode, copy_rtx (v->add_val),
+ v->new_reg);
else
- new = gen_rtx (COMPARE, VOIDmode, v->new_reg,
- copy_rtx (v->add_val));
+ new = gen_rtx_COMPARE (VOIDmode, v->new_reg,
+ copy_rtx (v->add_val));
/* Replace biv with the giv's reduced register. */
update_reg_last_use (v->add_val, insn);