Commit 3f1e3e70 by Alexandre Oliva Committed by Alexandre Oliva

re PR target/28146 (-O2 produces invalid code on s390-linux-gnu: gcc-4.1.2 20060608)

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.

From-SVN: r116215
parent d3b30e42
2006-08-17 Alexandre Oliva <aoliva@redhat.com>
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.
2006-08-17 Maxim Kuvyrkov <mkuvyrkov@ispras.ru>
PR rtl-optimization/28489
......
......@@ -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
......
......@@ -161,6 +161,7 @@ extern rtx *reg_equiv_invariant;
extern rtx *reg_equiv_memory_loc;
extern rtx *reg_equiv_address;
extern rtx *reg_equiv_mem;
extern rtx *reg_equiv_alt_mem_list;
/* Element N is the list of insns that initialized reg N from its equivalent
constant or memory slot. */
......
......@@ -123,6 +123,10 @@ rtx *reg_equiv_address;
or zero if pseudo reg N is not equivalent to a memory slot. */
rtx *reg_equiv_mem;
/* Element N is an EXPR_LIST of REG_EQUIVs containing MEMs with
alternate representations of the location of pseudo reg N. */
rtx *reg_equiv_alt_mem_list;
/* Widest width in which each pseudo reg is referred to (via subreg). */
static unsigned int *reg_max_ref_width;
......@@ -703,6 +707,7 @@ reload (rtx first, int global)
reg_equiv_constant = XCNEWVEC (rtx, max_regno);
reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
reg_equiv_mem = XCNEWVEC (rtx, max_regno);
reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
reg_equiv_address = XCNEWVEC (rtx, max_regno);
reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
reg_old_renumber = XCNEWVEC (short, max_regno);
......@@ -1260,6 +1265,11 @@ reload (rtx first, int global)
if (offsets_at)
free (offsets_at);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (reg_equiv_alt_mem_list[i])
free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
free (reg_equiv_alt_mem_list);
free (reg_equiv_mem);
reg_equiv_init = 0;
free (reg_equiv_address);
......@@ -7849,6 +7859,11 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
n_occurrences += count_occurrences (PATTERN (insn),
eliminate_regs (substed, 0,
NULL_RTX), 0);
for (i1 = reg_equiv_alt_mem_list [REGNO (reg)]; i1; i1 = XEXP (i1, 1))
{
gcc_assert (!rtx_equal_p (XEXP (i1, 0), substed));
n_occurrences += count_occurrences (PATTERN (insn), XEXP (i1, 0), 0);
}
if (n_occurrences > n_inherited)
return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment