The "prefetch" pattern always emitted PLD, ignoring the read/write
operand, so __builtin_prefetch (p, 1, ...) never produced the PLDW
write-prefetch hint on cores that support it.

PLDW is provided by the Multiprocessing Extensions (optional in ARMv7-A/R,
mandatory from ARMv8-A AArch32).  This is modelled by the "mp" ISA feature,
so expose it as arm_arch_mp / TARGET_HAVE_PLDW and emit PLDW for a write
prefetch when it is available, falling back to the always-safe PLD hint
otherwise.  Read prefetches and cores without the extension are unchanged.

        PR target/58699

gcc/ChangeLog:

        * config/arm/arm.cc (arm_arch_mp): New variable.
        (arm_option_reconfigure_globals): Set it from isa_bit_mp.
        * config/arm/arm-protos.h (arm_arch_mp): Declare.
        * config/arm/arm.h (TARGET_HAVE_PLDW): New macro.
        * config/arm/arm.md (prefetch): Emit PLDW for a write prefetch
        when TARGET_HAVE_PLDW, otherwise PLD.

gcc/testsuite/ChangeLog:

        * gcc.target/arm/pr58699-pldw-arm.c: New test.
        * gcc.target/arm/pr58699-pldw-thumb.c: New test.
        * gcc.target/arm/pr58699-pld-fallback.c: New test.

Signed-off-by: Dominic P <[email protected]>
---

Testing (cross arm-none-eabi; no native bootstrap was done): built cc1 at this
patch's base and with the patch applied and ran the full gcc.target/arm DejaGnu
suite (arm.exp) with each.  The two runs are identical except for the three new
tests, which add 8 PASSes (pr58699-pldw-arm, pr58699-pldw-thumb,
pr58699-pld-fallback); every pre-existing pass/fail/unresolved/unsupported count
is unchanged -- no regressions.  A gcc.c-torture/compile A/B at
-O2 -mcpu=cortex-a53 (a Multiprocessing-Extensions core) over the 1589 files
that compile for arm-none-eabi gave byte-identical assembly on all 1589 --
0 differences, 0 new ICEs.

Bugzilla carries an earlier, never-committed patch for this from 2013
(attachment 30991, "ARM: emit PLDW instruction for prefetch with write
intent").  This version was written against the current prefetch pattern
independently of it: it gates PLDW on the Multiprocessing Extensions isa
bit (PLDW does not exist without the MP extensions), keeps the always-safe
PLD fallback for read prefetches and non-MP cores, covers Thumb-2, and
adds tests.

This patch was prepared with the assistance of an AI coding tool.  Every line of
code, every test and every measurement was written, reviewed and verified by the
author, who takes responsibility for the patch; the Signed-off-by above 
certifies
the Developer Certificate of Origin.

 gcc/config/arm/arm-protos.h                   |  4 ++++
 gcc/config/arm/arm.cc                         |  5 +++++
 gcc/config/arm/arm.h                          |  4 ++++
 gcc/config/arm/arm.md                         |  9 ++++++++-
 .../gcc.target/arm/pr58699-pld-fallback.c     | 15 ++++++++++++++
 .../gcc.target/arm/pr58699-pldw-arm.c         | 20 +++++++++++++++++++
 .../gcc.target/arm/pr58699-pldw-thumb.c       | 13 ++++++++++++
 7 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/pr58699-pld-fallback.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pr58699-pldw-arm.c
 create mode 100644 gcc/testsuite/gcc.target/arm/pr58699-pldw-thumb.c

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index b607cdb3f..3966af1ed 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -459,6 +459,10 @@ extern int arm_arch7;
 /* Nonzero if this chip supports the Large Physical Address Extension.  */
 extern int arm_arch_lpae;
 
+/* Nonzero if this chip supports the Multiprocessing Extensions (and hence
+   the PLDW write-prefetch hint).  */
+extern int arm_arch_mp;
+
 /* Nonzero if instructions not present in the 'M' profile can be used.  */
 extern int arm_arch_notm;
 
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 0bc66abe2..5bb0c5070 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -915,6 +915,10 @@ int arm_arch7 = 0;
 /* Nonzero if this chip supports the Large Physical Address Extension.  */
 int arm_arch_lpae = 0;
 
+/* Nonzero if this chip supports the Multiprocessing Extensions (and hence
+   the PLDW write-prefetch hint).  */
+int arm_arch_mp = 0;
+
 /* Nonzero if instructions not present in the 'M' profile can be used.  */
 int arm_arch_notm = 0;
 
@@ -3925,6 +3929,7 @@ arm_option_reconfigure_globals (void)
   arm_arch_cmse = bitmap_bit_p (arm_active_target.isa, isa_bit_cmse);
   arm_arch8m_main = arm_arch7 && arm_arch_cmse;
   arm_arch_lpae = bitmap_bit_p (arm_active_target.isa, isa_bit_lpae);
+  arm_arch_mp = bitmap_bit_p (arm_active_target.isa, isa_bit_mp);
   arm_arch_i8mm = bitmap_bit_p (arm_active_target.isa, isa_bit_i8mm);
   arm_arch_bf16 = bitmap_bit_p (arm_active_target.isa, isa_bit_bf16);
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 10786ec91..9891704b9 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -287,6 +287,10 @@ emission of floating point pcs attributes.  */
 /* Nonzero if this chip supports LPAE.  */
 #define TARGET_HAVE_LPAE (arm_arch_lpae)
 
+/* Nonzero if this chip supports the write-prefetch hint PLDW, which is
+   provided by the Multiprocessing Extensions (mandatory from ARMv8-A).  */
+#define TARGET_HAVE_PLDW (arm_arch_mp)
+
 /* Nonzero if this chip supports ldrex{bh} and strex{bh}.  */
 #define TARGET_HAVE_LDREXBH ((arm_arch6k && TARGET_ARM)                \
                             || arm_arch7                       \
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index febff17df..373ae0d9b 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12233,7 +12233,14 @@
             (match_operand:SI 1 "" "")
             (match_operand:SI 2 "" ""))]
   "TARGET_32BIT && arm_arch5te"
