]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
hppa: Fix scaled and unscaled index support on targets with non-equivalent space...
authorJohn David Anglin <danglin@gcc.gnu.org>
Sun, 23 Nov 2025 22:27:51 +0000 (17:27 -0500)
committerJohn David Anglin <danglin@gcc.gnu.org>
Sun, 23 Nov 2025 22:27:51 +0000 (17:27 -0500)
HP-UX targets have non-equivalent space registers.  The base register
in most loads and stores selects the space register used to calculate
the global virtual address for the instruction.

Previously, the PA-RISC backend attempted to canonicalize the
register order in INDEX + BASE register addresses.  This has always
been problematic as reload would sometimes lose the REG_POINTER
flag used to mark a base register.  As a result, we allowed any
register order after reload and prayed the registers would be
in canonical order.

This broke with the new late_combine2 pass.  It sometimes creates
new indexed instructions after reload.  pa_legitimate_address_p
needs updating to ensure the base register is marked with the
REG_POINTER flag and the index register is not marked.

If scaled index instructions are created before reload, the LRA
pass will sometimes convert it an unscaled index instruction
plus reloads and drop the REG_POINTER flag that was in the base
register.  Thus, we can't allow scaled and unscaled index loads
and stores until reload is completed.

2025-11-23  John David Anglin  <danglin@gcc.gnu.org>

gcc/ChangeLog:

* config/pa/pa.cc (pa_print_operand): Use REG_POINTER
flag to select base and index registers on targets with
non-equivalent space registers.
(pa_legitimate_address_p): Don't allow scaled and unscaled
indexed addresses until reload is complete.  Allow any
register order in unscaled addresses as long as the
REG_POINTER flag is correctly set/unset in the base/index
registers.
* config/pa/predicates.md (mem_operand): Remove code to
delay creating move insns with unscaled indexed addresses
until CSE is not expected.
(move_src_operand): Likewise.

gcc/config/pa/pa.cc
gcc/config/pa/predicates.md

index b63ccf1982f238103ea0014c139edf3c82a2e14d..40abe07ced133d06de854176ebd7754bdf759269 100644 (file)
@@ -5764,11 +5764,22 @@ pa_print_operand (FILE *file, rtx x, int code)
                   && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG)
            {
              /* Because the REG_POINTER flag can get lost during reload,
-                pa_legitimate_address_p canonicalizes the order of the
-                index and base registers in the combined move patterns.  */
+                we now defer creation of instructions with scaled and
+                unscaled index addresses until after reload.  We require
+                that the flag be set in the base register on targets
+                that use space registers.  */
              rtx base = XEXP (XEXP (x, 0), 1);
              rtx index = XEXP (XEXP (x, 0), 0);
 
+             /* Accept non-canonical register order.  */
+             if (!TARGET_NO_SPACE_REGS && !REG_POINTER (base))
+               {
+                 rtx tmp = base;
+                 base = index;
+                 index = tmp;
+                 gcc_assert (REG_POINTER (base));
+               }
+
              fprintf (file, "%s(%s)",
                       reg_names [REGNO (index)], reg_names [REGNO (base)]);
            }
@@ -11001,12 +11012,15 @@ pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
 
       if (!TARGET_DISABLE_INDEXING
          /* Currently, the REG_POINTER flag is not set in a variety
-            of situations (e.g., call arguments and pointer arithmetic).
-            As a result, we can't reliably determine when unscaled
-            addresses are legitimate on targets that need space register
-            selection.  */
-         && TARGET_NO_SPACE_REGS
+            of situations (e.g., call arguments and pointer arithmetic)
+            and the flag can be lost during reload.  So, we only allow
+            unscaled index addresses after reload.  We can accept either
+            register order.  */
          && REG_P (index)
+         && (TARGET_NO_SPACE_REGS
+             || (reload_completed
+                 && ((REG_POINTER (base) && !REG_POINTER (index))
+                     || (!REG_POINTER (base) && REG_POINTER (index)))))
          && MODE_OK_FOR_UNSCALED_INDEXING_P (mode)
          && (strict ? STRICT_REG_OK_FOR_INDEX_P (index)
                     : REG_OK_FOR_INDEX_P (index))
@@ -11015,13 +11029,10 @@ pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
        return true;
 
       if (!TARGET_DISABLE_INDEXING
-         /* Only accept base operands with the REG_POINTER flag prior to
+         /* Only accept base operands with the REG_POINTER flag after
             reload on targets with non-equivalent space registers.  */
          && (TARGET_NO_SPACE_REGS
-             || reload_completed
-             || ((lra_in_progress || reload_in_progress)
-                  && HARD_REGISTER_P (base))
-             || REG_POINTER (base))
+             || (reload_completed && REG_POINTER (base)))
          && GET_CODE (index) == MULT
          && REG_P (XEXP (index, 0))
          && GET_MODE (XEXP (index, 0)) == Pmode
index b0f8274ff798ba127a0d8f211301b8ea5278808a..ecd2f255c9c725b3e10bc610b97f7ead4b31f967 100644 (file)
   if (! MEM_P (op))
     return false;
 
-  /* Until problems with management of the REG_POINTER flag are resolved,
-     we need to delay creating move insns with unscaled indexed addresses
-     until CSE is not expected.  */
-  if (!TARGET_NO_SPACE_REGS
-      && !cse_not_expected
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && REG_P (XEXP (XEXP (op, 0), 0))
-      && REG_P (XEXP (XEXP (op, 0), 1)))
-    return false;
-
   return memory_address_p (mode, XEXP (op, 0));
 })
 
   if (! MEM_P (op))
     return false;
 
-  /* Until problems with management of the REG_POINTER flag are resolved,
-     we need to delay creating move insns with unscaled indexed addresses
-     until CSE is not expected.  */
-  if (!TARGET_NO_SPACE_REGS
-      && !cse_not_expected
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && REG_P (XEXP (XEXP (op, 0), 0))
-      && REG_P (XEXP (XEXP (op, 0), 1)))
-    return false;
-
   return (memory_address_p (mode, XEXP (op, 0)));
 })