GCC was recently changed to prevent simplify_subreg from simplifying
a subreg of a mem when the mode of the new mem would have stricter alignment
constraints than the inner mem already has when the target requires
STRICT_ALIGNMENT.

However, such targets may have specialist patterns that can handle
unaligned accesses and this restriction turns out to be unduly restrictive.
So limit this restriction to only apply when the inner mem is naturally
aligned to the inner mode.

gcc/ChangeLog:

        PR target/102125
        * simplify-rtx.c (simplify_context::simplify_subreg): Allow
        simplifying (subreg (mem())) when the inner mem is already
        misaligned for its type.
---
 gcc/simplify-rtx.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index ebad5cb5a79..1baa50cb1b9 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -7317,7 +7317,11 @@ simplify_context::simplify_subreg (machine_mode outermode, rtx op,
          have instruction to move the whole thing.  */
       && (! MEM_VOLATILE_P (op)
 	  || ! have_insn_for (SET, innermode))
-      && !(STRICT_ALIGNMENT && MEM_ALIGN (op) < GET_MODE_ALIGNMENT (outermode))
+      /* On STRICT_ALIGNMENT targets, don't allow the alignment to be increased
+	 if the inner object is already naturally aligned.  */
+      && !(STRICT_ALIGNMENT
+	   && MEM_ALIGN (op) >= GET_MODE_ALIGNMENT (innermode)
+	   && MEM_ALIGN (op) < GET_MODE_ALIGNMENT (outermode))
       && known_le (outersize, innersize))
     return adjust_address_nv (op, outermode, byte);
 

Reply via email to