This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] PPC64: First in the series of patches implementing POWER8 vector math.
- From: GT <tnggil at protonmail dot com>
- To: "libc-alpha at sourceware dot org" <libc-alpha at sourceware dot org>
- Date: Mon, 18 Feb 2019 23:48:19 +0000
- Subject: [PATCH] PPC64: First in the series of patches implementing POWER8 vector math.
- Reply-to: GT <tnggil at protonmail dot com>
Empty Message
From 65fda4d67a61d7ae19e53001855cd4482e2bf59e Mon Sep 17 00:00:00 2001
From: Bert Tenjy <bert.tenjy@gmail.com>
Date: Mon, 18 Feb 2019 23:24:46 +0000
Subject: [PATCH] PPC64: First in the series of patches implementing POWER8
vector math.
Implements double-precision cosine using VSX vector capability. Algorithm for
cosine is from x86_64 [commit #2193311288] adapted to PPC64.
Name-mangling exactly duplicates SSE ISA of the x86_64 ABI. The details are
at <https://groups.google.com/forum/#!topic/x86-64-abi/LmppCfN1rZ4>.
Adds tests of the new double-precision vector cosine.
[BZ #24205]
---
ChangeLog | 16 ++++
sysdeps/powerpc/bits/math-vector.h | 41 ++++++++
sysdeps/powerpc/fpu/libm-test-ulps | 3 +
sysdeps/powerpc/powerpc64/fpu/Versions | 5 +
.../powerpc/powerpc64/fpu/multiarch/Makefile | 17 ++++
.../multiarch/test-double-vlen2-wrappers.c | 24 +++++
.../powerpc64/fpu/multiarch/vec_d_cos2_core.c | 30 ++++++
.../fpu/multiarch/vec_d_cos2_power8.c | 93 +++++++++++++++++++
.../powerpc64/fpu/multiarch/vec_d_cos2_vmx.c | 35 +++++++
.../powerpc64/fpu/multiarch/vec_d_trig_data.h | 61 ++++++++++++
.../linux/powerpc/powerpc64/libmvec.abilist | 1 +
11 files changed, 326 insertions(+)
create mode 100644 sysdeps/powerpc/bits/math-vector.h
create mode 100644 sysdeps/powerpc/powerpc64/fpu/Versions
create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/test-double-vlen2-wrappers.c
create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_core.c
create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_power8.c
create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_vmx.c
create mode 100644 sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_trig_data.h
create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64/libmvec.abilist
diff --git a/ChangeLog b/ChangeLog
index 312ef3bd8f..ccdd855136 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2019-02-18 <bert.tenjy@gmail.com>
+
+ * sysdeps/powerpc/bits/math-vector.h: New file.
+ * sysdeps/powerpc/fpu/libm-test-ulps (cos_vlen2): Regenerated.
+ * sysdeps/powerpc/powerpc64/fpu/Versions: New file.
+ * sysdeps/powerpc/powerpc64/multiarch/Makefile (libmvec-sysdep_routines)
+ (double-vlen-funcs,double-vlen-arch-ext-flags): Added build of VSX
+ vector cos function and its tests.
+ * sysdeps/powerpc/powerpc64/multiarch/test-double-vlen2-wrappers.c: New file.
+ * sysdeps/powerpc/powerpc64/multiarch/vec_d_cos2_core.c: New file.
+ * sysdeps/powerpc/powerpc64/multiarch/vec_d_cos2_power8.c: New file.
+ * sysdeps/powerpc/powerpc64/multiarch/vec_d_cos2_vmx.c: New file.
+ * sysdeps/powerpc/powerpc64/multiarch/vec_d_trig_data.h: New file.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/libmvec.abilist: New file.
+
+
2019-02-18 Florian Weimer <fweimer@redhat.com>
* resolv/compat-gethnamaddr.c (Dprintf): Remove definition.
diff --git a/sysdeps/powerpc/bits/math-vector.h b/sysdeps/powerpc/bits/math-vector.h
new file mode 100644
index 0000000000..a569b19e7a
--- /dev/null
+++ b/sysdeps/powerpc/bits/math-vector.h
@@ -0,0 +1,41 @@
+/* Platform-specific SIMD declarations of math functions.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MATH_H
+# error "Never include <bits/math-vector.h> directly;\
+ include <math.h> instead."
+#endif
+
+/* Get default empty definitions for simd declarations. */
+#include <bits/libm-simd-decl-stubs.h>
+
+#if defined __POWERPC64__ && defined __FAST_MATH__
+# if defined _OPENMP && _OPENMP >= 201307
+/* OpenMP case. */
+# define __DECL_SIMD_ARCH_PPC64 _Pragma ("omp declare simd notinbranch")
+# elif __GNUC_PREREQ (6,0)
+/* W/o OpenMP use GCC 6.* __attribute__ ((__simd__)). */
+# define __DECL_SIMD_ARCH_PPC64 __attribute__ ((__simd__ ("notinbranch")))
+# endif
+
+# ifdef __DECL_SIMD_ARCH_PPC64
+# undef __DECL_SIMD_cos
+# define __DECL_SIMD_cos __DECL_SIMD_ARCH_PPC64
+
+# endif
+#endif
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index 1eec27c1dc..d392b135a7 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -1311,6 +1311,9 @@ ifloat128: 2
ildouble: 5
ldouble: 5
+Function: "cos_vlen2":
+double: 2
+
Function: "cosh":
double: 1
float: 1
diff --git a/sysdeps/powerpc/powerpc64/fpu/Versions b/sysdeps/powerpc/powerpc64/fpu/Versions
new file mode 100644
index 0000000000..9a3e1211cc
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/Versions
@@ -0,0 +1,5 @@
+libmvec {
+ GLIBC_2.30 {
+ _ZGVbN2v_cos;
+ }
+}
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
index 39b557604c..51e89a2532 100644
--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile
@@ -42,3 +42,20 @@ CFLAGS-e_hypotf-power7.c = -mcpu=power7
CFLAGS-s_modf-ppc64.c += -fsignaling-nans
CFLAGS-s_modff-ppc64.c += -fsignaling-nans
endif
+
+ifeq ($(subdir),mathvec)
+libmvec-sysdep_routines += vec_d_cos2_core vec_d_cos2_power8 \
+ vec_d_cos2_vmx
+endif
+
+# Variables for libmvec tests.
+ifeq ($(subdir),math)
+ifeq ($(build-mathvec),yes)
+libmvec-tests += double-vlen2
+
+double-vlen2-funcs = cos
+
+double-vlen2-arch-ext-cflags = -mvsx
+
+endif
+endif
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/test-double-vlen2-wrappers.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/test-double-vlen2-wrappers.c
new file mode 100644
index 0000000000..17e2cc0724
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/test-double-vlen2-wrappers.c
@@ -0,0 +1,24 @@
+/* Wrapper part of tests for VSX ISA versions of vector math functions.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "test-double-vlen2.h"
+#include <altivec.h>
+
+#define VEC_TYPE vector double
+
+VECTOR_WRAPPER (WRAPPER_NAME (cos), _ZGVbN2v_cos)
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_core.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_core.c
new file mode 100644
index 0000000000..e089a8d844
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_core.c
@@ -0,0 +1,30 @@
+/* Multiple versions of vectorized cos function.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <shlib-compat.h>
+#include "init-arch.h"
+
+vector double _ZGVbN2v_cos (vector double x);
+
+extern __typeof (_ZGVbN2v_cos) _ZGVbN2v_cos_vmx attribute_hidden;
+extern __typeof (_ZGVbN2v_cos) _ZGVbN2v_cos_vsx attribute_hidden;
+
+libc_ifunc (_ZGVbN2v_cos,
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07)
+ ? _ZGVbN2v_cos_vsx : _ZGVbN2v_cos_vmx);
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_power8.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_power8.c
new file mode 100644
index 0000000000..4f6c9cce6b
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_power8.c
@@ -0,0 +1,93 @@
+/* Function cos vectorized with VSX.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include "vec_d_trig_data.h"
+
+vector double
+_ZGVbN2v_cos_vsx (vector double x)
+{
+
+/*
+ ARGUMENT RANGE REDUCTION:
+ Add Pi/2 to argument: X' = X+Pi/2
+ */
+ vector double x_prime = (vector double) d_half_pi + x;
+
+/* Get absolute argument value: X' = |X'| */
+ vector double abs_x_prime = vec_abs (x_prime);
+
+/* Y = X'*InvPi + RS : right shifter add */
+ vector double y = (x_prime * d_inv_pi) + d_rshifter;
+
+/* Check for large arguments path */
+ vector bool long long large_in = vec_cmpgt (abs_x_prime, d_rangeval);
+
+/* N = Y - RS : right shifter sub */
+ vector double n = y - d_rshifter;
+
+/* SignRes = Y<<63 : shift LSB to MSB place for result sign */
+ vector double sign_res = (vector double) vec_sl ((vector long long) y,
+ (vector unsigned long long)
+ vec_splats (63));
+
+/* N = N - 0.5 */
+ n = n - d_one_half;
+
+/* R = X - N*Pi1 */
+ vector double r = x - (n * d_pi1_fma);
+
+/* R = R - N*Pi2 */
+ r = r - (n * d_pi2_fma);
+
+/* R = R - N*Pi3 */
+ r = r - (n * d_pi3_fma);
+
+/* R2 = R*R */
+ vector double r2 = r * r;
+
+/* Poly = C3+R2*(C4+R2*(C5+R2*(C6+R2*C7))) */
+ vector double poly = r2 * d_coeff7 + d_coeff6;
+ poly = poly * r2 + d_coeff5;
+ poly = poly * r2 + d_coeff4;
+ poly = poly * r2 + d_coeff3;
+
+/* Poly = R+R*(R2*(C1+R2*(C2+R2*Poly))) */
+ poly = poly * r2 + d_coeff2;
+ poly = poly * r2 + d_coeff1;
+ poly = poly * r2 * r + r;
+
+/*
+ RECONSTRUCTION:
+ Final sign setting: Res = Poly^SignRes */
+ vector double out
+ = (vector double) ((vector long long) poly ^ (vector long long) sign_res);
+
+ if (large_in[0] != 0)
+ {
+ out[0] = cos (x[0]);
+ }
+
+ if (large_in[1] != 0)
+ {
+ out[1] = cos (x[1]);
+ }
+
+ return out;
+
+} /* _ZGVbN2v_cos_vsx */
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_vmx.c b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_vmx.c
new file mode 100644
index 0000000000..e32fd77b6c
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_cos2_vmx.c
@@ -0,0 +1,35 @@
+/* PowerPC64 default version of vectorized cos function.
+ Calls scalar cos version twice.
+
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <altivec.h>
+
+vector double
+_ZGVbN2v_cos_vmx (vector double x)
+{
+
+ vector double out;
+
+ out[0] = cos (x[0]);
+ out[1] = cos (x[1]);
+
+ return out;
+
+} // _ZGVbN2v_cos_vmx
diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_trig_data.h b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_trig_data.h
new file mode 100644
index 0000000000..ae33017324
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/vec_d_trig_data.h
@@ -0,0 +1,61 @@
+/* Constants used in polynomail approximations for vectorized sin, cos,
+ and sincos functions.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef D_TRIG_DATA_H
+#define D_TRIG_DATA_H
+
+#include <altivec.h>
+
+/* PI/2 */
+const vector double d_half_pi = {0x1.921fb54442d18p+0, 0x1.921fb54442d18p+0};
+
+/* 1/PI */
+const vector double d_inv_pi = {0x1.45f306dc9c883p-2, 0x1.45f306dc9c883p-2};
+
+/* right-shifter constant */
+const vector double d_rshifter = {0x1.8p+52, 0x1.8p+52};
+
+/* working range threshold */
+const vector double d_rangeval = {0x1p+23, 0x1p+23};
+
+/* 0.5 */
+const vector double d_one_half = {0x1p-1, 0x1p-1};
+
+/* Range reduction PI-based constants if FMA available:
+ PI high part (FMA available)
+ */
+const vector double d_pi1_fma = {0x1.921fb54442d18p+1, 0x1.921fb54442d18p+1};
+
+/* PI mid part (FMA available) */
+const vector double d_pi2_fma = {0x1.1a62633145c06p-53, 0x1.1a62633145c06p-53};
+
+/* PI low part (FMA available) */
+const vector double d_pi3_fma
+= {0x1.c1cd129024e09p-106,0x1.c1cd129024e09p-106};
+
+/* Polynomial coefficients (relative error 2^(-52.115)): */
+const vector double d_coeff7 = {-0x1.9f0d60811aac8p-41,-0x1.9f0d60811aac8p-41};
+const vector double d_coeff6 = {0x1.60e6857a2f22p-33,0x1.60e6857a2f22p-33};
+const vector double d_coeff5 = {-0x1.ae63546002231p-26,-0x1.ae63546002231p-26};
+const vector double d_coeff4 = {0x1.71de38030feap-19,0x1.71de38030feap-19};
+const vector double d_coeff3 = {-0x1.a01a019a5b86dp-13,-0x1.a01a019a5b86dp-13};
+const vector double d_coeff2 = {0x1.111111110a4a8p-7,0x1.111111110a4a8p-7};
+const vector double d_coeff1 = {-0x1.55555555554a7p-3,-0x1.55555555554a7p-3};
+
+#endif // D_TRIG_DATA_H
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libmvec.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libmvec.abilist
new file mode 100644
index 0000000000..656ce0541f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libmvec.abilist
@@ -0,0 +1 @@
+GLIBC_2.30 _ZGVbN2v_cos F
--
2.20.1