aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2006-08-17 08:55:02 +0000
committerAlexandre Oliva <aoliva@redhat.com>2006-08-17 08:55:02 +0000
commitf261f20031436ce079d4196be9a33c90430a8609 (patch)
tree5846cb80d97c878963127f9d3c488c23dfc9286c /gcc/reload.c
parent6de6a9efe8c512a0ddff11f6ab2b66ed9b2e94a5 (diff)
PR target/28146
* reload.h (reg_equiv_alt_mem_list): New declaration. * reload1.c (reg_equiv_alt_mem_list): New definition. (reload): Initialize it and release it. (delete_output_reload): Use it. * reload.c (push_reg_equiv_alt_mem): New function. (find_reloads_toplev): Call it. (find_reloads_address, find_reloads_address_1): Likewise. (find_reloads_subreg_address): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@116215 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index c8c48b1dc78..e1a4abc6953 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -283,6 +283,23 @@ static int find_inc_amount (rtx, rtx);
static int refers_to_mem_for_reload_p (rtx);
static int refers_to_regno_for_reload_p (unsigned int, unsigned int,
rtx, rtx *);
+
+/* Add NEW to reg_equiv_alt_mem_list[REGNO] if it's not present in the
+ list yet. */
+
+static void
+push_reg_equiv_alt_mem (int regno, rtx mem)
+{
+ rtx it;
+
+ for (it = reg_equiv_alt_mem_list [regno]; it; it = XEXP (it, 1))
+ if (rtx_equal_p (XEXP (it, 0), mem))
+ return;
+
+ reg_equiv_alt_mem_list [regno]
+ = alloc_EXPR_LIST (REG_EQUIV, mem,
+ reg_equiv_alt_mem_list [regno]);
+}
/* Determine if any secondary reloads are needed for loading (if IN_P is
nonzero) or storing (if IN_P is zero) X to or from a reload register of
@@ -4553,6 +4570,8 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
x = mem;
i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels, insn);
+ if (x != mem)
+ push_reg_equiv_alt_mem (regno, x);
if (address_reloaded)
*address_reloaded = i;
}
@@ -4761,9 +4780,13 @@ find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
+ rtx orig = tem;
+
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
ADDR_TYPE (type), ind_levels, insn);
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
}
/* We can avoid a reload if the register's equivalent memory
expression is valid as an indirect memory address.
@@ -5545,6 +5568,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_equiv_address[regno]
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
+ rtx orig = tem;
+
/* 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
@@ -5554,6 +5579,9 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
RELOAD_OTHER,
ind_levels, insn);
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
+
/* Then reload the memory location into a base
register. */
reloadnum = push_reload (tem, tem, &XEXP (x, 0),
@@ -5609,6 +5637,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
if (reg_equiv_address[regno]
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
+ rtx orig = tem;
+
/* 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
@@ -5616,6 +5646,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
ind_levels, insn);
+ if (tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
/* Put this inside a new increment-expression. */
x = gen_rtx_fmt_e (GET_CODE (x), GET_MODE (x), tem);
/* Proceed to reload that, as if it contained a register. */
@@ -5806,6 +5838,8 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
find_reloads_address (GET_MODE (x), &x, XEXP (x, 0),
&XEXP (x, 0), opnum, ADDR_TYPE (type),
ind_levels, insn);
+ if (x != tem)
+ push_reg_equiv_alt_mem (regno, x);
}
}
@@ -5993,6 +6027,7 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
+ rtx orig = tem;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
hold the correct (negative) byte offset. */
@@ -6028,6 +6063,9 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
ind_levels, insn);
+ /* ??? Do we need to handle nonzero offsets somehow? */
+ if (!offset && tem != orig)
+ push_reg_equiv_alt_mem (regno, tem);
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so