[gcc r17-3367] aarch64: name the SVE FRINTN pattern after the roundeven optab

Kyrylo Tkachov via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:5ea6e90b0374504d3ce15f76df56420883eda9fd

commit r17-3367-g5ea6e90b0374504d3ce15f76df56420883eda9fd
Author: Kyrylo Tkachov <[email protected]>
Date:   Mon Aug 3 09:10:25 2026 -0700

    aarch64: name the SVE FRINTN pattern after the roundeven optab
    
    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.
    
    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]>

Diff:
---
 gcc/config/aarch64/iterators.md                    |  2 +-
 gcc/testsuite/gcc.target/aarch64/sve/roundeven_1.c | 28 ++++++++++
 gcc/testsuite/gcc.target/aarch64/sve/roundeven_2.c | 60 ++++++++++++++++++++++
 3 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index f5e6ad8bfb3b..8bfa64290265 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -4589,7 +4589,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 000000000000..1348ae8fb133
--- /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 000000000000..a2a3364fb6e8
--- /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;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.