public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/6] MIPS: Improve math
@ 2024-05-13  8:14 YunQiang Su
  2024-05-13  8:14 ` [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf YunQiang Su
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

YunQiang Su (6):
  MIPSr6/math: Use builtin fma and fmaf
  MIPS/math: Define port-specific GET_HIGH_WORD
  MIPS/math: Implement optimized issignaling(f)
  MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f)
  MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f)
  MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f)

 sysdeps/mips/fpu/math-use-builtins-fma.h   |  13 +++
 sysdeps/mips/fpu_control.h                 |  17 +++
 sysdeps/mips/ieee754/s_fmax.c              |  45 ++++++++
 sysdeps/mips/ieee754/s_fmaxf.c             |  43 ++++++++
 sysdeps/mips/ieee754/s_fmaximum.c          |  48 ++++++++
 sysdeps/mips/ieee754/s_fmaximum_mag.c      |  57 ++++++++++
 sysdeps/mips/ieee754/s_fmaximum_mag_num.c  |  65 +++++++++++
 sysdeps/mips/ieee754/s_fmaximum_mag_numf.c |  64 +++++++++++
 sysdeps/mips/ieee754/s_fmaximum_magf.c     |  55 ++++++++++
 sysdeps/mips/ieee754/s_fmaximum_num.c      |  54 +++++++++
 sysdeps/mips/ieee754/s_fmaximum_numf.c     |  53 +++++++++
 sysdeps/mips/ieee754/s_fmaximumf.c         |  46 ++++++++
 sysdeps/mips/ieee754/s_fmaxmag.c           |  62 +++++++++++
 sysdeps/mips/ieee754/s_fmaxmagf.c          |  61 +++++++++++
 sysdeps/mips/ieee754/s_fmin.c              |  44 ++++++++
 sysdeps/mips/ieee754/s_fminf.c             |  43 ++++++++
 sysdeps/mips/ieee754/s_fminimum.c          |  48 ++++++++
 sysdeps/mips/ieee754/s_fminimum_mag.c      |  57 ++++++++++
 sysdeps/mips/ieee754/s_fminimum_mag_num.c  |  65 +++++++++++
 sysdeps/mips/ieee754/s_fminimum_mag_numf.c |  64 +++++++++++
 sysdeps/mips/ieee754/s_fminimum_magf.c     |  55 ++++++++++
 sysdeps/mips/ieee754/s_fminimum_num.c      |  54 +++++++++
 sysdeps/mips/ieee754/s_fminimum_numf.c     |  53 +++++++++
 sysdeps/mips/ieee754/s_fminimumf.c         |  46 ++++++++
 sysdeps/mips/ieee754/s_fminmag.c           |  62 +++++++++++
 sysdeps/mips/ieee754/s_fminmagf.c          |  61 +++++++++++
 sysdeps/mips/ieee754/s_issignaling.c       |  28 +++++
 sysdeps/mips/ieee754/s_issignalingf.c      |  27 +++++
 sysdeps/mips/math_private.h                | 121 +++++++++++++++++++++
 29 files changed, 1511 insertions(+)
 create mode 100644 sysdeps/mips/fpu/math-use-builtins-fma.h
 create mode 100644 sysdeps/mips/ieee754/s_fmax.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_magf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximumf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxmag.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxmagf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmin.c
 create mode 100644 sysdeps/mips/ieee754/s_fminf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_magf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimumf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminmag.c
 create mode 100644 sysdeps/mips/ieee754/s_fminmagf.c
 create mode 100644 sysdeps/mips/ieee754/s_issignaling.c
 create mode 100644 sysdeps/mips/ieee754/s_issignalingf.c
 create mode 100644 sysdeps/mips/math_private.h

-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-22 13:42   ` Adhemerval Zanella Netto
  2024-05-13  8:14 ` [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD YunQiang Su
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

MIPSr6 has MADDF.s/MADDF.d instructions, which are fused.

In MIPS ISA, double support can be subsetted.  Only FMAF is enabled
for this case.

	* sysdeps/mips/fpu/math-use-builtins-fma.h

Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
---
 sysdeps/mips/fpu/math-use-builtins-fma.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 sysdeps/mips/fpu/math-use-builtins-fma.h

diff --git a/sysdeps/mips/fpu/math-use-builtins-fma.h b/sysdeps/mips/fpu/math-use-builtins-fma.h
new file mode 100644
index 0000000000..6e296fd4c0
--- /dev/null
+++ b/sysdeps/mips/fpu/math-use-builtins-fma.h
@@ -0,0 +1,13 @@
+#if __mips_isa_rev >= 6
+#  if defined(__mips_single_float)
+#    define USE_FMA_BUILTIN 0
+#  else
+#    define USE_FMA_BUILTIN 1
+#  endif
+#  define USE_FMAF_BUILTIN 1
+#else
+#  define USE_FMA_BUILTIN 0
+#  define USE_FMAF_BUILTIN 0
+#endif
+#define USE_FMAL_BUILTIN 0
+#define USE_FMAF128_BUILTIN 0
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
  2024-05-13  8:14 ` [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-22 18:36   ` Adhemerval Zanella Netto
  2024-05-13  8:14 ` [PATCH 3/6] MIPS/math: Implement optimized issignaling(f) YunQiang Su
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

The generic implemention may issue some unneeded stack store and
load operations.

	* sysdeps/mips/math_private.h

Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
---
 sysdeps/mips/math_private.h | 56 +++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 sysdeps/mips/math_private.h

diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h
new file mode 100644
index 0000000000..4da8b0c2d9
--- /dev/null
+++ b/sysdeps/mips/math_private.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef MIPS_MATH_PRIVATE_H
+#define MIPS_MATH_PRIVATE_H 1
+
+#include <math.h>
+#include <nan-high-order-bit.h>
+#include_next <math_private.h>
+#include <fpu_control.h>
+
+#if defined(__mips_hard_float) && !defined(__mips_single_float)
+#  undef GET_HIGH_WORD
+#  if __mips_isa_rev >= 2
+#    define GET_HIGH_WORD(i, d)                                               \
+      do                                                                      \
+	{                                                                     \
+	  asm volatile("mfhc1  %0, %1" : "=r"(i) : "f"(d));                   \
+	}                                                                     \
+      while (0)
+#  elif defined(__mips64)
+#    define GET_HIGH_WORD(i, d)                                               \
+      do                                                                      \
+	{                                                                     \
+	  long long di;                                                       \
+	  asm volatile("dmfc1  %0, %1" : "=r"(di) : "f"(d));                  \
+	  i = di >> 32;                                                       \
+	}                                                                     \
+      while (0)
+#  else
+#    define GET_HIGH_WORD(i, d)                                               \
+      do                                                                      \
+	{                                                                     \
+	  long long tmp[1];                                                   \
+	  asm volatile("sdc1 %1, %0" : "=m"(tmp) : "f"(d));                   \
+	  (i) = tmp[0] >> 32;                                                 \
+	}                                                                     \
+      while (0)
+#  endif
+#endif /* __mips_hard_float && !__mips_single_float */
+
+#endif /* MIPS_MATH_PRIVATE_H */
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/6] MIPS/math: Implement optimized issignaling(f)
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
  2024-05-13  8:14 ` [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf YunQiang Su
  2024-05-13  8:14 ` [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-23 14:37   ` Adhemerval Zanella Netto
  2024-05-13  8:14 ` [PATCH 4/6] MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f) YunQiang Su
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

MIPSr6 introduces class.fmt instructions, which can help us to
determine whether a number is sNAN.

