Re: [PATCH 3/5] riscv: Use Zfa for fmaximum and fminimum
Adhemerval Zanella Netto <[email protected]> Thu, 6 Aug 2026 15:59:32 -0300
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Linaro |
| Message-ID | <[email protected]> |
On 06/08/26 07:25, Julian Zhu wrote: > Use the Zfa fmaxm and fminm instructions for the NaN-propagating C23 maximum and minimum operations in float and double precision. Keep the F/D implementation as the fallback when Zfa is unavailable. > > Signed-off-by: Julian Zhu <[email protected]> As for the f{max,min}imum_num, I think it would be implemented through compiler builtins. > --- > sysdeps/riscv/rvd/s_fmaximum.c | 9 +++++++-- > sysdeps/riscv/rvd/s_fminimum.c | 9 +++++++-- > sysdeps/riscv/rvf/s_fmaximumf.c | 9 +++++++-- > sysdeps/riscv/rvf/s_fminimumf.c | 9 +++++++-- > 4 files changed, 28 insertions(+), 8 deletions(-) > > diff --git a/sysdeps/riscv/rvd/s_fmaximum.c b/sysdeps/riscv/rvd/s_fmaximum.c > index d514fb17a6..a9b99a0fd5 100644 > --- a/sysdeps/riscv/rvd/s_fmaximum.c > +++ b/sysdeps/riscv/rvd/s_fmaximum.c > @@ -21,17 +21,22 @@ > > /* fmaximum is the IEEE 754-2019 maximum operation: like fmaximum_num but > NaN-propagating, so a NaN operand yields a quiet NaN result (and a > - signaling NaN also raises the invalid exception). RISC-V's fmax.d gives > - the correct result whenever neither operand is NaN, so only the NaN case > + signaling NaN also raises the invalid exception). Zfa's fmaxm.d > + implements it in a single instruction. Without Zfa, fmax.d gives the > + correct result whenever neither operand is NaN, so only the NaN case > needs to be handled explicitly. */ > > double > __fmaximum (double x, double y) > { > double res; > +#ifdef __riscv_zfa > + asm ("fmaxm.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#else > if (__glibc_unlikely (isunordered (x, y))) > return x + y; > asm ("fmax.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#endif > return res; > } > libm_alias_double (__fmaximum, fmaximum) > diff --git a/sysdeps/riscv/rvd/s_fminimum.c b/sysdeps/riscv/rvd/s_fminimum.c > index 608b37bed5..7b37d953fe 100644 > --- a/sysdeps/riscv/rvd/s_fminimum.c > +++ b/sysdeps/riscv/rvd/s_fminimum.c > @@ -21,17 +21,22 @@ > > /* fminimum is the IEEE 754-2019 minimum operation: like fminimum_num but > NaN-propagating, so a NaN operand yields a quiet NaN result (and a > - signaling NaN also raises the invalid exception). RISC-V's fmin.d gives > - the correct result whenever neither operand is NaN, so only the NaN case > + signaling NaN also raises the invalid exception). Zfa's fminm.d > + implements it in a single instruction. Without Zfa, fmin.d gives the > + correct result whenever neither operand is NaN, so only the NaN case > needs to be handled explicitly. */ > > double > __fminimum (double x, double y) > { > double res; > +#ifdef __riscv_zfa > + asm ("fminm.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#else > if (__glibc_unlikely (isunordered (x, y))) > return x + y; > asm ("fmin.d %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#endif > return res; > } > libm_alias_double (__fminimum, fminimum) > diff --git a/sysdeps/riscv/rvf/s_fmaximumf.c b/sysdeps/riscv/rvf/s_fmaximumf.c > index daa71f0f34..6aad94d149 100644 > --- a/sysdeps/riscv/rvf/s_fmaximumf.c > +++ b/sysdeps/riscv/rvf/s_fmaximumf.c > @@ -19,16 +19,21 @@ > #include <math.h> > #include <libm-alias-float.h> > > -/* See s_fmaximum.c for a description of the semantics. RISC-V's fmax.s > - handles the ordered case, so only NaNs need explicit handling. */ > +/* See s_fmaximum.c for a description of the semantics. Zfa's fmaxm.s > + implements maximum for single precision; otherwise fmax.s handles the > + non-NaN case. */ > > float > __fmaximumf (float x, float y) > { > float res; > +#ifdef __riscv_zfa > + asm ("fmaxm.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#else > if (__glibc_unlikely (isunordered (x, y))) > return x + y; > asm ("fmax.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#endif > return res; > } > libm_alias_float (__fmaximum, fmaximum) > diff --git a/sysdeps/riscv/rvf/s_fminimumf.c b/sysdeps/riscv/rvf/s_fminimumf.c > index 2dba5412f8..6be5cb81d0 100644 > --- a/sysdeps/riscv/rvf/s_fminimumf.c > +++ b/sysdeps/riscv/rvf/s_fminimumf.c > @@ -19,16 +19,21 @@ > #include <math.h> > #include <libm-alias-float.h> > > -/* See s_fminimum.c for a description of the semantics. RISC-V's fmin.s > - handles the ordered case, so only NaNs need explicit handling. */ > +/* See s_fminimum.c for a description of the semantics. Zfa's fminm.s > + implements minimum for single precision; otherwise fmin.s handles the > + non-NaN case. */ > > float > __fminimumf (float x, float y) > { > float res; > +#ifdef __riscv_zfa > + asm ("fminm.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#else > if (__glibc_unlikely (isunordered (x, y))) > return x + y; > asm ("fmin.s %0, %1, %2" : "=f" (res) : "f" (x), "f" (y)); > +#endif > return res; > } > libm_alias_float (__fminimum, fminimum)