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.
Pushed to trunk as r16-5123-gca6e0f65afaf19
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 <[email protected]>
---
gcc/config/pru/pru-protos.h | 2 ++
gcc/config/pru/pru.cc | 44 +++++++++++++++++++++++
gcc/config/pru/pru.md | 16 ++++++---
gcc/testsuite/gcc.target/pru/pr122415-1.c | 9 +++++
gcc/testsuite/gcc.target/pru/pr122415-2.c | 9 +++++
5 files changed, 76 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/pru/pr122415-1.c
create mode 100644 gcc/testsuite/gcc.target/pru/pr122415-2.c
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index d2e51ea44d2..12eed90c1bd 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -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;
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index 3fdc56e373b..d7e8309de0b 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -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;
+}
/* 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
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index b8ef55b98f9..20f580792c3 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -1289,7 +1289,9 @@ (define_expand "call"
(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 "")
@@ -1297,7 +1299,9 @@ (define_expand "call_value"
(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"))
@@ -1325,7 +1329,9 @@ (define_expand "sibcall"
(match_operand 1 ""))
(return)])]
""
- "")
+{
+ operands[0] = pru_fixup_jump_address_operand (operands[0]);
+})
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "")
@@ -1333,7 +1339,9 @@ (define_expand "sibcall_value"
(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
index 00000000000..4508a850861
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pr122415-1.c
@@ -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
index 00000000000..c0cf3b38e19
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pr122415-2.c
@@ -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" } } */
--
2.51.1