]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
pru: Implement TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS [PR122415]
authorDimitar Dimitrov <dimitar@dinux.eu>
Fri, 7 Nov 2025 20:09:06 +0000 (22:09 +0200)
committerDimitar Dimitrov <dimitar@dinux.eu>
Mon, 10 Nov 2025 17:24:23 +0000 (19:24 +0200)
Splitting a CONST_INT address into base and offset can be beneficial
when accessing multiple addresses in the same UBYTE region.  The base
constant load can be shared among those accesses.

There is no regression for single accesses per UBYTE memory region.
The transformation by TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS generates
practically equivalent code:

   **before**                  **after**
   ldi32 r0, 0x11223344        ldi32 r0, 0x11223300
   lbbo  r1, r0, 0, 4          lbbo  r1, r0, 0x44, 4

For PRU there is a small complication.  While load/store instructions
support base+offset addressing, the call instructions do not.
But the TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS arguments do not show
which operation is using the address, so invalid address is emitted for
call instructions to CONST_INT addresses.  This is solved by fixing up
the call address operands during expansion.

PR target/122415

gcc/ChangeLog:

* config/pru/pru-protos.h (pru_fixup_jump_address_operand):
Declare.
* config/pru/pru.cc (pru_fixup_jump_address_operand): New
function.
(pru_addr_space_legitimize_address): New function.
(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Declare.
* config/pru/pru.md (call): Fixup the address operand.
(call_value): Ditto.
(sibcall): Ditto.
(sibcall_value): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/pru/pr122415-1.c: New test.
* gcc.target/pru/pr122415-2.c: New test.

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
gcc/config/pru/pru-protos.h
gcc/config/pru/pru.cc
gcc/config/pru/pru.md
gcc/testsuite/gcc.target/pru/pr122415-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/pr122415-2.c [new file with mode: 0644]

index d2e51ea44d2f757284f031694d99891adc7a8e7f..12eed90c1bd06299b82bd58e8943b3b50200fdd6 100644 (file)
@@ -72,6 +72,8 @@ extern int pru_get_ctable_base_offset (HOST_WIDE_INT caddr);
 
 extern int pru_symref2ioregno (rtx op);
 
+extern rtx pru_fixup_jump_address_operand (rtx op);
+
 /* Forward declarations to avoid unnecessarily including headers.  */
 class simple_ipa_opt_pass;
 class gimple_opt_pass;
index 3fdc56e373b74272497fbddf4d7e003364d949db..d7e8309de0b96fcabb9cbc7a8b0787f604edcd19 100644 (file)
@@ -1534,6 +1534,23 @@ int pru_symref2ioregno (rtx op)
     return -1;
 }
 
+/* TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS has no arguments to help discern
+   which insn is using the address.  But PRU load/store instructions support
+   offsets, while call instructions do not.
+   So call this when expanding call patterns to revert the effect of
+   TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS.  */
+rtx
+pru_fixup_jump_address_operand (rtx op)
+{
+  if (MEM_P (op)
+      && GET_CODE (XEXP (op, 0)) == PLUS)
+    {
+      rtx tmpval = force_reg (SImode, XEXP (op, 0));
+      op = gen_rtx_MEM (SImode, tmpval);
+    }
+  return op;
+}
+
 /* Implement TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  */
 static bool
 pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
@@ -1582,6 +1599,29 @@ pru_addr_space_legitimate_address_p (machine_mode mode, rtx operand,
     }
   return false;
 }
+
+/* Implement TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS.  */
+rtx
+pru_addr_space_legitimize_address (rtx x, rtx, machine_mode, addr_space_t)
+{
+  if (CONST_INT_P (x) && optimize > 0)
+    {
+      HOST_WIDE_INT mask, base, index;
+      rtx base_reg;
+
+      /* Load/store with UBYTE offset is practically free for PRU.
+        If there two or more operations with addresses in the same UBYTE
+        address range, they all will share the base constant load operation.
+        Clearing the lower 8 bits is a good heuristic to
+        choose a common constant base address.  */
+      mask = 0xff;
+      base = INTVAL (x) & ~mask;
+      index = INTVAL (x) & mask;
+      base_reg = force_reg (SImode, GEN_INT (base));
+      x = plus_constant (Pmode, base_reg, index);
+    }
+  return x;
+}
 \f
 /* Output assembly language related definitions.  */
 
@@ -3246,6 +3286,10 @@ pru_unwind_word_mode (void)
 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
   pru_addr_space_legitimate_address_p
 
+#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS \
+  pru_addr_space_legitimize_address
+
 #undef TARGET_INIT_LIBFUNCS
 #define TARGET_INIT_LIBFUNCS pru_init_libfuncs
 #undef TARGET_LIBFUNC_GNU_PREFIX
index b8ef55b98f93c56ae77f66e104c1e8a96c8700f1..20f580792c3f36ace8debee3ee185b2478c89b40 100644 (file)
                    (match_operand 1 ""))
              (clobber (reg:HI RA_REGNUM))])]
   ""
-  "")
+{
+  operands[0] = pru_fixup_jump_address_operand (operands[0]);
+})
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "")
                         (match_operand 2 "")))
              (clobber (reg:HI RA_REGNUM))])]
   ""
-  "")
+{
+  operands[1] = pru_fixup_jump_address_operand (operands[1]);
+})
 
 (define_insn "*call"
   [(call (mem:SI (match_operand:SI 0 "call_operand" "i,r"))
                    (match_operand 1 ""))
              (return)])]
   ""
-  "")
+{
+  operands[0] = pru_fixup_jump_address_operand (operands[0]);
+})
 
 (define_expand "sibcall_value"
   [(parallel [(set (match_operand 0 "")
                         (match_operand 2 "")))
              (return)])]
   ""
-  "")
+{
+  operands[1] = pru_fixup_jump_address_operand (operands[1]);
+})
 
 (define_insn "*sibcall"
  [(call (mem:SI (match_operand:SI 0 "call_operand" "i,Rsib"))
diff --git a/gcc/testsuite/gcc.target/pru/pr122415-1.c b/gcc/testsuite/gcc.target/pru/pr122415-1.c
new file mode 100644 (file)
index 0000000..4508a85
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do assemble } */
+/* { dg-options "-O1" } */
+/* { dg-final { object-size text <= 24 } } */
+
+void test(void)
+{
+  (*(unsigned *)0x11223344) = 1;
+  (*(unsigned *)0x11223364) = 1;
+}
diff --git a/gcc/testsuite/gcc.target/pru/pr122415-2.c b/gcc/testsuite/gcc.target/pru/pr122415-2.c
new file mode 100644 (file)
index 0000000..c0cf3b3
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-options "-O1" } */
+
+void test(void)
+{
+  (*(unsigned *)0x11223364) = 1;
+  (*(unsigned *)0x11223344) = 1;
+}
+/* { dg-final { scan-assembler "sbbo\\tr\[0-9.bw\]*, r\[0-9\]*, 100, 4" } } */
+/* { dg-final { scan-assembler "sbbo\\tr\[0-9.bw\]*, r\[0-9\]*, 68, 4" } } */