[2/2] RISC-V: Add implementation for fmaximum_num and fminimum_num

Message ID 20240911141952.37217-2-jz531210@gmail.com
State Changes Requested
Headers
Series [1/2] RISC-V: Add implementation for fmaximum and fminimum |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Julian Zhu Sept. 11, 2024, 2:19 p.m. UTC
  Implemented `fmaximum_num{f}` and `fminimum_num{f}` using hard-float `fclass.fmt` and `f{max,min}.fmt` instructions to generate more simplified code.

Signed-off-by: Julian Zhu <jz531210@gmail.com>
---
 sysdeps/riscv/rvd/s_fmaximum_num.c  | 44 +++++++++++++++++++++++++++++
 sysdeps/riscv/rvd/s_fminimum_num.c  | 44 +++++++++++++++++++++++++++++
 sysdeps/riscv/rvf/s_fmaximum_numf.c | 44 +++++++++++++++++++++++++++++
 sysdeps/riscv/rvf/s_fminimum_numf.c | 44 +++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+)
 create mode 100644 sysdeps/riscv/rvd/s_fmaximum_num.c
 create mode 100644 sysdeps/riscv/rvd/s_fminimum_num.c
 create mode 100644 sysdeps/riscv/rvf/s_fmaximum_numf.c
 create mode 100644 sysdeps/riscv/rvf/s_fminimum_numf.c
  

Comments

Joseph Myers Sept. 11, 2024, 4:52 p.m. UTC | #1
On Wed, 11 Sep 2024, Julian Zhu wrote:

> +  if (__glibc_unlikely((_FCLASS (x) & _FCLASS_NAN) && !(_FCLASS (y) & _FCLASS_NAN)))
> +    {
> +      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
> +      return res;
> +    }
> +  else if (__glibc_unlikely(!(_FCLASS (x) & _FCLASS_NAN) && (_FCLASS (y) & _FCLASS_NAN)))
> +    {
> +      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
> +      return res;
> +    }
> +  else
> +    {
> +      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
> +      return res;

I don't follow the logic here, which seems to do the same thing under each 
of three different runtime conditions.

If the processor implements version 2.2 of the F and D extensions, the 
fmax and fmin instructions implement IEEE 754-2019 maximumNumber / 
minimumNumber, which is appropriate for fmaximum_num / fminimum_num 
(without special runtime conditions about NaNs being needed).

If the processor implements an older version of the F and D extensions, 
the fmax and fmin instructions implement IEEE 754-2008 maxNum / minNum, 
which is appropriate for fmax / fmin.

If you don't know what version the processor implements, maybe you can do 
something with runtime conditions for NaNs, but I don't think they'd look 
like the above conditions, because checking runtime conditions is useless 
when you end up executing the same asm under all conditions.
  

Patch

diff --git a/sysdeps/riscv/rvd/s_fmaximum_num.c b/sysdeps/riscv/rvd/s_fmaximum_num.c
new file mode 100644
index 0000000000..da644b58f9
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fmaximum_num.c
@@ -0,0 +1,44 @@ 
+/* Return maximum number of X and Y. RISC-V 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 <libm-alias-double.h>
+
+double
+__fmaximum_num (double x, double y)
+{
+  double res;
+
+  if (__glibc_unlikely((_FCLASS (x) & _FCLASS_NAN) && !(_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else if (__glibc_unlikely(!(_FCLASS (x) & _FCLASS_NAN) && (_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else
+    {
+      asm volatile ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+}
+libm_alias_double (__fmaximum_num, fmaximum_num)
diff --git a/sysdeps/riscv/rvd/s_fminimum_num.c b/sysdeps/riscv/rvd/s_fminimum_num.c
new file mode 100644
index 0000000000..debeb90550
--- /dev/null
+++ b/sysdeps/riscv/rvd/s_fminimum_num.c
@@ -0,0 +1,44 @@ 
+/* Return minimum number of X and Y. RISC-V 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 <libm-alias-double.h>
+
+double
+__fminimum_num (double x, double y)
+{
+  double res;
+
+  if (__glibc_unlikely((_FCLASS (x) & _FCLASS_NAN) && !(_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmin.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else if (__glibc_unlikely(!(_FCLASS (x) & _FCLASS_NAN) && (_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmin.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else
+    {
+      asm volatile ("fmin.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+}
+libm_alias_double (__fminimum_num, fminimum_num)
diff --git a/sysdeps/riscv/rvf/s_fmaximum_numf.c b/sysdeps/riscv/rvf/s_fmaximum_numf.c
new file mode 100644
index 0000000000..34fecef968
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fmaximum_numf.c
@@ -0,0 +1,44 @@ 
+/* Return maximum number of X and Y. RISC-V 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 <libm-alias-float.h>
+
+float
+__fmaximum_numf (float x, float y)
+{
+  float res;
+
+  if (__glibc_unlikely((_FCLASS (x) & _FCLASS_NAN) && !(_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmax.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else if (__glibc_unlikely(!(_FCLASS (x) & _FCLASS_NAN) && (_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmax.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else
+    {
+      asm volatile ("fmax.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+}
+libm_alias_float (__fmaximum_num, fmaximum_num)
diff --git a/sysdeps/riscv/rvf/s_fminimum_numf.c b/sysdeps/riscv/rvf/s_fminimum_numf.c
new file mode 100644
index 0000000000..ef2699f3b6
--- /dev/null
+++ b/sysdeps/riscv/rvf/s_fminimum_numf.c
@@ -0,0 +1,44 @@ 
+/* Return minimum number of X and Y. RISC-V 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 <libm-alias-float.h>
+
+float
+__fminimum_numf (float x, float y)
+{
+  float res;
+
+  if (__glibc_unlikely((_FCLASS (x) & _FCLASS_NAN) && !(_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmin.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else if (__glibc_unlikely(!(_FCLASS (x) & _FCLASS_NAN) && (_FCLASS (y) & _FCLASS_NAN)))
+    {
+      asm volatile ("fmin.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+  else
+    {
+      asm volatile ("fmin.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y));
+      return res;
+    }
+}
+libm_alias_float (__fminimum_num, fminimum_num)