We define __mips_issignaling(f) as always inline in mips/math_private.h,
and call them in s_issignaling(f).c.  Issignaling operation is also used
by some other functions, such as fmax.  Inlining it can introduce better
codesize and performance, due to libcall may issue some stack operations.

	* sysdeps/mips/fpu_control.h: Define FCLASS constants.
	* sysdeps/mips/ieee754/s_issignaling.c
	* sysdeps/mips/ieee754/s_issignalingf.c
	* sysdeps/mips/math_private.h: Define __mips_issignaling(f).

Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
---
 sysdeps/mips/fpu_control.h            | 17 +++++++
 sysdeps/mips/ieee754/s_issignaling.c  | 28 ++++++++++++
 sysdeps/mips/ieee754/s_issignalingf.c | 27 +++++++++++
 sysdeps/mips/math_private.h           | 65 +++++++++++++++++++++++++++
 4 files changed, 137 insertions(+)
 create mode 100644 sysdeps/mips/ieee754/s_issignaling.c
 create mode 100644 sysdeps/mips/ieee754/s_issignalingf.c

diff --git a/sysdeps/mips/fpu_control.h b/sysdeps/mips/fpu_control.h
index 3ceb34fc25..086293117e 100644
--- a/sysdeps/mips/fpu_control.h
+++ b/sysdeps/mips/fpu_control.h
@@ -127,6 +127,23 @@ extern void __mips_fpu_setcw (fpu_control_t) __THROW;
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;
 
+#  define _FCLASS_SNAN (1 << 0)
+#  define _FCLASS_QNAN (1 << 1)
+#  define _FCLASS_MINF (1 << 2)
+#  define _FCLASS_MNORM (1 << 3)
+#  define _FCLASS_MSUBNORM (1 << 4)
+#  define _FCLASS_MZERO (1 << 5)
+#  define _FCLASS_PINF (1 << 6)
+#  define _FCLASS_PNORM (1 << 7)
+#  define _FCLASS_PSUBNORM (1 << 8)
+#  define _FCLASS_PZERO (1 << 9)
+
+#  define _FCLASS_ZERO (_FCLASS_MZERO | _FCLASS_PZERO)
+#  define _FCLASS_SUBNORM (_FCLASS_MSUBNORM | _FCLASS_PSUBNORM)
+#  define _FCLASS_NORM (_FCLASS_MNORM | _FCLASS_PNORM)
+#  define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF)
+#  define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN)
+
 #endif /* __mips_soft_float */
 
 #endif	/* fpu_control.h */
diff --git a/sysdeps/mips/ieee754/s_issignaling.c b/sysdeps/mips/ieee754/s_issignaling.c
new file mode 100644
index 0000000000..3bf65f07a5
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_issignaling.c
@@ -0,0 +1,28 @@
+/* issignaling().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <fenv_private.h>
+#include <math_private.h>
+
+int
+__issignaling (double x)
+{
+  return __mips_issignaling (x);
+}
+libm_hidden_def (__issignaling)
diff --git a/sysdeps/mips/ieee754/s_issignalingf.c b/sysdeps/mips/ieee754/s_issignalingf.c
new file mode 100644
index 0000000000..14863595bc
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_issignalingf.c
@@ -0,0 +1,27 @@
+/* issignalingf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__issignalingf (float x)
+{
+  return __mips_issignalingf (x);
+}
+libm_hidden_def (__issignalingf)
diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h
index 4da8b0c2d9..6c388ddb64 100644
--- a/sysdeps/mips/math_private.h
+++ b/sysdeps/mips/math_private.h
@@ -53,4 +53,69 @@
 #  endif
 #endif /* __mips_hard_float && !__mips_single_float */
 
