reload.c (find_reloads_subreg_address): Fail the substitution if the resulting addres...
authorRichard Henderson <rth@redhat.com>
Wed, 24 Jan 2001 23:50:56 +0000 (15:50 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 24 Jan 2001 23:50:56 +0000 (15:50 -0800)
        * reload.c (find_reloads_subreg_address): Fail the substitution
        if the resulting address is insufficiently aligned.

From-SVN: r39250

gcc/ChangeLog
gcc/reload.c

index 8dc545edda7d5449389f22aa2d1b9ed6ed78fae3..fbc0142fcf6bde44f3d71b5b25006f338158ffc9 100644 (file)
@@ -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,
index 533c28c92491b6b8cd881843b3a991e9561c4a23..5f27744057d53a558ae65e092a92333b77b16ce3 100644 (file)
@@ -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.  */