From: Kyrylo Tkachov <[email protected]>

The SVE unary floating-point patterns are named from the "optab" attribute of
the unspec they implement, and UNSPEC_COND_FRINTN was mapped to "frintn"
rather than to the standard name.  FRINTN is round-to-nearest-ties-to-even,
which is exactly roundeven, and the Advanced SIMD side already spells it that
way, so the only effect of the mismatch was that roundeven had no SVE
implementation and every such loop was vectorised with Advanced SIMD:

  double *d, *a;  for (i) d[i] = __builtin_roundeven (a[i]);

  before                                after

  frintn        v31.2d                  frintn  z31.d, p7/m, z31.d

The renaming also applies to the cond_ and aarch64_pred_ forms of the same
pattern, neither of which is a standard name and neither of which is
referred to by name anywhere.

Bootstrapped and tested on aarch64-none-linux-gnu.
Pushing to trunk.
Thanks,
Kyrill

gcc/ChangeLog:

        * config/aarch64/iterators.md (optab): Map UNSPEC_COND_FRINTN to
        roundeven.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/sve/roundeven_1.c: New test.
        * gcc.target/aarch64/sve/roundeven_2.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/config/aarch64/iterators.md               |  2 +-
 .../gcc.target/aarch64/sve/roundeven_1.c      | 28 +++++++++
 .../gcc.target/aarch64/sve/roundeven_2.c      | 60 +++++++++++++++++++
 3 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/roundeven_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/roundeven_2.c

diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index e7ae93d1896..12e65c0f230 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -4571,7 +4571,7 @@
                        (UNSPEC_COND_FRINTA "round")
                        (UNSPEC_COND_FRINTI "nearbyint")
                        (UNSPEC_COND_FRINTM "floor")
-                       (UNSPEC_COND_FRINTN "frintn")
+                       (UNSPEC_COND_FRINTN "roundeven")
                        (UNSPEC_COND_FRINTP "ceil")
                        (UNSPEC_COND_FRINTX "rint")
                        (UNSPEC_COND_FRINTZ "btrunc")
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/roundeven_1.c 
b/gcc/testsuite/gcc.target/aarch64/sve/roundeven_1.c
new file mode 100644
index 00000000000..1348ae8fb13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/roundeven_1.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+sve+fp16 -msve-vector-bits=scalable" } */
+
+void
+rev (double *__restrict d, double *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundeven (a[i]);
+}
+
+void
+revf (float *__restrict d, float *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundevenf (a[i]);
+}
+
+void
+revh (_Float16 *__restrict d, _Float16 *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundevenf16 (a[i]);
+}
+
+/* { dg-final { scan-assembler-times {\tfrintn\tz[0-9]+\.d, p[0-9]+/m, 
z[0-9]+\.d} 1 } } */
+/* { dg-final { scan-assembler-times {\tfrintn\tz[0-9]+\.s, p[0-9]+/m, 
z[0-9]+\.s} 1 } } */
+/* { dg-final { scan-assembler-times {\tfrintn\tz[0-9]+\.h, p[0-9]+/m, 
z[0-9]+\.h} 3 } } */
+/* { dg-final { scan-assembler-not {\tfrintn\tv[0-9]+\.} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/roundeven_2.c 
b/gcc/testsuite/gcc.target/aarch64/sve/roundeven_2.c
new file mode 100644
index 00000000000..a2a3364fb6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/roundeven_2.c
@@ -0,0 +1,60 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+/* { dg-require-effective-target aarch64_sve_hw } */
+/* { dg-additional-options "-march=armv8-a+sve" } */
+
+#define N 137
+static double a[N], d[N], e[N];
+static float fa[N], fd[N], fe[N];
+
+__attribute__((noipa)) void
+rev (double *__restrict d, double *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundeven (a[i]);
+}
+
+__attribute__((noipa, optimize ("O0"))) void
+rev_ref (double *__restrict d, double *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundeven (a[i]);
+}
+
+__attribute__((noipa)) void
+revf (float *__restrict d, float *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundevenf (a[i]);
+}
+
+__attribute__((noipa, optimize ("O0"))) void
+revf_ref (float *__restrict d, float *__restrict a, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = __builtin_roundevenf (a[i]);
+}
+
+int
+main (void)
+{
+  for (int i = 0; i < N; i++)
+    {
+      a[i] = (i - 68) * 0.5 + (i & 3) * 0.25;
+      fa[i] = (float) a[i];
+    }
+
+  rev (d, a, N);
+  rev_ref (e, a, N);
+  for (int i = 0; i < N; i++)
+    if (d[i] != e[i])
+      __builtin_abort ();
+
+  revf (fd, fa, N);
+  revf_ref (fe, fa, N);
+  for (int i = 0; i < N; i++)
+    if (fd[i] != fe[i])
+      __builtin_abort ();
+
+  return 0;
+}
-- 
2.50.1 (Apple Git-155)

Reply via email to