+/* Copy from sysdeps/ieee754/flt-32/s_issignalingf.c.
+   Function call can introduce lots for stack operations.  Inline can even
+   reduce codesize.  */
+static __always_inline int
+__mips_issignalingf (float x)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float c;
+  int ret;
+  asm volatile("class.s %0, %1" : "=f"(c) : "f"(x));
+  asm volatile("mfc1 %0, %1" : "=r"(ret) : "f"(c));
+  return ret & _FCLASS_SNAN;
+#else
+  uint32_t xi;
+  GET_FLOAT_WORD (xi, x);
+#  if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (xi & 0x7fc00000) == 0x7fc00000;
+#  else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  xi ^= 0x00400000;
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (xi & 0x7fffffff) > 0x7fc00000;
+#  endif
+#endif
+}
+
+/* Copy from sysdeps/ieee754/dbl-64/s_issignaling.c.
+   Function call can introduce lots for stack operations.  Inline can even
+   reduce codesize.  */
+static __always_inline int
+__mips_issignaling (double x)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double c;
+  int ret;
+  asm volatile("class.d %0, %1" : "=f"(c) : "f"(x));
+  asm volatile("mfc1 %0, %1" : "=r"(ret) : "f"(c));
+  return ret & _FCLASS_SNAN;
+#else
+  uint32_t xi;
+  GET_HIGH_WORD (xi, x);
+#  if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
+  /* We only have to care about the high-order bit of x's significand, because
+     having it set (sNaN) already makes the significand different from that
+     used to designate infinity.  */
+  return (xi & UINT32_C (0x7ff80000)) == UINT32_C (0x7ff80000);
+#  else
+  /* To keep the following comparison simple, toggle the quiet/signaling bit,
+     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
+     common practice for IEEE 754-1985).  */
+  xi ^= UINT32_C (0x00080000);
+  /* We have to compare for greater (instead of greater or equal), because x's
+     significand being all-zero designates infinity not NaN.  */
+  return (xi & UINT32_C (0x7fffffff)) > UINT32_C (0x7ff80000);
+#  endif
+#endif
+}
+
 #endif /* MIPS_MATH_PRIVATE_H */
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/6] MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f)
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
                   ` (2 preceding siblings ...)
  2024-05-13  8:14 ` [PATCH 3/6] MIPS/math: Implement optimized issignaling(f) YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-13  8:14 ` [PATCH 5/6] MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f) YunQiang Su
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

MIPSr6 defines max/maxa/min/mina instructions, which have slight
different with fmaximum/fminimum: return the number instead of NAN if
NUM vs NAN.  Detecting NAN is required before these instructions.

Another problem of the generic implemention for MIPS is that, it
use copysign for +0/-0 problem.  In fact we can use GET_HIGH_WORD or
GET_FLOAT_WORD, and then determine by the sign bit:

  int32_t xi;
  GET_HIGH_WORD (xi, x);
  return (xi < 0 ? y : x);

GET_HIGH_WORD/GET_FLOAT_WORD are much more friendly to MIPS FPU.
We can use `mfhc1` to GET_HIGH_WORD, and `mfc1` to GET_FLOAT_WORD.

Since the abs.fmt instructions will signal if one operand is qNAN or
sNaN, M_FABS, aka __builtin_fabs will issue at least 4 instructions
(mfc1/ext/ins/mtc1).  So detecting NaN is also required.

	* sysdeps/mips/ieee754/s_fmaximum.c
	* sysdeps/mips/ieee754/s_fmaximum_mag.c
	* sysdeps/mips/ieee754/s_fmaximum_magf.c
	* sysdeps/mips/ieee754/s_fmaximumf.c
	* sysdeps/mips/ieee754/s_fminimum.c
	* sysdeps/mips/ieee754/s_fminimum_mag.c
	* sysdeps/mips/ieee754/s_fminimum_magf.c
	* sysdeps/mips/ieee754/s_fminimumf.c

Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
---
 sysdeps/mips/ieee754/s_fmaximum.c      | 48 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximum_mag.c  | 57 ++++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximum_magf.c | 55 +++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximumf.c     | 46 +++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum.c      | 48 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_mag.c  | 57 ++++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_magf.c | 55 +++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimumf.c     | 46 +++++++++++++++++++++
 8 files changed, 412 insertions(+)
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_magf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximumf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_magf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimumf.c

diff --git a/sysdeps/mips/ieee754/s_fmaximum.c b/sysdeps/mips/ieee754/s_fmaximum.c
new file mode 100644
index 0000000000..5a1e6a0313
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum.c
@@ -0,0 +1,48 @@
+/* fmaximum().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fmaximum (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  /* MAX.d returns NUM if NUM vs qNAN.  */
+  if (isunordered (x, y))
+    return x + y;
+  double ret;
+  asm volatile("max.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreater (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+  if (isunordered (x, y))
+    return x + y;
+
+  int32_t xi;
+  GET_HIGH_WORD (xi, x);
+  return (xi < 0 ? y : x);
+#endif
+}
+
+libm_alias_double (__fmaximum, fmaximum)
diff --git a/sysdeps/mips/ieee754/s_fmaximum_mag.c b/sysdeps/mips/ieee754/s_fmaximum_mag.c
new file mode 100644
index 0000000000..0eac275167
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_mag.c
@@ -0,0 +1,57 @@
+/* fmaximum_mag().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+#include <math-type-macros-double.h>
+
+double
+__fmaximum_mag (double x, double y)
+{
+  /* MAXA.d return NUM if NUM vs qNAN.  ABS.d signals both sNAN and qNAN on
+     pre-R5.  */
+  if (isunordered (x, y))
+    return x + y;
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("maxa.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  double ax;
+  double ay;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+  asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return x;
+  else if (isless (ax, ay))
+    return y;
+
+  int32_t xi;
+  GET_HIGH_WORD (xi, x);
+  return (xi < 0 ? y : x);
+#endif
+}
+
+libm_alias_double (__fmaximum_mag, fmaximum_mag)
diff --git a/sysdeps/mips/ieee754/s_fmaximum_magf.c b/sysdeps/mips/ieee754/s_fmaximum_magf.c
new file mode 100644
index 0000000000..dd871bac07
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_magf.c
@@ -0,0 +1,55 @@
+/* fmaximum_magf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math-type-macros-float.h>
+
+float
+__fmaximum_magf (float x, float y)
+{
+  /* MAXA.s return NUM if NUM vs qNAN.  ABS.s signals both sNAN and qNAN on
+     pre-R5.  */
+  if (isunordered (x, y))
+    return x + y;
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("maxa.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  float ax;
+  float ay;
+#  if defined(__mips_hard_float)
+  asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return x;
+  else if (isless (ax, ay))
+    return y;
+
+  int32_t xi;
+  GET_FLOAT_WORD (xi, x);
+  return (xi < 0 ? y : x);
+#endif
+}
+
+libm_alias_float (__fmaximum_mag, fmaximum_mag)
diff --git a/sysdeps/mips/ieee754/s_fmaximumf.c b/sysdeps/mips/ieee754/s_fmaximumf.c
new file mode 100644
index 0000000000..a266ee76b6
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximumf.c
@@ -0,0 +1,46 @@
+/* fmaximumf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+
+float
+__fmaximumf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  /* MAX.s returns NUM if NUM vs qNAN.  */
+  if (isunordered (x, y))
+    return x + y;
+  float ret;
+  asm volatile("max.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreater (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+  if (isunordered (x, y))
+    return x + y;
+
+  int32_t xi;
+  GET_FLOAT_WORD (xi, x);
+  return (xi < 0 ? y : x);
+#endif
+}
+
+libm_alias_float (__fmaximum, fmaximum)
diff --git a/sysdeps/mips/ieee754/s_fminimum.c b/sysdeps/mips/ieee754/s_fminimum.c
new file mode 100644
index 0000000000..083da390ae
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum.c
@@ -0,0 +1,48 @@
+/* fminimum().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fminimum (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  /* MIN.d returns NUM if NUM vs qNAN.  */
+  if (isunordered (x, y))
+    return x + y;
+  double ret;
+  asm volatile("min.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreater (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+  if (isunordered (x, y))
+    return x + y;
+
+  int32_t xi;
+  GET_HIGH_WORD (xi, x);
+  return (xi < 0 ? x : y);
+#endif
+}
+
+libm_alias_double (__fminimum, fminimum)
diff --git a/sysdeps/mips/ieee754/s_fminimum_mag.c b/sysdeps/mips/ieee754/s_fminimum_mag.c
new file mode 100644
index 0000000000..7adaa1c279
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_mag.c
@@ -0,0 +1,57 @@
+/* fminimum_mag().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+#include <math-type-macros-double.h>
+
+double
+__fminimum_mag (double x, double y)
+{
+  /* MINA.d return NUM if NUM vs qNAN.  ABS.d signals both sNAN and qNAN on
+     pre-R5.  */
+  if (isunordered (x, y))
+    return x + y;
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("mina.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  double ax;
+  double ay;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+  asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return y;
+  else if (isless (ax, ay))
+    return x;
+
+  int32_t xi;
+  GET_HIGH_WORD (xi, x);
+  return (xi < 0 ? x : y);
+#endif
+}
+
+libm_alias_double (__fminimum_mag, fminimum_mag)
diff --git a/sysdeps/mips/ieee754/s_fminimum_magf.c b/sysdeps/mips/ieee754/s_fminimum_magf.c
new file mode 100644
index 0000000000..6839e2914d
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_magf.c
@@ -0,0 +1,55 @@
+/* fminimum_magf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math-type-macros-float.h>
+
+float
+__fminimum_magf (float x, float y)
+{
+  /* MAXA.s return NUM if NUM vs qNAN.  ABS.s signals both sNAN and qNAN on
+     pre-R5.  */
+  if (isunordered (x, y))
+    return x + y;
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("mina.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  float ax;
+  float ay;
+#  if defined(__mips_hard_float)
+  asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return y;
+  else if (isless (ax, ay))
+    return x;
+
+  int32_t xi;
+  GET_FLOAT_WORD (xi, x);
+  return (xi < 0 ? x : y);
+#endif
+}
+
+libm_alias_float (__fminimum_mag, fminimum_mag)
diff --git a/sysdeps/mips/ieee754/s_fminimumf.c b/sysdeps/mips/ieee754/s_fminimumf.c
new file mode 100644
index 0000000000..f37ca1c23b
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimumf.c
@@ -0,0 +1,46 @@
+/* fminimumf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+
+float
+__fminimumf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  /* MIN.s returns NUM if NUM vs qNAN.  */
+  if (isunordered (x, y))
+    return x + y;
+  float ret;
+  asm volatile("min.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreater (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+  if (isunordered (x, y))
+    return x + y;
+
+  int xi;
+  GET_FLOAT_WORD (xi, x);
+  return (xi < 0 ? x : y);
+#endif
+}
+
+libm_alias_float (__fminimum, fminimum)
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 5/6] MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f)
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
                   ` (3 preceding siblings ...)
  2024-05-13  8:14 ` [PATCH 4/6] MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f) YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-13  8:14 ` [PATCH 6/6] MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f) YunQiang Su
  2024-05-22 13:21 ` [PATCH 0/6] MIPS: Improve math YunQiang Su
  6 siblings, 0 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

MIPSr6 instroduces min/mina/max/maxa instructions, which
can be use for fmax(mag)(f)/fmin(mag) directly.

For other cases, we continue to use the generic implemention,
with our defined __mips_issignaling inline functions.

Since abs.fmt instructions will signal for NAN, so we need to
be sure that the operands is orderable first.

	* sysdeps/mips/ieee754/s_fmax.c
	* sysdeps/mips/ieee754/s_fmaxf.c
	* sysdeps/mips/ieee754/s_fmin.c
	* sysdeps/mips/ieee754/s_fminf.c
	* sysdeps/mips/ieee754/s_fmaxmag.c
	* sysdeps/mips/ieee754/s_fmaxmagf.c
	* sysdeps/mips/ieee754/s_fminmag.c
	* sysdeps/mips/ieee754/s_fminmagf.c
---
 sysdeps/mips/ieee754/s_fmax.c     | 45 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaxf.c    | 43 +++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaxmag.c  | 62 +++++++++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaxmagf.c | 61 ++++++++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmin.c     | 44 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminf.c    | 43 +++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminmag.c  | 62 +++++++++++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminmagf.c | 61 ++++++++++++++++++++++++++++++
 8 files changed, 421 insertions(+)
 create mode 100644 sysdeps/mips/ieee754/s_fmax.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxmag.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaxmagf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmin.c
 create mode 100644 sysdeps/mips/ieee754/s_fminf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminmag.c
 create mode 100644 sysdeps/mips/ieee754/s_fminmagf.c

diff --git a/sysdeps/mips/ieee754/s_fmax.c b/sysdeps/mips/ieee754/s_fmax.c
new file mode 100644
index 0000000000..190ca4a885
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmax.c
@@ -0,0 +1,45 @@
+/* fmax().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fmax (double x, double y)
+{
+
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("max.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreaterequal (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+
+  if (__mips_issignaling (x) || __mips_issignaling (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+#endif
+}
+
+libm_alias_double (__fmax, fmax)
diff --git a/sysdeps/mips/ieee754/s_fmaxf.c b/sysdeps/mips/ieee754/s_fmaxf.c
new file mode 100644
index 0000000000..358ddefc17
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaxf.c
@@ -0,0 +1,43 @@
+/* fmaxf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+
+float
+__fmaxf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("max.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreaterequal (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+#endif
+
+  if (__mips_issignalingf (x) || __mips_issignalingf (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_float (__fmax, fmax)
diff --git a/sysdeps/mips/ieee754/s_fmaxmag.c b/sysdeps/mips/ieee754/s_fmaxmag.c
new file mode 100644
index 0000000000..3f1b32afe9
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaxmag.c
@@ -0,0 +1,62 @@
+/* fmaxmag().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+#include <math-type-macros-double.h>
+
+double
+__fmaxmag (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("maxa.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  /* ABS.d signals both sNAN and qNAN on pre-R5.  */
+  if (!isunordered (x, y))
+    {
+      double ax;
+      double ay;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+      asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+      asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+      ax = M_FABS (x);
+      ay = M_FABS (y);
+#  endif
+      if (isgreater (ax, ay))
+	return x;
+      else if (isless (ax, ay))
+	return y;
+
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+#endif /* __mips_isa_rev >= 6 */
+
+  if (__mips_issignaling (x) || __mips_issignaling (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_double (__fmaxmag, fmaxmag)
diff --git a/sysdeps/mips/ieee754/s_fmaxmagf.c b/sysdeps/mips/ieee754/s_fmaxmagf.c
new file mode 100644
index 0000000000..cfa44c773d
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaxmagf.c
@@ -0,0 +1,61 @@
+/* fmaxmagf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+#include <math-type-macros-float.h>
+
+float
+__fmaxmagf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("maxa.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  /* ABS.s signals both sNAN and qNAN on pre-R5.  */
+  if (!isunordered (x, y))
+    {
+      float ax;
+      float ay;
+#  if defined(__mips_hard_float)
+      asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+      asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+      ax = M_FABS (x);
+      ay = M_FABS (y);
+#  endif
+      if (isgreater (ax, ay))
+	return x;
+      else if (isless (ax, ay))
+	return y;
+
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+#endif /* __mips_isa_rev >= 6 */
+
+  if (__mips_issignalingf (x) || __mips_issignalingf (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_float (__fmaxmag, fmaxmag)
diff --git a/sysdeps/mips/ieee754/s_fmin.c b/sysdeps/mips/ieee754/s_fmin.c
new file mode 100644
index 0000000000..56ff7100c4
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmin.c
@@ -0,0 +1,44 @@
+/* fmin().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fmin (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("min.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreaterequal (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+#endif
+
+  if (__mips_issignaling (x) || __mips_issignaling (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_double (__fmin, fmin)
diff --git a/sysdeps/mips/ieee754/s_fminf.c b/sysdeps/mips/ieee754/s_fminf.c
new file mode 100644
index 0000000000..55c56183c1
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminf.c
@@ -0,0 +1,43 @@
+/* fminf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+
+float
+__fminf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("min.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  if (isgreaterequal (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+#endif
+
+  if (__mips_issignalingf (x) || __mips_issignalingf (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_float (__fmin, fmin)
diff --git a/sysdeps/mips/ieee754/s_fminmag.c b/sysdeps/mips/ieee754/s_fminmag.c
new file mode 100644
index 0000000000..bd115675f4
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminmag.c
@@ -0,0 +1,62 @@
+/* fminmag().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math-type-macros-double.h>
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fminmag (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("mina.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  /* ABS.d signals both sNAN and qNAN on pre-R5.  */
+  if (!isunordered (x, y))
+    {
+      double ax;
+      double ay;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+      asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+      asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+      ax = M_FABS (x);
+      ay = M_FABS (y);
+#  endif
+      if (isgreater (ax, ay))
+	return y;
+      else if (isless (ax, ay))
+	return x;
+
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+#endif /* __mips_isa_rev >= 6 */
+
+  if (__mips_issignaling (x) || __mips_issignaling (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_double (__fminmag, fminmag)
diff --git a/sysdeps/mips/ieee754/s_fminmagf.c b/sysdeps/mips/ieee754/s_fminmagf.c
new file mode 100644
index 0000000000..8997ef05f7
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminmagf.c
@@ -0,0 +1,61 @@
+/* fminmagf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+#include <math-type-macros-float.h>
+
+float
+__fminmagf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("mina.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  return ret;
+#else
+  /* ABS.s signals both sNAN and qNAN on pre-R5.  */
+  if (!isunordered (x, y))
+    {
+      float ax;
+      float ay;
+#  if defined(__mips_hard_float)
+      asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+      asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+      ax = M_FABS (x);
+      ay = M_FABS (y);
+#  endif
+      if (isgreater (ax, ay))
+	return y;
+      else if (isless (ax, ay))
+	return x;
+
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+#endif
+
+  if (__mips_issignalingf (x) || __mips_issignalingf (y))
+    return x + y;
+  else
+    return isnan (y) ? x : y;
+}
+
+libm_alias_float (__fminmag, fminmag)
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 6/6] MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f)
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
                   ` (4 preceding siblings ...)
  2024-05-13  8:14 ` [PATCH 5/6] MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f) YunQiang Su
@ 2024-05-13  8:14 ` YunQiang Su
  2024-05-22 13:21 ` [PATCH 0/6] MIPS: Improve math YunQiang Su
  6 siblings, 0 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-13  8:14 UTC (permalink / raw)
  To: libc-alpha

MIPSr6 instroduces min.s/min.d/max.s/max.d instructions, which have
slight different with fmaximum_num, when one operand is sNaN.
In this case, these instructions will return qNaN, while fmaximum_num
requires another operand.

For pre-r6 with hardfloat, we determine whether NAN is present, so that
we can use abs.fmt, which can boost performance.  We also use
GET_HIGH_WORD/GET_FLOAT_WORD instead of copysign for the equal cases.

	* sysdeps/mips/ieee754/s_fmaximum_num.c
	* sysdeps/mips/ieee754/s_fmaximum_numf.c
	* sysdeps/mips/ieee754/s_fminimum_num.c
	* sysdeps/mips/ieee754/s_fminimum_numf.c
	* sysdeps/mips/ieee754/s_fmaximum_mag_num.c
	* sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
	* sysdeps/mips/ieee754/s_fminimum_mag_num.c
	* sysdeps/mips/ieee754/s_fminimum_mag_numf.c

Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
---
 sysdeps/mips/ieee754/s_fmaximum_mag_num.c  | 65 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximum_mag_numf.c | 64 +++++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximum_num.c      | 54 ++++++++++++++++++
 sysdeps/mips/ieee754/s_fmaximum_numf.c     | 53 ++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_mag_num.c  | 65 ++++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_mag_numf.c | 64 +++++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_num.c      | 54 ++++++++++++++++++
 sysdeps/mips/ieee754/s_fminimum_numf.c     | 53 ++++++++++++++++++
 8 files changed, 472 insertions(+)
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fmaximum_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_numf.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_num.c
 create mode 100644 sysdeps/mips/ieee754/s_fminimum_numf.c

diff --git a/sysdeps/mips/ieee754/s_fmaximum_mag_num.c b/sysdeps/mips/ieee754/s_fmaximum_mag_num.c
new file mode 100644
index 0000000000..83e9a28bed
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_mag_num.c
@@ -0,0 +1,65 @@
+/* fmaximum_mag_num().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+#include <math-type-macros-double.h>
+
+double
+__fmaximum_mag_num (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("maxa.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignaling (x))
+	ret = x;
+      else if (!__mips_issignaling (y))
+	ret = y;
+    }
+  return ret;
+#else
+  double ax;
+  double ay;
+  /* ABS.d signals both sNAN and qNAN on pre-R5.  */
+  if (isunordered (x, y))
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+  asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return x;
+  else if (isless (ax, ay))
+    return y;
+  else
+    {
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+#endif
+}
+
+libm_alias_double (__fmaximum_mag_num, fmaximum_mag_num)
diff --git a/sysdeps/mips/ieee754/s_fmaximum_mag_numf.c b/sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
new file mode 100644
index 0000000000..c0e6589c00
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
@@ -0,0 +1,64 @@
+/* fmaximum_mag_numf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+#include <math-type-macros-float.h>
+
+float
+__fmaximum_mag_numf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("maxa.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignalingf (x))
+	ret = x;
+      else if (!__mips_issignalingf (y))
+	ret = y;
+    }
+  return ret;
+#else
+  float ax;
+  float ay;
+  /* ABS.s signals both sNAN and qNAN on pre-R5.  */
+  if (isunordered (x, y))
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#  if defined(__mips_hard_float)
+  asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return x;
+  else if (isless (ax, ay))
+    return y;
+  else
+    {
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+#endif
+}
+
+libm_alias_float (__fmaximum_mag_num, fmaximum_mag_num)
diff --git a/sysdeps/mips/ieee754/s_fmaximum_num.c b/sysdeps/mips/ieee754/s_fmaximum_num.c
new file mode 100644
index 0000000000..85816a12be
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_num.c
@@ -0,0 +1,54 @@
+/* fmaximum_num().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fmaximum_num (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("max.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignaling (x))
+	ret = x;
+      else if (!__mips_issignaling (y))
+	ret = y;
+    }
+  return ret;
+#else
+  if (isgreater (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+  else if (x == y)
+    {
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+  else
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#endif
+}
+
+libm_alias_double (__fmaximum_num, fmaximum_num)
diff --git a/sysdeps/mips/ieee754/s_fmaximum_numf.c b/sysdeps/mips/ieee754/s_fmaximum_numf.c
new file mode 100644
index 0000000000..1047f354be
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fmaximum_numf.c
@@ -0,0 +1,53 @@
+/* fmaximum_numf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+
+float
+__fmaximum_numf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("max.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignalingf (x))
+	ret = x;
+      if (!__mips_issignalingf (y))
+	ret = y;
+    }
+  return ret;
+#else
+  if (isgreater (x, y))
+    return x;
+  else if (isless (x, y))
+    return y;
+  else if (x == y)
+    {
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? y : x);
+    }
+  else
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#endif
+}
+
+libm_alias_float (__fmaximum_num, fmaximum_num)
diff --git a/sysdeps/mips/ieee754/s_fminimum_mag_num.c b/sysdeps/mips/ieee754/s_fminimum_mag_num.c
new file mode 100644
index 0000000000..a6df931aaf
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_mag_num.c
@@ -0,0 +1,65 @@
+/* fminimum_mag_num().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+#include <math-type-macros-double.h>
+
+double
+__fminimum_mag_num (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("mina.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignaling (x))
+	ret = x;
+      else if (!__mips_issignaling (y))
+	ret = y;
+    }
+  return ret;
+#else
+  double ax;
+  double ay;
+  /* ABS.d signals both sNAN and qNAN on pre-R5.  */
+  if (isunordered (x, y))
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#  if defined(__mips_hard_float) && !defined(__mips_single_float)
+  asm volatile("abs.d	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.d	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return y;
+  else if (isless (ax, ay))
+    return x;
+  else
+    {
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+#endif
+}
+
+libm_alias_double (__fminimum_mag_num, fminimum_mag_num)
diff --git a/sysdeps/mips/ieee754/s_fminimum_mag_numf.c b/sysdeps/mips/ieee754/s_fminimum_mag_numf.c
new file mode 100644
index 0000000000..74d189b380
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_mag_numf.c
@@ -0,0 +1,64 @@
+/* fminimum_mag_numf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+#include <math-type-macros-float.h>
+
+float
+__fminimum_mag_numf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("mina.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignalingf (x))
+	ret = x;
+      else if (!__mips_issignalingf (y))
+	ret = y;
+    }
+  return ret;
+#else
+  float ax;
+  float ay;
+  /* ABS.s signals both sNAN and qNAN on pre-R5.  */
+  if (isunordered (x, y))
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#  if defined(__mips_hard_float)
+  asm volatile("abs.s	%0, %1" : "=f"(ax) : "f"(x));
+  asm volatile("abs.s	%0, %1" : "=f"(ay) : "f"(y));
+#  else
+  ax = M_FABS (x);
+  ay = M_FABS (y);
+#  endif
+  if (isgreater (ax, ay))
+    return y;
+  else if (isless (ax, ay))
+    return x;
+  else
+    {
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+#endif
+}
+
+libm_alias_float (__fminimum_mag_num, fminimum_mag_num)
diff --git a/sysdeps/mips/ieee754/s_fminimum_num.c b/sysdeps/mips/ieee754/s_fminimum_num.c
new file mode 100644
index 0000000000..62fd139d63
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_num.c
@@ -0,0 +1,54 @@
+/* fminimum_num().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-double.h>
+#include <math_private.h>
+
+double
+__fminimum_num (double x, double y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
+    && !defined(__mips_single_float)
+  double ret;
+  asm volatile("min.d	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignaling (x))
+	ret = x;
+      if (!__mips_issignaling (y))
+	ret = y;
+    }
+  return ret;
+#else
+  if (isgreater (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+  else if (x == y)
+    {
+      int32_t xi;
+      GET_HIGH_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+  else
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#endif
+}
+
+libm_alias_double (__fminimum_num, fminimum_num)
diff --git a/sysdeps/mips/ieee754/s_fminimum_numf.c b/sysdeps/mips/ieee754/s_fminimum_numf.c
new file mode 100644
index 0000000000..37d66ff6fa
--- /dev/null
+++ b/sysdeps/mips/ieee754/s_fminimum_numf.c
@@ -0,0 +1,53 @@
+/* fminimum_numf().  MIPS version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <math.h>
+#include <libm-alias-float.h>
+#include <math_private.h>
+
+float
+__fminimum_numf (float x, float y)
+{
+#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
+  float ret;
+  asm volatile("min.s	%0, %1, %2" : "=f"(ret) : "f"(x), "f"(y));
+  if (isnan (ret))
+    {
+      if (!__mips_issignalingf (x))
+	ret = x;
+      if (!__mips_issignalingf (y))
+	ret = y;
+    }
+  return ret;
+#else
+  if (isgreater (x, y))
+    return y;
+  else if (isless (x, y))
+    return x;
+  else if (x == y)
+    {
+      int32_t xi;
+      GET_FLOAT_WORD (xi, x);
+      return (xi < 0 ? x : y);
+    }
+  else
+    return isnan (y) ? (isnan (x) ? x + y : x) : y;
+#endif
+}
+
+libm_alias_float (__fminimum_num, fminimum_num)
-- 
2.39.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/6] MIPS: Improve math
  2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
                   ` (5 preceding siblings ...)
  2024-05-13  8:14 ` [PATCH 6/6] MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f) YunQiang Su
@ 2024-05-22 13:21 ` YunQiang Su
  6 siblings, 0 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-22 13:21 UTC (permalink / raw)
  To: libc-alpha

