]> gcc.gnu.org Git - gcc.git/commitdiff
hppa: Revise REG+D address support to allow long displacements before reload
authorJohn David Anglin <danglin@gcc.gnu.org>
Thu, 16 Nov 2023 17:42:26 +0000 (17:42 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Thu, 16 Nov 2023 17:42:26 +0000 (17:42 +0000)
In analyzing PR rtl-optimization/112415, I realized that restricting
REG+D offsets to 5-bits before reload results in very poor code and
complexities in optimizing these instructions after reload.  The
general problem is long displacements are not allowed for floating
point accesses when generating PA 1.1 code.  Even with PA 2.0, there
is a ELF linker bug that prevents using long displacements for
floating point loads and stores.

In the past, enabling long displacements before reload caused issues
in reload.  However, there have been fixes in the handling of reloads
for floating-point accesses.  This change allows long displacements
before reload and corrects a couple of issues in the constraint
handling for integer and floating-point accesses.

2023-11-16  John David Anglin  <danglin@gcc.gnu.org>

gcc/ChangeLog:

PR rtl-optimization/112415
* config/pa/pa.cc (pa_legitimate_address_p): Allow 14-bit
displacements before reload.  Simplify logic flow.  Revise
comments.
* config/pa/pa.h (TARGET_ELF64): New define.
(INT14_OK_STRICT): Update define and comment.
* config/pa/pa64-linux.h (TARGET_ELF64): Define.
* config/pa/predicates.md (base14_operand): Don't check
alignment of short displacements.
(integer_store_memory_operand): Don't return true when
reload_in_progress is true.  Remove INT_5_BITS check.
(floating_point_store_memory_operand): Don't return true when
reload_in_progress is true.  Use INT14_OK_STRICT to check
whether long displacements are always okay.

gcc/config/pa/pa.cc
gcc/config/pa/pa.h
gcc/config/pa/pa64-linux.h
gcc/config/pa/predicates.md

index 218c48b4ae000d252a67522fd6fddf9c2bd30cb1..565c948a9e6181761595cfd8f1d42abf8aeaff35 100644 (file)
@@ -10819,23 +10819,29 @@ pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 
       if (GET_CODE (index) == CONST_INT)
        {
+         /* Short 5-bit displacements always okay.  */
          if (INT_5_BITS (index))
            return true;
 
-         /* When INT14_OK_STRICT is false, a secondary reload is needed
-            to adjust the displacement of SImode and DImode floating point
-            instructions but this may fail when the register also needs
-            reloading.  So, we return false when STRICT is true.  We
-            also reject long displacements for float mode addresses since
-            the majority of accesses will use floating point instructions
-            that don't support 14-bit offsets.  */
-         if (!INT14_OK_STRICT
-             && (strict || !(reload_in_progress || reload_completed))
-             && mode != QImode
-             && mode != HImode)
+         if (!base14_operand (index, mode))
            return false;
 
-         return base14_operand (index, mode);
+         /* Long 14-bit displacements always okay for these cases.  */
+         if (INT14_OK_STRICT
+             || mode == QImode
+             || mode == HImode)
+           return true;
+
+         /* A secondary reload may be needed to adjust the displacement
+            of floating-point accesses when STRICT is nonzero.  */
+         if (strict)
+           return false;
+
+         /* We get significantly better code if we allow long displacements
+            before reload for all accesses.  Instructions must satisfy their
+            constraints after reload, so we must have an integer access.
+            Return true for both cases.  */
+         return true;
        }
 
       if (!TARGET_DISABLE_INDEXING
index e65af52296634cbb728ed2a15dbbbbd1ac7908da..aba2cec73579baf239c520d280985d5abef04347 100644 (file)
@@ -37,6 +37,11 @@ extern unsigned long total_code_bytes;
 #define TARGET_ELF32 0
 #endif
 
+/* Generate code for ELF64 ABI.  */
+#ifndef TARGET_ELF64
+#define TARGET_ELF64 0
+#endif
+
 /* Generate code for SOM 32bit ABI.  */
 #ifndef TARGET_SOM
 #define TARGET_SOM 0
@@ -823,12 +828,11 @@ extern int may_call_alloca;
 
 /* Nonzero if 14-bit offsets can be used for all loads and stores.
    This is not possible when generating PA 1.x code as floating point
-   loads and stores only support 5-bit offsets.  Note that we do not
-   forbid the use of 14-bit offsets for integer modes.  Instead, we
-   use secondary reloads to fix REG+D memory addresses for integer
-   mode floating-point loads and stores.
+   accesses only support 5-bit offsets.  Note that we do not forbid
+   the use of 14-bit offsets prior to reload.  Instead, we use secondary
+   reloads to fix REG+D memory addresses for floating-point accesses.
 
-   FIXME: the ELF32 linker clobbers the LSB of the FP register number
+   FIXME: the GNU ELF 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
    yet supported by GNU ld.  For now, we reject long displacements
@@ -836,7 +840,7 @@ extern int may_call_alloca;
 
 #define INT14_OK_STRICT \
   (TARGET_SOFT_FLOAT                                                   \
-   || (TARGET_PA_20 && !TARGET_ELF32))
+   || (TARGET_PA_20 && !TARGET_ELF32 && !TARGET_ELF64))
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
index f61c9e16f4489ff1a2ffe3ffd290d19447d64944..33fed023643d42d9d566d8065558d2969a0b9b01 100644 (file)
@@ -17,6 +17,10 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
+/* 64-bit ELF target.  */
+#undef TARGET_ELF64
+#define TARGET_ELF64 1
+
 #if 0 /* needs some work :-( */
 /* If defined, this macro specifies a table of register pairs used to
    eliminate unneeded registers that point into the stack frame.  */
index 08071b2d279e6f75fbadcfdb923bd57165e7882f..1b50020e1deb935badece0466dee99abe3cd480b 100644 (file)
   if (!INT_14_BITS (op))
     return false;
 
+  /* Short displacement.  */
+  if (INT_5_BITS (op))
+    return true;
+
   /* Although this may not be necessary, we require that the
      base value is correctly aligned for its mode as this is
      assumed in the instruction encoding.  */
 
   if (reg_plus_base_memory_operand (op, mode))
     {
-      if (reload_in_progress)
-       return true;
-
       /* Extract CONST_INT operand.  */
       if (GET_CODE (op) == SUBREG)
        op = SUBREG_REG (op);
       op = XEXP (op, 0);
       op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
-      return base14_operand (op, mode) || INT_5_BITS (op);
+      return base14_operand (op, mode);
     }
 
   if (!MEM_P (op))
 
   if (reg_plus_base_memory_operand (op, mode))
     {
-      if (reload_in_progress)
-       return true;
-
       /* Extract CONST_INT operand.  */
       if (GET_CODE (op) == SUBREG)
        op = SUBREG_REG (op);
       op = XEXP (op, 0);
       op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
-      return ((TARGET_PA_20
-              && !TARGET_ELF32
-              && base14_operand (op, mode))
+      return ((INT14_OK_STRICT && base14_operand (op, mode))
              || INT_5_BITS (op));
     }
 
This page took 0.076278 seconds and 5 git commands to generate.