aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2000-07-28 10:46:18 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-07-28 10:46:18 -0700
commit4b983fdc50c590dde021fae533d8c3745897fdae (patch)
treec6bbf69024ca51b064647b9762f5100f294e8b2b /gcc/reload.c
parent777ba8d110978fc69481e5f50ebcca1fd39a8542 (diff)
downloadgcc-4b983fdc50c590dde021fae533d8c3745897fdae.zip
gcc-4b983fdc50c590dde021fae533d8c3745897fdae.tar.gz
gcc-4b983fdc50c590dde021fae533d8c3745897fdae.tar.bz2
cse.c (canon_hash): Handle PRE_MODIFY/POST_MODIFY.
* cse.c (canon_hash): Handle PRE_MODIFY/POST_MODIFY. (cse_insn): Likewise. (addr_affects_sp_p): Likewise. * expr.c (move_by_pieces): Likewise. (clear_by_pieces): Likewise. * gcse.c (oprs_unchanged_p): Likewise. * haifa-sched.c (sched_analyze_2): Likewise. * recog.c (offsettable_address_p): Likewise. * regclass.c (record_address_regs): Likewise. * reload.c (find_reusable_reload): Likewise. (push_reload): Likewise. (operands_match_p): Likewise. (decompose): Likewise. (find_reloads_address_1): Likewise. (find_inc_amount): Likewise. * reload1.c (elimination_effects): Likewise. * resource.c (mark_set_resources): Likewise. * flow.c (attempt_auto_inc): New function; mostly broken out of find_auto_inc. (find_auto_inc): Split into two functions and enhanced to generate POST_MODIFY. * rtl.def (PRE_MODIFY, POST_MODIFY): Adjust comment. * rtl.h (count_all_occurrences): Declare. (HAVE_{PRE,POST}_MODIFY_{DISP,REG}): Provide default of 0 if not defined. * rtlanal.c (count_all_occurrences): New function. * tm.texi (HAVE_POST_MODIFY_DISP, HAVE_PRE_MODIFY_DISP, HAVE_POST_MODIFY_REG, HAVE_PRE_MODIFY_REG): Document. * config/ia64/ia64-protos.h (destination_operand): Declare. * config/ia64/ia64.c (destination_operand): New function. (ia64_print_operand): Handle POST_MODIFY. (rtx_needs_barrier): Likewise. * config/ia64/ia64.h (HAVE_POST_MODIFY_DISP): Define to 1. (HAVE_POST_MODIFY_REG): Define to 1. (MAX_REGS_PER_ADDRESS): Change to 2. (GO_IF_LEGITIMATE_ADDRESS): Accept POST_MODIFY too. (LEGITIMATE_ADDRESS_REG): New helper macro. (LEGITIMATE_ADDRESS_DISP): Likewise. (PREDICATE_CODES): Add entry for destination_operand. * config/ia64/ia64.md (all mov patterns): Use destination_operand predicate for operand 0. From-SVN: r35321
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c134
1 files changed, 118 insertions, 16 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index d519708..01286ba 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -748,18 +748,11 @@ find_reusable_reload (p_in, out, class, type, opnum, dont_share)
true_regnum (rld[i].reg_rtx)))
&& out == 0 && rld[i].out == 0 && rld[i].in != 0
&& ((GET_CODE (in) == REG
- && (GET_CODE (rld[i].in) == POST_INC
- || GET_CODE (rld[i].in) == POST_DEC
- || GET_CODE (rld[i].in) == PRE_INC
- || GET_CODE (rld[i].in) == PRE_DEC)
+ && GET_RTX_CLASS (GET_CODE (rld[i].in)) == 'a'
&& MATCHES (XEXP (rld[i].in, 0), in))
- ||
- (GET_CODE (rld[i].in) == REG
- && (GET_CODE (in) == POST_INC
- || GET_CODE (in) == POST_DEC
- || GET_CODE (in) == PRE_INC
- || GET_CODE (in) == PRE_DEC)
- && MATCHES (XEXP (in, 0), rld[i].in)))
+ || (GET_CODE (rld[i].in) == REG
+ && GET_RTX_CLASS (GET_CODE (in)) == 'a'
+ && MATCHES (XEXP (in, 0), rld[i].in)))
&& (rld[i].out == 0 || ! earlyclobber_operand_p (rld[i].out))
&& (reg_class_size[(int) class] == 1 || SMALL_REGISTER_CLASSES)
&& MERGABLE_RELOADS (type, rld[i].when_needed,
@@ -865,7 +858,8 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && out != 0 && GET_CODE (in) == MEM && rtx_equal_p (in, out))
{
if (GET_CODE (XEXP (in, 0)) == POST_INC
- || GET_CODE (XEXP (in, 0)) == POST_DEC)
+ || GET_CODE (XEXP (in, 0)) == POST_DEC
+ || GET_CODE (XEXP (in, 0)) == POST_MODIFY)
{
rtx new = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0));
@@ -873,7 +867,8 @@ push_reload (in, out, inloc, outloc, class,
in = new;
}
if (GET_CODE (XEXP (in, 0)) == PRE_INC
- || GET_CODE (XEXP (in, 0)) == PRE_DEC)
+ || GET_CODE (XEXP (in, 0)) == PRE_DEC
+ || GET_CODE (XEXP (in, 0)) == PRE_MODIFY)
{
rtx new = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0));
@@ -2052,7 +2047,7 @@ operands_match_p (x, y)
because the assembler insn would increment only once.
On the other hand, an postincrement matches ordinary indexing
if the postincrement is the output operand. */
- if (code == POST_DEC || code == POST_INC)
+ if (code == POST_DEC || code == POST_INC || code == POST_MODIFY)
return operands_match_p (XEXP (x, 0), y);
/* Two preincrements are invalid
because the assembler insn would increment only once.
@@ -2060,7 +2055,8 @@ operands_match_p (x, y)
if the preincrement is the input operand.
In this case, return 2, since some callers need to do special
things when this happens. */
- if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC)
+ if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC
+ || GET_CODE (y) == PRE_MODIFY)
return operands_match_p (x, XEXP (y, 0)) ? 2 : 0;
slow:
@@ -2168,6 +2164,20 @@ decompose (x)
return val;
}
+ if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
+ {
+ if (GET_CODE (XEXP (addr, 1)) == PLUS
+ && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+ && CONSTANT_P (XEXP (XEXP (addr, 1), 1)))
+ {
+ val.base = XEXP (addr, 0);
+ val.start = -INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.end = INTVAL (XEXP (XEXP (addr, 1), 1));
+ val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
+ return val;
+ }
+ }
+
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
@@ -5095,6 +5105,86 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
return 0;
+ case POST_MODIFY:
+ case PRE_MODIFY:
+ {
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
+ return 0;
+
+ /* Currently, we only support {PRE,POST}_MODIFY constructs
+ where a base register is {inc,dec}remented by the contents
+ of another register or by a constant value. Thus, these
+ operands must match. */
+ if (op0 != XEXP (op1, 0))
+ abort();
+
+ /* Require index register (or constant). Let's just handle the
+ register case in the meantime... If the target allows
+ auto-modify by a constant then we could try replacing a pseudo
+ register with its equivalent constant where applicable. */
+ if (REG_P (XEXP (op1, 1)))
+ if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
+ find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
+ opnum, type, ind_levels, insn);
+
+ if (REG_P (XEXP (op1, 0)))
+ {
+ register int regno = REGNO (XEXP (op1, 0));
+
+ /* A register that is incremented cannot be constant! */
+ if (regno >= FIRST_PSEUDO_REGISTER
+ && reg_equiv_constant[regno] != 0)
+ abort ();
+
+ /* Handle a register that is equivalent to a memory location
+ which cannot be addressed directly. */
+ if (reg_equiv_memory_loc[regno] != 0
+ && (reg_equiv_address[regno] != 0
+ || num_not_at_initial_offset))
+ {
+ rtx tem = make_memloc (XEXP (x, 0), regno);
+
+ if (reg_equiv_address[regno]
+ || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+ {
+ /* First reload the memory location's address.
+ We can't use ADDR_TYPE (type) here, because we need to
+ write back the value after reading it, hence we actually
+ need two registers. */
+ find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum, type,
+ ind_levels, insn);
+
+ /* Then reload the memory location into a base
+ register. */
+ push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0),
+ BASE_REG_CLASS, GET_MODE (x), GET_MODE (x),
+ 0, 0, opnum, RELOAD_OTHER);
+ break;
+ }
+ }
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
+ /* We require a base register here... */
+ if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
+ {
+ push_reload (XEXP (op1, 0), XEXP (x, 0),
+ &XEXP (op1, 0), &XEXP (x, 0),
+ BASE_REG_CLASS,
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
+ }
+ }
+ else
+ abort();
+ }
+ return 0;
+
case POST_INC:
case POST_DEC:
case PRE_INC:
@@ -5988,6 +6078,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
case PRE_INC:
case POST_DEC:
case PRE_DEC:
+ case POST_MODIFY:
+ case PRE_MODIFY:
return 0;
default:
break;
@@ -6407,7 +6499,17 @@ find_inc_amount (x, inced)
|| GET_CODE (addr) == POST_INC)
&& XEXP (addr, 0) == inced)
return GET_MODE_SIZE (GET_MODE (x));
- }
+ else if ((GET_CODE (addr) == PRE_MODIFY
+ || GET_CODE (addr) == POST_MODIFY)
+ && GET_CODE (XEXP (addr, 1)) == PLUS
+ && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
+ && XEXP (addr, 0) == inced
+ && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+ {
+ i = INTVAL (XEXP (XEXP (addr, 1), 1));
+ return i < 0 ? -i : i;
+ }
+ }
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)