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)