aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1997-03-15 07:28:39 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1997-03-15 07:28:39 -0500
commit55c225655fa54b70bddbc00fc19916e8b246ad08 (patch)
treea39b801adc2b7553ca6b041443450e89049f9b09 /gcc/reload.c
parentfa1610e95b31962667db9ac4c2553227bd236c52 (diff)
downloadgcc-55c225655fa54b70bddbc00fc19916e8b246ad08.zip
gcc-55c225655fa54b70bddbc00fc19916e8b246ad08.tar.gz
gcc-55c225655fa54b70bddbc00fc19916e8b246ad08.tar.bz2
Include expr.h.
(find_reloads_address, find_reloads_address_1): New argument INSN. (find_reloads_address_1): Reload inside of p{re,ost}_{in,de}c instead of entire p{re,ost}_{in,de}c where appropriate. From-SVN: r13706
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c148
1 files changed, 95 insertions, 53 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index 40ab588..802ede6 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -99,6 +99,7 @@ a register with any other reload. */
#include "flags.h"
#include "real.h"
#include "output.h"
+#include "expr.h"
#ifndef REGISTER_MOVE_COST
#define REGISTER_MOVE_COST(x, y) 2
@@ -325,11 +326,11 @@ static int alternative_allows_memconst PROTO((char *, int));
static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int));
static rtx make_memloc PROTO((rtx, int));
static int find_reloads_address PROTO((enum machine_mode, rtx *, rtx, rtx *,
- int, enum reload_type, int));
+ int, enum reload_type, int, rtx));
static rtx subst_reg_equivs PROTO((rtx));
static rtx subst_indexed_address PROTO((rtx));
static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
- int, enum reload_type,int));
+ int, enum reload_type,int, rtx));
static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
enum machine_mode, int,
enum reload_type, int));
@@ -693,7 +694,7 @@ get_secondary_mem (x, mode, opnum, type)
: RELOAD_OTHER);
find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0),
- opnum, type, 0);
+ opnum, type, 0, 0);
}
secondary_memlocs_elim[(int) mode][opnum] = loc;
@@ -2538,7 +2539,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
- i, operand_type[i], ind_levels);
+ i, operand_type[i], ind_levels, insn);
/* If we now have a simple operand where we used to have a
PLUS or MULT, re-recognize and try again. */
@@ -2561,7 +2562,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_operand_loc[i],
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
- i, address_type[i], ind_levels))
+ i, address_type[i], ind_levels, insn))
address_reloaded[i] = 1;
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
@@ -2629,7 +2630,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_operand_loc[i],
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
- i, address_type[i], ind_levels);
+ i, address_type[i], ind_levels, insn);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
}
@@ -3950,7 +3951,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (insn_operand_address_p[insn_code_number][i])
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
- i, RELOAD_FOR_INPUT, ind_levels);
+ i, RELOAD_FOR_INPUT, ind_levels, insn);
/* In these cases, we can't tell if the operand is an input
or an output, so be conservative. In practice it won't be
@@ -3961,7 +3962,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_operand_loc[i],
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
- i, RELOAD_OTHER, ind_levels);
+ i, RELOAD_OTHER, ind_levels, insn);
if (code == SUBREG)
recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, RELOAD_OTHER,
@@ -4067,7 +4068,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
- &XEXP (x, 0), opnum, type, ind_levels);
+ &XEXP (x, 0), opnum, type, ind_levels, 0);
}
return x;
}
@@ -4075,7 +4076,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
{
rtx tem = x;
find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
- opnum, type, ind_levels);
+ opnum, type, ind_levels, 0);
return tem;
}
@@ -4156,7 +4157,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
- &XEXP (x, 0), opnum, type, ind_levels);
+ &XEXP (x, 0), opnum, type, ind_levels, 0);
}
}
@@ -4216,6 +4217,9 @@ make_memloc (ad, regno)
IND_LEVELS says how many levels of indirect addressing this machine
supports.
+ INSN, if nonzero, is the insn in which we do the reload. It is used
+ to determine if we may generate output reloads.
+
Value is nonzero if this address is reloaded or replaced as a whole.
This is interesting to the caller if the address is an autoincrement.
@@ -4226,7 +4230,7 @@ make_memloc (ad, regno)
to a hard register, and frame pointer elimination. */
static int
-find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
+find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
enum machine_mode mode;
rtx *memrefloc;
rtx ad;
@@ -4234,6 +4238,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
int opnum;
enum reload_type type;
int ind_levels;
+ rtx insn;
{
register int regno;
rtx tem;
@@ -4258,7 +4263,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
tem = make_memloc (ad, regno);
find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
&XEXP (tem, 0), opnum, ADDR_TYPE (type),
- ind_levels);
+ ind_levels, insn);
push_reload (tem, NULL_RTX, loc, NULL_PTR,
reload_address_base_reg_class,
GET_MODE (ad), VOIDmode, 0, 0,
@@ -4334,7 +4339,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
tem = ad;
find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0),
opnum, ADDR_TYPE (type),
- ind_levels == 0 ? 0 : ind_levels - 1);
+ ind_levels == 0 ? 0 : ind_levels - 1, insn);
/* If tem was changed, then we must create a new memory reference to
hold it and store it back into memrefloc. */
@@ -4456,7 +4461,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
reload_address_base_reg_class,
GET_MODE (ad), opnum, type, ind_levels);
find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
- type, 0);
+ type, 0, insn);
return 1;
}
@@ -4481,7 +4486,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
reload_address_base_reg_class,
GET_MODE (ad), opnum, type, ind_levels);
find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
- type, 0);
+ type, 0, insn);
return 1;
}
@@ -4528,7 +4533,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
return 1;
}
- return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels);
+ return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
+ insn);
}
/* Find all pseudo regs appearing in AD
@@ -4704,6 +4710,9 @@ subst_indexed_address (addr)
IND_LEVELS says how many levels of indirect addressing are
supported at this point in the address.
+ INSN, if nonzero, is the insn in which we do the reload. It is used
+ to determine if we may generate output reloads.
+
We return nonzero if X, as a whole, is reloaded or replaced. */
/* Note that we take shortcuts assuming that no multi-reg machine mode
@@ -4713,7 +4722,7 @@ subst_indexed_address (addr)
could have addressing modes that this does not handle right. */
static int
-find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
+find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
enum machine_mode mode;
rtx x;
int context;
@@ -4721,6 +4730,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
int opnum;
enum reload_type type;
int ind_levels;
+ rtx insn;
{
register RTX_CODE code = GET_CODE (x);
@@ -4757,29 +4767,29 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
|| code0 == ZERO_EXTEND || code1 == MEM)
{
find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
}
else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
|| code1 == ZERO_EXTEND || code0 == MEM)
{
find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
}
else if (code0 == CONST_INT || code0 == CONST
|| code0 == SYMBOL_REF || code0 == LABEL_REF)
find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else if (code1 == CONST_INT || code1 == CONST
|| code1 == SYMBOL_REF || code1 == LABEL_REF)
find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else if (code0 == REG && code1 == REG)
{
@@ -4791,39 +4801,39 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
return 0;
else if (REG_MODE_OK_FOR_BASE_P (op1, mode))
find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else if (REG_MODE_OK_FOR_BASE_P (op0, mode))
find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else if (REG_OK_FOR_INDEX_P (op1))
find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else if (REG_OK_FOR_INDEX_P (op0))
find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
else
{
find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
}
}
else if (code0 == REG)
{
find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
}
else if (code1 == REG)
{
find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
- type, ind_levels);
+ type, ind_levels, insn);
}
}
@@ -4855,7 +4865,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
need two registers. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
- ind_levels);
+ ind_levels, insn);
/* Put this inside a new increment-expression. */
x = gen_rtx (GET_CODE (x), GET_MODE (x), tem);
/* Proceed to reload that, as if it contained a register. */
@@ -4879,18 +4889,50 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
{
register rtx link;
-
- int reloadnum
- = push_reload (x, NULL_RTX, loc, NULL_PTR,
- (context
- ? reload_address_index_reg_class
- : reload_address_base_reg_class),
- GET_MODE (x), GET_MODE (x), VOIDmode, 0,
- opnum, type);
- reload_inc[reloadnum]
- = find_inc_amount (PATTERN (this_insn), XEXP (x_orig, 0));
-
- value = 1;
+ int reloadnum;
+
+ /* If we can output the register afterwards, do so, this
+ saves the extra update.
+ We can do so if we have an INSN - i.e. no JUMP_INSN nor
+ CALL_INSN - and it does not set CC0.
+ But don't do this if we cannot directly address the
+ memory location, since this will make it harder to
+ reuse address reloads, and increses register pressure.
+ Also don't do this if we can probably update x directly. */
+ rtx equiv = reg_equiv_mem[regno];
+ int icode = (int) add_optab->handlers[(int) Pmode].insn_code;
+ if (insn && GET_CODE (insn) == INSN && equiv
+#ifdef HAVE_cc0
+ && ! sets_cc0_p (PATTERN (insn))
+#endif
+ && ! (icode != CODE_FOR_nothing
+ && (*insn_operand_predicate[icode][0]) (equiv, Pmode)
+ && (*insn_operand_predicate[icode][1]) (equiv, Pmode)))
+ {
+ loc = &XEXP (x, 0);
+ x = XEXP (x, 0);
+ reloadnum
+ = push_reload (x, x, loc, loc,
+ (context
+ ? reload_address_index_reg_class
+ : reload_address_base_reg_class),
+ GET_MODE (x), GET_MODE (x), VOIDmode, 0,
+ opnum, RELOAD_OTHER);
+ }
+ else
+ {
+ reloadnum
+ = push_reload (x, NULL_RTX, loc, NULL_PTR,
+ (context
+ ? reload_address_index_reg_class
+ : reload_address_base_reg_class),
+ GET_MODE (x), GET_MODE (x), VOIDmode, 0,
+ opnum, type);
+ reload_inc[reloadnum]
+ = find_inc_amount (PATTERN (this_insn), XEXP (x_orig, 0));
+
+ value = 1;
+ }
#ifdef AUTO_INC_DEC
/* Update the REG_INC notes. */
@@ -4926,7 +4968,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
need two registers. */
find_reloads_address (GET_MODE (x), &XEXP (x, 0),
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
- opnum, type, ind_levels);
+ opnum, type, ind_levels, insn);
reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
(context
@@ -4958,7 +5000,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
reload1.c here. */
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
- opnum, ADDR_TYPE (type), ind_levels);
+ opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, NULL_PTR,
(context ? reload_address_index_reg_class
: reload_address_base_reg_class),
@@ -4996,7 +5038,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
{
x = make_memloc (x, regno);
find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
- opnum, ADDR_TYPE (type), ind_levels);
+ opnum, ADDR_TYPE (type), ind_levels, insn);
}
if (reg_renumber[regno] >= 0)
@@ -5078,7 +5120,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels)
{
if (fmt[i] == 'e')
find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i),
- opnum, type, ind_levels);
+ opnum, type, ind_levels, insn);
}
}
@@ -5116,7 +5158,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
{
rtx tem = x = force_const_mem (mode, x);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
- opnum, type, ind_levels);
+ opnum, type, ind_levels, 0);
}
else if (GET_CODE (x) == PLUS
@@ -5128,7 +5170,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
x = gen_rtx (PLUS, GET_MODE (x), XEXP (x, 0), tem);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
- opnum, type, ind_levels);
+ opnum, type, ind_levels, 0);
}
push_reload (x, NULL_RTX, loc, NULL_PTR, class,