[PATCH 3/5] riscv: Use Zfa for fmaximum and fminimum
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu Aug 6 18:59:32 GMT 2026
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 <jz531210@gmail.com>
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)
More information about the Libc-alpha
mailing list