re PR rtl-optimization/14782 (produces an unaligned data access at -O2)
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>
Mon, 21 Jun 2004 23:49:04 +0000 (23:49 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Mon, 21 Jun 2004 23:49:04 +0000 (23:49 +0000)
PR rtl-optimization/14782
* pa.c (emit_move_sequence): Use SFmode for 4-byte modes when doing
the address checks for secondary reloads for loads from and stores
to floating-point registers.
* pa.h (EXTRA_CONSTRAINT, case T): Use SFmode for 4-byte modes
in the address check.  Move work around for ELF32 targets to
GO_IF_LEGITIMATE_ADDRESS.
(GO_IF_LEGITIMATE_ADDRESS): Require constant offsets to be
correctly aligned for DImode loads and stores.  Don't allow long
SFmode displacements on ELF32.

From-SVN: r83464

gcc/ChangeLog
gcc/config/pa/pa.c
gcc/config/pa/pa.h

index 9cc5d53db731c84f4748136e6aa97f08f76319bf..9f124c17310e8212ff861e2445009e5464b1f3a5 100644 (file)
@@ -1,3 +1,16 @@
+2004-06-21  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       PR rtl-optimization/14782
+       * pa.c (emit_move_sequence): Use SFmode for 4-byte modes when doing
+       the address checks for secondary reloads for loads from and stores
+       to floating-point registers.
+       * pa.h (EXTRA_CONSTRAINT, case T): Use SFmode for 4-byte modes
+       in the address check.  Move work around for ELF32 targets to
+       GO_IF_LEGITIMATE_ADDRESS.
+       (GO_IF_LEGITIMATE_ADDRESS): Require constant offsets to be
+       correctly aligned for DImode loads and stores.  Don't allow long
+       SFmode displacements on ELF32.
+
 2004-06-21  Richard Henderson  <rth@redhat.com>
 
         PR rtl-opt/16114
index 8bae9e32ad7ce6f9730fd85513a659a94070b98f..3aee1adecbd883eacafff2437b228d8229ab231f 100644 (file)
@@ -1562,15 +1562,18 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
     operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
 
   /* Handle secondary reloads for loads/stores of FP registers from
-     REG+D addresses where D does not fit in 5 bits, including
+     REG+D addresses where D does not fit in 5 or 14 bits, including
      (subreg (mem (addr))) cases.  */
   if (scratch_reg
       && fp_reg_operand (operand0, mode)
       && ((GET_CODE (operand1) == MEM
-          && !memory_address_p (DFmode, XEXP (operand1, 0)))
+          && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode),
+                                XEXP (operand1, 0)))
          || ((GET_CODE (operand1) == SUBREG
               && GET_CODE (XEXP (operand1, 0)) == MEM
-              && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0))))))
+              && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                     ? SFmode : DFmode),
+                                    XEXP (XEXP (operand1, 0), 0))))))
     {
       if (GET_CODE (operand1) == SUBREG)
        operand1 = XEXP (operand1, 0);
@@ -1600,10 +1603,13 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
   else if (scratch_reg
           && fp_reg_operand (operand1, mode)
           && ((GET_CODE (operand0) == MEM
-               && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+               && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                       ? SFmode : DFmode),
+                                      XEXP (operand0, 0)))
               || ((GET_CODE (operand0) == SUBREG)
                   && GET_CODE (XEXP (operand0, 0)) == MEM
-                  && !memory_address_p (DFmode,
+                  && !memory_address_p ((GET_MODE_SIZE (mode) == 4
+                                         ? SFmode : DFmode),
                                         XEXP (XEXP (operand0, 0), 0)))))
     {
       if (GET_CODE (operand0) == SUBREG)
index b08021dd472c5307ac1ed029875ad4e83eb2a38b..5edc151d26d47db243cedacc63811f0ed34fb657 100644 (file)
@@ -1284,7 +1284,7 @@ extern int may_call_alloca;
 
    `S' is the constant 31.
 
-   `T' is for fp loads and stores.
+   `T' is for floating-point loads and stores.
 
    `U' is the constant 63.  */
 
@@ -1307,17 +1307,20 @@ extern int may_call_alloca;
       (GET_CODE (OP) == MEM                                            \
        && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))                         \
        && !IS_INDEX_ADDR_P (XEXP (OP, 0))                              \
