diff options
author | Richard Henderson <rth@redhat.com> | 2001-01-24 15:50:56 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-01-24 15:50:56 -0800 |
commit | 0a28aef93e6edbd2a0858840e3856ce4e0b4037b (patch) | |
tree | b56353a0eed78434279ea535f0b49194fb4a6e06 /gcc/reload.c | |
parent | bf5582ec663dce078a2baebe444e0a656ab1ee60 (diff) | |
download | gcc-0a28aef93e6edbd2a0858840e3856ce4e0b4037b.zip gcc-0a28aef93e6edbd2a0858840e3856ce4e0b4037b.tar.gz gcc-0a28aef93e6edbd2a0858840e3856ce4e0b4037b.tar.bz2 |
reload.c (find_reloads_subreg_address): Fail the substitution if the resulting address is insufficiently aligned.
* reload.c (find_reloads_subreg_address): Fail the substitution
if the resulting address is insufficiently aligned.
From-SVN: r39250
Diffstat (limited to 'gcc/reload.c')
-rw-r--r-- | gcc/reload.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/gcc/reload.c b/gcc/reload.c index 533c28c9..5f27744 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -5648,21 +5648,42 @@ find_reloads_subreg_address (x, force_replace, opnum, type, || ! rtx_equal_p (tem, reg_equiv_mem[regno])) { int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + unsigned outer_size = GET_MODE_SIZE (GET_MODE (x)); + unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); if (BYTES_BIG_ENDIAN) { - int size; - - size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); - offset += MIN (size, UNITS_PER_WORD); - size = GET_MODE_SIZE (GET_MODE (x)); - offset -= MIN (size, UNITS_PER_WORD); + offset += MIN (inner_size, UNITS_PER_WORD); + offset -= MIN (outer_size, UNITS_PER_WORD); } XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset); PUT_MODE (tem, GET_MODE (x)); + + /* 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); + if (GET_CODE (base) == PLUS) + { + if (GET_CODE (XEXP (base, 1)) == CONST_INT + && INTVAL (XEXP (base, 1)) % outer_size != 0) + return x; + base = XEXP (base, 0); + } + if (GET_CODE (base) != REG + || (REGNO_POINTER_ALIGN (REGNO (base)) + < outer_size * BITS_PER_UNIT)) + return x; + } + find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), &XEXP (tem, 0), opnum, ADDR_TYPE (type), ind_levels, insn); + /* If this is not a toplevel operand, find_reloads doesn't see this substitution. We have to emit a USE of the pseudo so that delete_output_reload can see it. */ |