diff options
author | Alexandre Oliva <aoliva@redhat.com> | 2006-08-17 08:55:02 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2006-08-17 08:55:02 +0000 |
commit | 3f1e3e7010cf18ef218f107015b8f66fc75ed4d9 (patch) | |
tree | 5846cb80d97c878963127f9d3c488c23dfc9286c /gcc/reload.c | |
parent | d3b30e42b73d0a369046e53fcdbe69517c0195be (diff) | |
download | gcc-3f1e3e7010cf18ef218f107015b8f66fc75ed4d9.zip gcc-3f1e3e7010cf18ef218f107015b8f66fc75ed4d9.tar.gz gcc-3f1e3e7010cf18ef218f107015b8f66fc75ed4d9.tar.bz2 |
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
Diffstat (limited to 'gcc/reload.c')
-rw-r--r-- | gcc/reload.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/gcc/reload.c b/gcc/reload.c index c8c48b1..e1a4abc 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 |