YunQiang Su <syq@gcc.gnu.org> 于2024年5月13日周一 16:14写道:
>
> YunQiang Su (6):
>   MIPSr6/math: Use builtin fma and fmaf
>   MIPS/math: Define port-specific GET_HIGH_WORD
>   MIPS/math: Implement optimized issignaling(f)
>   MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f)
>   MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f)
>   MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f)
>

ping

>  sysdeps/mips/fpu/math-use-builtins-fma.h   |  13 +++
>  sysdeps/mips/fpu_control.h                 |  17 +++
>  sysdeps/mips/ieee754/s_fmax.c              |  45 ++++++++
>  sysdeps/mips/ieee754/s_fmaxf.c             |  43 ++++++++
>  sysdeps/mips/ieee754/s_fmaximum.c          |  48 ++++++++
>  sysdeps/mips/ieee754/s_fmaximum_mag.c      |  57 ++++++++++
>  sysdeps/mips/ieee754/s_fmaximum_mag_num.c  |  65 +++++++++++
>  sysdeps/mips/ieee754/s_fmaximum_mag_numf.c |  64 +++++++++++
>  sysdeps/mips/ieee754/s_fmaximum_magf.c     |  55 ++++++++++
>  sysdeps/mips/ieee754/s_fmaximum_num.c      |  54 +++++++++
>  sysdeps/mips/ieee754/s_fmaximum_numf.c     |  53 +++++++++
>  sysdeps/mips/ieee754/s_fmaximumf.c         |  46 ++++++++
>  sysdeps/mips/ieee754/s_fmaxmag.c           |  62 +++++++++++
>  sysdeps/mips/ieee754/s_fmaxmagf.c          |  61 +++++++++++
>  sysdeps/mips/ieee754/s_fmin.c              |  44 ++++++++
>  sysdeps/mips/ieee754/s_fminf.c             |  43 ++++++++
>  sysdeps/mips/ieee754/s_fminimum.c          |  48 ++++++++
>  sysdeps/mips/ieee754/s_fminimum_mag.c      |  57 ++++++++++
>  sysdeps/mips/ieee754/s_fminimum_mag_num.c  |  65 +++++++++++
>  sysdeps/mips/ieee754/s_fminimum_mag_numf.c |  64 +++++++++++
>  sysdeps/mips/ieee754/s_fminimum_magf.c     |  55 ++++++++++
>  sysdeps/mips/ieee754/s_fminimum_num.c      |  54 +++++++++
>  sysdeps/mips/ieee754/s_fminimum_numf.c     |  53 +++++++++
>  sysdeps/mips/ieee754/s_fminimumf.c         |  46 ++++++++
>  sysdeps/mips/ieee754/s_fminmag.c           |  62 +++++++++++
>  sysdeps/mips/ieee754/s_fminmagf.c          |  61 +++++++++++
>  sysdeps/mips/ieee754/s_issignaling.c       |  28 +++++
>  sysdeps/mips/ieee754/s_issignalingf.c      |  27 +++++
>  sysdeps/mips/math_private.h                | 121 +++++++++++++++++++++
>  29 files changed, 1511 insertions(+)
>  create mode 100644 sysdeps/mips/fpu/math-use-builtins-fma.h
>  create mode 100644 sysdeps/mips/ieee754/s_fmax.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaxf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_num.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_mag_numf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_magf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_num.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximum_numf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaximumf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaxmag.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmaxmagf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fmin.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_num.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_mag_numf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_magf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_num.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimum_numf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminimumf.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminmag.c
>  create mode 100644 sysdeps/mips/ieee754/s_fminmagf.c
>  create mode 100644 sysdeps/mips/ieee754/s_issignaling.c
>  create mode 100644 sysdeps/mips/ieee754/s_issignalingf.c
>  create mode 100644 sysdeps/mips/math_private.h
>
> --
> 2.39.2
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf
  2024-05-13  8:14 ` [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf YunQiang Su
@ 2024-05-22 13:42   ` Adhemerval Zanella Netto
  2024-05-25 11:55     ` YunQiang Su
  0 siblings, 1 reply; 13+ messages in thread
From: Adhemerval Zanella Netto @ 2024-05-22 13:42 UTC (permalink / raw)
  To: YunQiang Su, libc-alpha



On 13/05/24 05:14, YunQiang Su wrote:
> MIPSr6 has MADDF.s/MADDF.d instructions, which are fused.
> 
> In MIPS ISA, double support can be subsetted.  Only FMAF is enabled
> for this case.
> 
> 	* sysdeps/mips/fpu/math-use-builtins-fma.h
> 
> Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
> ---
>  sysdeps/mips/fpu/math-use-builtins-fma.h | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>  create mode 100644 sysdeps/mips/fpu/math-use-builtins-fma.h
> 
> diff --git a/sysdeps/mips/fpu/math-use-builtins-fma.h b/sysdeps/mips/fpu/math-use-builtins-fma.h
> new file mode 100644
> index 0000000000..6e296fd4c0
> --- /dev/null
> +++ b/sysdeps/mips/fpu/math-use-builtins-fma.h
> @@ -0,0 +1,13 @@
> +#if __mips_isa_rev >= 6
> +#  if defined(__mips_single_float)

Usually for a single case we write as '#ifdef __mips_single_float,
also the identation is a single space.

The rest look ok, gcc seems to emit the the MADDF.X even with
pretty old versions (gcc 5.5.0).

> +#    define USE_FMA_BUILTIN 0
> +#  else
> +#    define USE_FMA_BUILTIN 1
> +#  endif
> +#  define USE_FMAF_BUILTIN 1
> +#else
> +#  define USE_FMA_BUILTIN 0
> +#  define USE_FMAF_BUILTIN 0
> +#endif
> +#define USE_FMAL_BUILTIN 0
> +#define USE_FMAF128_BUILTIN 0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD
  2024-05-13  8:14 ` [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD YunQiang Su
@ 2024-05-22 18:36   ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 13+ messages in thread
From: Adhemerval Zanella Netto @ 2024-05-22 18:36 UTC (permalink / raw)
  To: YunQiang Su, libc-alpha



On 13/05/24 05:14, YunQiang Su wrote:
> The generic implemention may issue some unneeded stack store and
> load operations.
> 
> 	* sysdeps/mips/math_private.h
> 
> Signed-off-by: YunQiang Su <syq@gcc.gnu.org>

That's not what I see with a recent GCC [1] and such macros uses generic
code for fp to int transformation where it is expected that the compiler
have all the required information to handle it correctly (check 
4e7fbdd7c2884e8909ea8f2f59d52f7d0c699252 for why we removed such optimization
from x86_64 and if you still see issues the correct way is to fix it on
compiler).

[1] https://godbolt.org/z/7TdsY7b6v

> ---
>  sysdeps/mips/math_private.h | 56 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 56 insertions(+)
>  create mode 100644 sysdeps/mips/math_private.h
> 
> diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h
> new file mode 100644
> index 0000000000..4da8b0c2d9
> --- /dev/null
> +++ b/sysdeps/mips/math_private.h
> @@ -0,0 +1,56 @@
> +/* Copyright (C) 2024 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef MIPS_MATH_PRIVATE_H
> +#define MIPS_MATH_PRIVATE_H 1
> +
> +#include <math.h>
> +#include <nan-high-order-bit.h>
> +#include_next <math_private.h>
> +#include <fpu_control.h>
> +
> +#if defined(__mips_hard_float) && !defined(__mips_single_float)
> +#  undef GET_HIGH_WORD
> +#  if __mips_isa_rev >= 2
> +#    define GET_HIGH_WORD(i, d)                                               \
> +      do                                                                      \
> +	{                                                                     \
> +	  asm volatile("mfhc1  %0, %1" : "=r"(i) : "f"(d));                   \
> +	}                                                                     \
> +      while (0)
> +#  elif defined(__mips64)
> +#    define GET_HIGH_WORD(i, d)                                               \
> +      do                                                                      \
> +	{                                                                     \
> +	  long long di;                                                       \
> +	  asm volatile("dmfc1  %0, %1" : "=r"(di) : "f"(d));                  \
> +	  i = di >> 32;                                                       \
> +	}                                                                     \
> +      while (0)
> +#  else
> +#    define GET_HIGH_WORD(i, d)                                               \
> +      do                                                                      \
> +	{                                                                     \
> +	  long long tmp[1];                                                   \
> +	  asm volatile("sdc1 %1, %0" : "=m"(tmp) : "f"(d));                   \
> +	  (i) = tmp[0] >> 32;                                                 \
> +	}                                                                     \
> +      while (0)
> +#  endif
> +#endif /* __mips_hard_float && !__mips_single_float */
> +
> +#endif /* MIPS_MATH_PRIVATE_H */

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/6] MIPS/math: Implement optimized issignaling(f)
  2024-05-13  8:14 ` [PATCH 3/6] MIPS/math: Implement optimized issignaling(f) YunQiang Su
@ 2024-05-23 14:37   ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 13+ messages in thread
From: Adhemerval Zanella Netto @ 2024-05-23 14:37 UTC (permalink / raw)
  To: YunQiang Su, libc-alpha



On 13/05/24 05:14, YunQiang Su wrote:
> MIPSr6 introduces class.fmt instructions, which can help us to
> determine whether a number is sNAN.
> 
> We define __mips_issignaling(f) as always inline in mips/math_private.h,
> and call them in s_issignaling(f).c.  Issignaling operation is also used
> by some other functions, such as fmax.  Inlining it can introduce better
> codesize and performance, due to libcall may issue some stack operations.

We used to provide such internal inlines optimizations, which requires a lot 
of boilerplate code to inline alternative implementation of C standard symbols 
(such as isnan/isinf).  This tend of get really complicate to maintain, and it 
leads to worse outcomes once compilers start to optimize it way (by providing
proper builtins) since we need to either reimplement internally the symbol
or use a different name (that compiler can not map to the builtin).

Also recently, we started to use builtins more to implement such math symbol
(check the math-use-builtins-*), so the idea would to add support for the builtin
use on both dbl-64 and flt-32 issignaling, and enable it to use if compiler supports
it (afaik it was enabled as arch-independent way on gcc 13). Another possible
optimization is also to add a similar enablement on math/math.h, where if compiler
supports also route issignaling to its builtin (similar to isnan/isinf/etc.).

Then you can focus on optimizing the compiler code generation of issignaling
to the emit the class.s.

With all these in place there will be no need to internally re-implement the
symbol and it would be future-proof regarding compiler optimizations.

> 
> 	* sysdeps/mips/fpu_control.h: Define FCLASS constants.
> 	* sysdeps/mips/ieee754/s_issignaling.c
> 	* sysdeps/mips/ieee754/s_issignalingf.c
> 	* sysdeps/mips/math_private.h: Define __mips_issignaling(f).
> 
> Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
> ---
>  sysdeps/mips/fpu_control.h            | 17 +++++++
>  sysdeps/mips/ieee754/s_issignaling.c  | 28 ++++++++++++
>  sysdeps/mips/ieee754/s_issignalingf.c | 27 +++++++++++
>  sysdeps/mips/math_private.h           | 65 +++++++++++++++++++++++++++
>  4 files changed, 137 insertions(+)
>  create mode 100644 sysdeps/mips/ieee754/s_issignaling.c
>  create mode 100644 sysdeps/mips/ieee754/s_issignalingf.c
> 
> diff --git a/sysdeps/mips/fpu_control.h b/sysdeps/mips/fpu_control.h
> index 3ceb34fc25..086293117e 100644
> --- a/sysdeps/mips/fpu_control.h
> +++ b/sysdeps/mips/fpu_control.h
> @@ -127,6 +127,23 @@ extern void __mips_fpu_setcw (fpu_control_t) __THROW;
>  /* Default control word set at startup.  */
>  extern fpu_control_t __fpu_control;
>  
> +#  define _FCLASS_SNAN (1 << 0)
> +#  define _FCLASS_QNAN (1 << 1)
> +#  define _FCLASS_MINF (1 << 2)
> +#  define _FCLASS_MNORM (1 << 3)
> +#  define _FCLASS_MSUBNORM (1 << 4)
> +#  define _FCLASS_MZERO (1 << 5)
> +#  define _FCLASS_PINF (1 << 6)
> +#  define _FCLASS_PNORM (1 << 7)
> +#  define _FCLASS_PSUBNORM (1 << 8)
> +#  define _FCLASS_PZERO (1 << 9)
> +
> +#  define _FCLASS_ZERO (_FCLASS_MZERO | _FCLASS_PZERO)
> +#  define _FCLASS_SUBNORM (_FCLASS_MSUBNORM | _FCLASS_PSUBNORM)
> +#  define _FCLASS_NORM (_FCLASS_MNORM | _FCLASS_PNORM)
> +#  define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF)
> +#  define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN)
> +
>  #endif /* __mips_soft_float */
>  
>  #endif	/* fpu_control.h */
> diff --git a/sysdeps/mips/ieee754/s_issignaling.c b/sysdeps/mips/ieee754/s_issignaling.c
> new file mode 100644
> index 0000000000..3bf65f07a5
> --- /dev/null
> +++ b/sysdeps/mips/ieee754/s_issignaling.c
> @@ -0,0 +1,28 @@
> +/* issignaling().  MIPS version.
> +   Copyright (C) 2024 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <math.h>
> +#include <fenv_private.h>
> +#include <math_private.h>
> +
> +int
> +__issignaling (double x)
> +{
> +  return __mips_issignaling (x);
> +}
> +libm_hidden_def (__issignaling)
> diff --git a/sysdeps/mips/ieee754/s_issignalingf.c b/sysdeps/mips/ieee754/s_issignalingf.c
> new file mode 100644
> index 0000000000..14863595bc
> --- /dev/null
> +++ b/sysdeps/mips/ieee754/s_issignalingf.c
> @@ -0,0 +1,27 @@
> +/* issignalingf().  MIPS version.
> +   Copyright (C) 2024 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <math.h>
> +#include <math_private.h>
> +
> +int
> +__issignalingf (float x)
> +{
> +  return __mips_issignalingf (x);
> +}
> +libm_hidden_def (__issignalingf)
> diff --git a/sysdeps/mips/math_private.h b/sysdeps/mips/math_private.h
> index 4da8b0c2d9..6c388ddb64 100644
> --- a/sysdeps/mips/math_private.h
> +++ b/sysdeps/mips/math_private.h
> @@ -53,4 +53,69 @@
>  #  endif
>  #endif /* __mips_hard_float && !__mips_single_float */
>  
> +/* Copy from sysdeps/ieee754/flt-32/s_issignalingf.c.
> +   Function call can introduce lots for stack operations.  Inline can even
> +   reduce codesize.  */
> +static __always_inline int
> +__mips_issignalingf (float x)
> +{
> +#if __mips_isa_rev >= 6 && defined(__mips_hard_float)
> +  float c;
> +  int ret;
> +  asm volatile("class.s %0, %1" : "=f"(c) : "f"(x));
> +  asm volatile("mfc1 %0, %1" : "=r"(ret) : "f"(c));
> +  return ret & _FCLASS_SNAN;
> +#else
> +  uint32_t xi;
> +  GET_FLOAT_WORD (xi, x);
> +#  if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
> +  /* We only have to care about the high-order bit of x's significand, because
> +     having it set (sNaN) already makes the significand different from that
> +     used to designate infinity.  */
> +  return (xi & 0x7fc00000) == 0x7fc00000;
> +#  else
> +  /* To keep the following comparison simple, toggle the quiet/signaling bit,
> +     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
> +     common practice for IEEE 754-1985).  */
> +  xi ^= 0x00400000;
> +  /* We have to compare for greater (instead of greater or equal), because x's
> +     significand being all-zero designates infinity not NaN.  */
> +  return (xi & 0x7fffffff) > 0x7fc00000;
> +#  endif
> +#endif
> +}
> +
> +/* Copy from sysdeps/ieee754/dbl-64/s_issignaling.c.
> +   Function call can introduce lots for stack operations.  Inline can even
> +   reduce codesize.  */
> +static __always_inline int
> +__mips_issignaling (double x)
> +{
> +#if __mips_isa_rev >= 6 && defined(__mips_hard_float)                         \
> +    && !defined(__mips_single_float)
> +  double c;
> +  int ret;
> +  asm volatile("class.d %0, %1" : "=f"(c) : "f"(x));
> +  asm volatile("mfc1 %0, %1" : "=r"(ret) : "f"(c));
> +  return ret & _FCLASS_SNAN;
> +#else
> +  uint32_t xi;
> +  GET_HIGH_WORD (xi, x);
> +#  if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
> +  /* We only have to care about the high-order bit of x's significand, because
> +     having it set (sNaN) already makes the significand different from that
> +     used to designate infinity.  */
> +  return (xi & UINT32_C (0x7ff80000)) == UINT32_C (0x7ff80000);
> +#  else
> +  /* To keep the following comparison simple, toggle the quiet/signaling bit,
> +     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
> +     common practice for IEEE 754-1985).  */
> +  xi ^= UINT32_C (0x00080000);
> +  /* We have to compare for greater (instead of greater or equal), because x's
> +     significand being all-zero designates infinity not NaN.  */
> +  return (xi & UINT32_C (0x7fffffff)) > UINT32_C (0x7ff80000);
> +#  endif
> +#endif
> +}
> +
>  #endif /* MIPS_MATH_PRIVATE_H */

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf
  2024-05-22 13:42   ` Adhemerval Zanella Netto
