Re: [PATCH 1/5] riscv: Optimize fmaximum_num and fminimum_num
Adhemerval Zanella Netto <[email protected]> Thu, 6 Aug 2026 15:34:57 -0300
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Linaro |
| Message-ID | <[email protected]> |
On 06/08/26 07:25, Julian Zhu wrote: > Implement the C23 maximumNumber and minimumNumber operations with the RISC-V fmax and fmin instructions for float and double. These instructions provide the required NaN and signed-zero semantics using the base F and D extensions. > > Signed-off-by: Julian Zhu <[email protected]> The version 2.2 of the F extension requirement really makes this messy to keep deployment generic. Ideally it would be better to implement it with builtin and let compiler handle it, and then we gate it through USE_*_BUILTIN. If deployers want to support pre 2.1 hardware, using the generic implementation is the price to pay. Another possibility is to: #if defined(__riscv_f) && __riscv_f >= 2002000 double __fmaximum_num (double x, double y) { double res; asm ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); return res; } libm_alias_double (__fmaximum_num, fmaximum_num) #else /* Use the generic implementation. */ #endif But this is keeps moving RISC-V glibc support the old style of having exponential build permutation which increase the cost of testing and maintaining. Another possibility is to move this as ifunc implementation and gate it the selection with RISCV_HWPROBE_IMA_FD: Documentation/arch/riscv/hwprobe.rst 74 * :c:macro:`RISCV_HWPROBE_IMA_FD`: The F and D extensions are supported, as 75 defined by commit cd20cee ("FMIN/FMAX now implement 76 minimumNumber/maximumNumber, not minNum/maxNum") of the RISC-V ISA manual. However the kernel code for the selection seems limited: arch/riscv/kernel/sys_hwprobe.c 87 pair->value = 0; 88 if (has_fpu()) 89 pair->value |= RISCV_HWPROBE_IMA_FD; arch/riscv/include/asm/switch_to.h 61 static __always_inline bool has_fpu(void) 62 { 63 return riscv_has_extension_likely(RISCV_ISA_EXT_f) || 64 riscv_has_extension_likely(RISCV_ISA_EXT_d); 65 } There is no distinction which version is this f/d extension, so I am not sure if kernel is doing the expected thing here. My suggestion is to follow the first suggestion: track this on compiler and use the builtin on glibc. > --- > sysdeps/riscv/rvd/s_fmaximum_num.c | 37 +++++++++++++++++++++++++++++ > sysdeps/riscv/rvd/s_fminimum_num.c | 37 +++++++++++++++++++++++++++++ > sysdeps/riscv/rvf/s_fmaximum_numf.c | 32 +++++++++++++++++++++++++ > sysdeps/riscv/rvf/s_fminimum_numf.c | 32 +++++++++++++++++++++++++ > 4 files changed, 138 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 > > diff --git a/sysdeps/riscv/rvd/s_fmaximum_num.c b/sysdeps/riscv/rvd/s_fmaximum_num.c > new file mode 100644 > index 0000000000..0203329935 > --- /dev/null > +++ b/sysdeps/riscv/rvd/s_fmaximum_num.c > @@ -0,0 +1,37 @@ > +/* fmaximum_num(). RISC-V version. > + Copyright (C) 2026 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> > + > +/* fmaximum_num is the IEEE 754-2019 maximumNumber operation: it returns > + the larger operand, treats a NaN operand as if it were absent (so a > + NaN and a number yield the number), returns a quiet NaN only when both > + operands are NaN, and orders +0 above -0. The RISC-V fmax.d > + instruction implements exactly these semantics and raises the invalid > + exception for a signaling NaN input, so unlike fmax it needs no NaN > + pre-check. */ > + > +double > +__fmaximum_num (double x, double y) > +{ > + double res; > + asm ("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..7875f3cb8e > --- /dev/null > +++ b/sysdeps/riscv/rvd/s_fminimum_num.c > @@ -0,0 +1,37 @@ > +/* fminimum_num(). RISC-V version. > + Copyright (C) 2026 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> > + > +/* fminimum_num is the IEEE 754-2019 minimumNumber operation: it returns > + the smaller operand, treats a NaN operand as if it were absent (so a > + NaN and a number yield the number), returns a quiet NaN only when both > + operands are NaN, and orders -0 below +0. The RISC-V fmin.d > + instruction implements exactly these semantics and raises the invalid > + exception for a signaling NaN input, so unlike fmin it needs no NaN > + pre-check. */ > + > +double > +__fminimum_num (double x, double y) > +{ > + double res; > + asm ("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..334a177f63 > --- /dev/null > +++ b/sysdeps/riscv/rvf/s_fmaximum_numf.c > @@ -0,0 +1,32 @@ > +/* fmaximum_numf(). RISC-V version. > + Copyright (C) 2026 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> > + > +/* See s_fmaximum_num.c for a description of the semantics; the RISC-V > + fmax.s instruction implements maximumNumber for single precision. */ > + > +float > +__fmaximum_numf (float x, float y) > +{ > + float res; > + asm ("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..71d2683a97 > --- /dev/null > +++ b/sysdeps/riscv/rvf/s_fminimum_numf.c > @@ -0,0 +1,32 @@ > +/* fminimum_numf(). RISC-V version. > + Copyright (C) 2026 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> > + > +/* See s_fminimum_num.c for a description of the semantics; the RISC-V > + fmin.s instruction implements minimumNumber for single precision. */ > + > +float > +__fminimum_numf (float x, float y) > +{ > + float res; > + asm ("fmin.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > + return res; > +} > +libm_alias_float (__fminimum_num, fminimum_num)