From 0a28aef93e6edbd2a0858840e3856ce4e0b4037b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 24 Jan 2001 15:50:56 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 +++++ gcc/reload.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8dc545edda7..fbc0142fcf6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2001-01-24 Richard Henderson + + * reload.c (find_reloads_subreg_address): Fail the substitution + if the resulting address is insufficiently aligned. + 2001-01-24 DJ Delorie * combine.c (combine_simplify_rtx): If the modes are all VOIDmode, diff --git a/gcc/reload.c b/gcc/reload.c index 533c28c9249..5f27744057d 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. */ -- 2.30.2