-       /* Using DFmode forces only short displacements                 \
-         to be recognized as valid in reg+d addresses.                 \
-         However, this is not necessary for PA2.0 since                \
-         it has long FP loads/stores.                                  \
+       /* Floating-point loads and stores are used to load             \
+         integer values as well as floating-point values.              \
+         They don't have the same set of REG+D address modes           \
+         as integer loads and stores.  PA 1.x supports only            \
+         short displacements.  PA 2.0 supports long displacements      \
+         but the base register needs to be aligned.                    \
                                                                        \
-         FIXME: the ELF32 linker clobbers the LSB of                   \
-         the FP register number in {fldw,fstw} insns.                  \
-         Thus, we only allow long FP loads/stores on                   \
-         TARGET_64BIT.  */                                             \
-       && memory_address_p ((TARGET_PA_20 && !TARGET_ELF32             \
-                            ? GET_MODE (OP)                            \
+         The checks in GO_IF_LEGITIMATE_ADDRESS for SFmode and         \
+         DFmode test the validity of an address for use in a           \
+         floating point load or store.  So, we use SFmode/DFmode       \
+         to see if the address is valid for a floating-point           \
+         load/store operation.  */                                     \
+       && memory_address_p ((GET_MODE_SIZE (GET_MODE (OP)) == 4                \
+                            ? SFmode                                   \
                             : DFmode),                                 \
                            XEXP (OP, 0)))                              \
    : ((C) == 'S' ?                                                     \
@@ -1467,13 +1470,32 @@ extern int may_call_alloca;
       if (base                                                         \
          && GET_CODE (index) == CONST_INT                              \
          && ((INT_14_BITS (index)                                      \
-              && (TARGET_SOFT_FLOAT                                    \
-                  || (TARGET_PA_20                                     \
-                      && ((MODE == SFmode                              \
-                           && (INTVAL (index) % 4) == 0)               \
-                          || (MODE == DFmode                           \
-                              && (INTVAL (index) % 8) == 0)))          \
-                  || ((MODE) != SFmode && (MODE) != DFmode)))          \
+              && (((MODE) != DImode                                    \
+                   && (MODE) != SFmode                                 \
+                   && (MODE) != DFmode)                                \
+                  /* The base register for DImode loads and stores     \
+                     with long displacements must be aligned because   \
+                     the lower three bits in the displacement are      \
+                     assumed to be zero.  */                           \
+                  || ((MODE) == DImode                                 \
+                      && (!TARGET_64BIT                                \
+                          || (INTVAL (index) % 8) == 0))               \
+                  /* Similarly, the base register for SFmode/DFmode    \
+                     loads and stores with long displacements must     \
+                     be aligned.                                       \
+                                                                       \
+                     FIXME: the ELF32 linker clobbers the LSB of       \
+                     the FP register number in PA 2.0 floating-point   \
+                     insns with long displacements.  This is because   \
+                     R_PARISC_DPREL14WR and other relocations like     \
+                     it are not supported.  For now, we reject long    \
+                     displacements on this target.  */                 \
+                  || (((MODE) == SFmode || (MODE) == DFmode)           \
+                      && (TARGET_SOFT_FLOAT                            \
+                          || (TARGET_PA_20                             \
+                              && !TARGET_ELF32                         \
+                              && (INTVAL (index)                       \
+                                  % GET_MODE_SIZE (MODE)) == 0)))))    \
               || INT_5_BITS (index)))                                  \
        goto ADDR;                                                      \
       if (!TARGET_DISABLE_INDEXING                                     \
@@ -1589,6 +1611,11 @@ do {                                                                     \
       else                                                             \
        newoffset = offset & ~mask;                                     \
                                                                        \
+      /* Ensure that long displacements are aligned.  */               \
+      if (!VAL_5_BITS_P (newoffset)                                    \
+         && GET_MODE_CLASS (MODE) == MODE_FLOAT)                       \
+       newoffset &= ~(GET_MODE_SIZE (MODE) -1);                        \
+                                                                       \
       if (newoffset != 0 && VAL_14_BITS_P (newoffset))                 \
        {                                                               \
          temp = gen_rtx_PLUS (Pmode, XEXP (new, 0),                    \