[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; +}