@ 2024-05-25 11:55     ` YunQiang Su
  2024-05-31 15:53       ` YunQiang Su
  0 siblings, 1 reply; 13+ messages in thread
From: YunQiang Su @ 2024-05-25 11:55 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha

Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> 于2024年5月22日周三 21:42写道:
>
>
>
> On 13/05/24 05:14, YunQiang Su wrote:
> > MIPSr6 has MADDF.s/MADDF.d instructions, which are fused.
> >
> > In MIPS ISA, double support can be subsetted.  Only FMAF is enabled
> > for this case.
> >
> >       * sysdeps/mips/fpu/math-use-builtins-fma.h
> >
> > Signed-off-by: YunQiang Su <syq@gcc.gnu.org>
> > ---
> >  sysdeps/mips/fpu/math-use-builtins-fma.h | 13 +++++++++++++
> >  1 file changed, 13 insertions(+)
> >  create mode 100644 sysdeps/mips/fpu/math-use-builtins-fma.h
> >
> > diff --git a/sysdeps/mips/fpu/math-use-builtins-fma.h b/sysdeps/mips/fpu/math-use-builtins-fma.h
> > new file mode 100644
> > index 0000000000..6e296fd4c0
> > --- /dev/null
> > +++ b/sysdeps/mips/fpu/math-use-builtins-fma.h
> > @@ -0,0 +1,13 @@
> > +#if __mips_isa_rev >= 6
> > +#  if defined(__mips_single_float)
>
> Usually for a single case we write as '#ifdef __mips_single_float,
> also the identation is a single space.
>

