aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-01-24 15:50:56 -0800
committerRichard Henderson <rth@gcc.gnu.org>2001-01-24 15:50:56 -0800
commit0a28aef93e6edbd2a0858840e3856ce4e0b4037b (patch)
treeb56353a0eed78434279ea535f0b49194fb4a6e06
parentbf5582ec663dce078a2baebe444e0a656ab1ee60 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/reload.c33
2 files changed, 32 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8dc545e..fbc0142 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2001-01-24 Richard Henderson <rth@redhat.com>
+
+ * reload.c (find_reloads_subreg_address): Fail the substitution
+ if the resulting address is insufficiently aligned.
+
2001-01-24 DJ Delorie <dj@redhat.com>
* combine.c (combine_simplify_rtx): If the modes are all VOIDmode,
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. */