-  "pld\\t%a0"
+  {
+    /* A write-prefetch (operands[1] != 0) can use PLDW, but only when the
+       Multiprocessing Extensions are available (mandatory from ARMv8-A).
+       Otherwise fall back to PLD, which is a hint and always safe.  */
+    if (INTVAL (operands[1]) != 0 && TARGET_HAVE_PLDW)
+      return "pldw\\t%a0";
+    return "pld\\t%a0";
+  }
   [(set_attr "type" "load_4")]
 )
 
diff --git a/gcc/testsuite/gcc.target/arm/pr58699-pld-fallback.c 
b/gcc/testsuite/gcc.target/arm/pr58699-pld-fallback.c
new file mode 100644
index 000000000..49ab3392c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58699-pld-fallback.c
@@ -0,0 +1,15 @@
+/* PR target/58699: on a core without the Multiprocessing Extensions
+   (plain ARMv7-A) PLDW is unavailable, so a write prefetch must fall back
+   to the always-safe PLD hint and must never emit PLDW.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v7a_ok } */
+/* { dg-options "-O2 -marm" } */
+/* { dg-add-options arm_arch_v7a } */
+
+void write_prefetch (int *p)
+{
+  __builtin_prefetch (p, 1, 3);
+}
+
+/* { dg-final { scan-assembler "\tpld\t" } } */
+/* { dg-final { scan-assembler-not "\tpldw\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr58699-pldw-arm.c 
b/gcc/testsuite/gcc.target/arm/pr58699-pldw-arm.c
new file mode 100644
index 000000000..1755fb128
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58699-pldw-arm.c
@@ -0,0 +1,20 @@
+/* PR target/58699: __builtin_prefetch with write intent should emit PLDW
+   on cores that have the Multiprocessing Extensions (here ARMv8-A, ARM
+   state).  Read prefetch still uses PLD.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2 -marm" } */
+/* { dg-add-options arm_arch_v8a } */
+
+void write_prefetch (int *p)
+{
+  __builtin_prefetch (p, 1, 3);
+}
+
+void read_prefetch (int *p)
+{
+  __builtin_prefetch (p, 0, 3);
+}
+
+/* { dg-final { scan-assembler "\tpldw\t" } } */
+/* { dg-final { scan-assembler "\tpld\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr58699-pldw-thumb.c 
b/gcc/testsuite/gcc.target/arm/pr58699-pldw-thumb.c
new file mode 100644
index 000000000..127f356e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr58699-pldw-thumb.c
@@ -0,0 +1,13 @@
+/* PR target/58699: __builtin_prefetch with write intent should emit PLDW
+   on Multiprocessing-Extensions cores in Thumb-2 state too.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8a_ok } */
+/* { dg-options "-O2 -mthumb" } */
+/* { dg-add-options arm_arch_v8a } */
+
+void write_prefetch (int *p)
+{
+  __builtin_prefetch (p, 1, 3);
+}
+
+/* { dg-final { scan-assembler "\tpldw\t" } } */
-- 
2.55.0

Reply via email to