public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] AArch64: Reassociate CONST in address expressions [PR112573]
@ 2024-01-10 15:54 Wilco Dijkstra
  2024-01-10 17:57 ` Richard Sandiford
  0 siblings, 1 reply; 3+ messages in thread
From: Wilco Dijkstra @ 2024-01-10 15:54 UTC (permalink / raw)
  To: GCC Patches; +Cc: Richard Sandiford, Richard Earnshaw, Kyrylo Tkachov

GCC tends to optimistically create CONST of globals with an immediate offset. 
However it is almost always better to CSE addresses of globals and add immediate
offsets separately (the offset could be merged later in single-use cases).
Splitting CONST expressions with an index in aarch64_legitimize_address fixes part
of PR112573.

Passes regress & bootstrap, OK for commit?

gcc/ChangeLog:
        PR target/112573
        * config/aarch64/aarch64.cc (aarch64_legitimize_address): Reassociate badly
        formed CONST expressions.

gcc/testsuite/ChangeLog:
        PR target/112573
        * gcc.target/aarch64/pr112573.c: Add new test.

---

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 0909b319d16b9a1587314bcfda0a8112b42a663f..9fbc8b62455f48baec533d3dd5e2d9ea995d5a8f 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -12608,6 +12608,20 @@ aarch64_legitimize_address (rtx x, rtx /* orig_x  */, machine_mode mode)
      not to split a CONST for some forms of address expression, otherwise
      it will generate sub-optimal code.  */
 
+  /* First split X + CONST (base, offset) into (base + X) + offset.  */
+  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST)
+    {
+      poly_int64 offset;
+      rtx base = strip_offset_and_salt (XEXP (x, 1), &offset);
+
+      if (offset.is_constant ())
+      {
+	  base = expand_binop (Pmode, add_optab, base, XEXP (x, 0),
+			       NULL_RTX, true, OPTAB_DIRECT);
+	  x = plus_constant (Pmode, base, offset);
+      }
+    }
+
   if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
     {
       rtx base = XEXP (x, 0);
diff --git a/gcc/testsuite/gcc.target/aarch64/pr112573.c b/gcc/testsuite/gcc.target/aarch64/pr112573.c
new file mode 100644
index 0000000000000000000000000000000000000000..be04c0ca86ad9f33975a85f497549955d6d1236d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr112573.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-section-anchors" } */
+
+char a[100];
+
+void f1 (int x, int y)
+{
+  *((a + y) + 3) = x;
+  *((a + y) + 2) = x;
+  *((a + y) + 1) = x;
+  *((a + y) + 0) = x;
+}
+
+/* { dg-final { scan-assembler-times "strb" 4 } } */
+/* { dg-final { scan-assembler-times "adrp" 1 } } */


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] AArch64: Reassociate CONST in address expressions [PR112573]
  2024-01-10 15:54 [PATCH] AArch64: Reassociate CONST in address expressions [PR112573] Wilco Dijkstra
@ 2024-01-10 17:57 ` Richard Sandiford
  2024-01-16 17:20   ` Wilco Dijkstra
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Sandiford @ 2024-01-10 17:57 UTC (permalink / raw)
  To: Wilco Dijkstra; +Cc: GCC Patches, Richard Earnshaw, Kyrylo Tkachov

Wilco Dijkstra <Wilco.Dijkstra@arm.com> writes:
> GCC tends to optimistically create CONST of globals with an immediate offset.
> However it is almost always better to CSE addresses of globals and add immediate
> offsets separately (the offset could be merged later in single-use cases).
> Splitting CONST expressions with an index in aarch64_legitimize_address fixes part
> of PR112573.
>
> Passes regress & bootstrap, OK for commit?
>
> gcc/ChangeLog:
>         PR target/112573
>         * config/aarch64/aarch64.cc (aarch64_legitimize_address): Reassociate badly
>         formed CONST expressions.
>
> gcc/testsuite/ChangeLog:
>         PR target/112573
>         * gcc.target/aarch64/pr112573.c: Add new test.
>
> ---
>
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 0909b319d16b9a1587314bcfda0a8112b42a663f..9fbc8b62455f48baec533d3dd5e2d9ea995d5a8f 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -12608,6 +12608,20 @@ aarch64_legitimize_address (rtx x, rtx /* orig_x  */, machine_mode mode)
>       not to split a CONST for some forms of address expression, otherwise
>       it will generate sub-optimal code.  */
>
> +  /* First split X + CONST (base, offset) into (base + X) + offset.  */
> +  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST)
> +    {
> +      poly_int64 offset;
> +      rtx base = strip_offset_and_salt (XEXP (x, 1), &offset);

This should be just strip_offset, so that we don't lose the salt
during optimisation.

> +
> +      if (offset.is_constant ())

I'm not sure this is really required.  Logically the same thing
would apply to SVE, although admittedly:

/* { dg-do compile } */
/* { dg-options "-O2 -fno-section-anchors" } */

#include <arm_sve.h>

char a[2048];

void f1 (svint8_t x, int y)
{
  *(svint8_t *)((a + y) + svcntb() * 3) = x;
  *(svint8_t *)((a + y) + svcntb() * 2) = x;
  *(svint8_t *)((a + y) + svcntb() * 1) = x;
  *(svint8_t *)((a + y) + 0) = x;
}

/* { dg-final { scan-assembler-times "strb" 4 } } */
/* { dg-final { scan-assembler-times "adrp" 1 } } */

doesn't get arranged into the same form for other reasons (and already
produces somewhat decent code).

The patch is OK from my POV without the offset.is_constant check and
with s/strip_offset_and_salt/strip_offset/.  Please say if there's
a reason to keep the offset check though.

Thanks,
Richard

> +      {
> +         base = expand_binop (Pmode, add_optab, base, XEXP (x, 0),
> +                              NULL_RTX, true, OPTAB_DIRECT);
> +         x = plus_constant (Pmode, base, offset);
> +      }
> +    }
> +
>    if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
>      {
>        rtx base = XEXP (x, 0);
> diff --git a/gcc/testsuite/gcc.target/aarch64/pr112573.c b/gcc/testsuite/gcc.target/aarch64/pr112573.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..be04c0ca86ad9f33975a85f497549955d6d1236d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/pr112573.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-section-anchors" } */
> +
> +char a[100];
> +
> +void f1 (int x, int y)
> +{
> +  *((a + y) + 3) = x;
> +  *((a + y) + 2) = x;
> +  *((a + y) + 1) = x;
> +  *((a + y) + 0) = x;
> +}
> +
> +/* { dg-final { scan-assembler-times "strb" 4 } } */
> +/* { dg-final { scan-assembler-times "adrp" 1 } } */

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] AArch64: Reassociate CONST in address expressions [PR112573]
  2024-01-10 17:57 ` Richard Sandiford
@ 2024-01-16 17:20   ` Wilco Dijkstra
  0 siblings, 0 replies; 3+ messages in thread
From: Wilco Dijkstra @ 2024-01-16 17:20 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: GCC Patches, Richard Earnshaw, Kyrylo Tkachov

Hi Richard,

>> +      rtx base = strip_offset_and_salt (XEXP (x, 1), &offset);
>
> This should be just strip_offset, so that we don't lose the salt
> during optimisation.

Fixed.

> +
> +      if (offset.is_constant ())

> I'm not sure this is really required.  Logically the same thing
> would apply to SVE, although admittedly:

It's not needed indeed, I've committed it with the if removed.

However I believe CONST only allows immediate offsets here so that it can
be used in const data. Building SPEC with gcc_assert (!offset.is_constant ()) 
doesn't ever trigger it.

Cheers,
Wilco

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-01-16 17:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-10 15:54 [PATCH] AArch64: Reassociate CONST in address expressions [PR112573] Wilco Dijkstra
2024-01-10 17:57 ` Richard Sandiford
2024-01-16 17:20   ` Wilco Dijkstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).