In fact I sent V2, can you have a look at it?
https://sourceware.org/pipermail/libc-alpha/2024-May/156668.html

> The rest look ok, gcc seems to emit the the MADDF.X even with
> pretty old versions (gcc 5.5.0).
>
> > +#    define USE_FMA_BUILTIN 0
> > +#  else
> > +#    define USE_FMA_BUILTIN 1
> > +#  endif
> > +#  define USE_FMAF_BUILTIN 1
> > +#else
> > +#  define USE_FMA_BUILTIN 0
> > +#  define USE_FMAF_BUILTIN 0
> > +#endif
> > +#define USE_FMAL_BUILTIN 0
> > +#define USE_FMAF128_BUILTIN 0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf
  2024-05-25 11:55     ` YunQiang Su
@ 2024-05-31 15:53       ` YunQiang Su
  0 siblings, 0 replies; 13+ messages in thread
From: YunQiang Su @ 2024-05-31 15:53 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha

@Adhemerval Zanella can you help to merge it if the V2 is OK?

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-05-31 15:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-13  8:14 [PATCH 0/6] MIPS: Improve math YunQiang Su
2024-05-13  8:14 ` [PATCH 1/6] MIPSr6/math: Use builtin fma and fmaf YunQiang Su
2024-05-22 13:42   ` Adhemerval Zanella Netto
2024-05-25 11:55     ` YunQiang Su
2024-05-31 15:53       ` YunQiang Su
2024-05-13  8:14 ` [PATCH 2/6] MIPS/math: Define port-specific GET_HIGH_WORD YunQiang Su
2024-05-22 18:36   ` Adhemerval Zanella Netto
2024-05-13  8:14 ` [PATCH 3/6] MIPS/math: Implement optimized issignaling(f) YunQiang Su
2024-05-23 14:37   ` Adhemerval Zanella Netto
2024-05-13  8:14 ` [PATCH 4/6] MIPS/math: Implement optimized fmaximum/fminmum(,_mag)(,f) YunQiang Su
2024-05-13  8:14 ` [PATCH 5/6] MIPS/math: Implement optimized fmax(mag)(f)/fmin(mag)(f) YunQiang Su
2024-05-13  8:14 ` [PATCH 6/6] MIPS/math: Implement optimized f(max,min)imum(_mag)_num(f) YunQiang Su
2024-05-22 13:21 ` [PATCH 0/6] MIPS: Improve math YunQiang Su

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).