This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[cft/reload] maybe fix target/14532
- From: Richard Henderson <rth at redhat dot com>
- To: jakub at gcc dot gnu dot org <gcc-bugzilla at gcc dot gnu dot org>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 15 Mar 2004 20:53:14 -0800
- Subject: [cft/reload] maybe fix target/14532
- References: <20040311125714.14532.jakub@gcc.gnu.org> <20040312125346.16968.qmail@sources.redhat.com>
I don't see how calling find_reloads_address_1 on CONSTs would do anything.
How would we determine what we can or cannot do? I think better would be
to not create this kind of rtl in the first place.
The following appears to work on the given test case, but probably needs a
bit o testing to figure out if it's safe or not.
r~
* reload.c (find_reloads_subreg_address): When applying an offset
to a non-offsettable address, force the original into a register.
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.229.4.5
diff -u -p -r1.229.4.5 reload.c
--- reload.c 10 Mar 2004 01:51:01 -0000 1.229.4.5
+++ reload.c 16 Mar 2004 04:46:48 -0000
@@ -5847,8 +5847,10 @@ find_reloads_subreg_address (rtx x, int
if (force_replace
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
- unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
+ enum machine_mode mode = GET_MODE (x);
+ unsigned outer_size = GET_MODE_SIZE (mode);
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
+ rtx orig_addr, new_addr;
int offset;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
@@ -5858,17 +5860,16 @@ find_reloads_subreg_address (rtx x, int
else
offset = SUBREG_BYTE (x);
- XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
- PUT_MODE (tem, GET_MODE (x));
-
+ /* Calculate the new address, but don't install it yet. */
+ orig_addr = XEXP (tem, 0);
+ new_addr = plus_constant (orig_addr, offset);
+
/* If this was a paradoxical subreg that we replaced, the
resulting memory must be sufficiently aligned to allow
us to widen the mode of the memory. */
if (outer_size > inner_size && STRICT_ALIGNMENT)
{
- rtx base;
-
- base = XEXP (tem, 0);
+ rtx base = new_addr;
if (GET_CODE (base) == PLUS)
{
if (GET_CODE (XEXP (base, 1)) == CONST_INT
@@ -5882,9 +5883,31 @@ find_reloads_subreg_address (rtx x, int
return x;
}
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
- ind_levels, insn);
+ /* If the original address is offsettable, then go ahead and
+ use the offset address we computed earlier. If it isn't,
+ then we have to work harder in order to avoid creating
+ something (involving const and unspec) that we can't fix. */
+ if (offsettable_memref_p (tem))
+ {
+ XEXP (tem, 0) = new_addr;
+ PUT_MODE (tem, mode);
+
+ find_reloads_address (mode, &tem, new_addr,
+ &XEXP (tem, 0), opnum,
+ ADDR_TYPE (type), ind_levels, insn);
+ }
+ else
+ {
+ new_addr = gen_rtx_PLUS (Pmode, orig_addr, GEN_INT (offset));
+ XEXP (tem, 0) = new_addr;
+ PUT_MODE (tem, mode);
+
+ find_reloads_address_part (XEXP (new_addr, 0),
+ &XEXP (new_addr, 0),
+ MODE_BASE_REG_CLASS (mode),
+ Pmode, opnum, ADDR_TYPE (type),
+ ind_levels);
+ }
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so