> On 13 Nov 2026, at 15:50, Karl Meakin <[email protected]> wrote:
> 
> The floating point variants of `vmin` and `vmax` were not ported to the
> pragma-based framework when the integer variants were, because the
> semantics AArch64's `fmin`/`fmax` instructions don't match the semantics
> of GCC's `MIN_EXPR`/`MAX_EXPR`. This commit ports them to the pragma
> framework, by expanding them to `UNSPEC_FMIN` and `UNSPEC_FMAX`.
> 
> There are no test changes, as tests for FP variants of vmin/vmax were
> already included in vmin.c and vmax.c. The absence of any changes to the
> tests does show that there were no changes in codegen (ie no
> regressions).
> 
> Also delete the `__builtin_aarch64_{u,s}{min,max}` functions which were
> mistakenly left behind when the integer min/max intrinsics were ported.
> 

Ok.
Thanks,
Kyrill

> gcc/ChangeLog:
> 
> * config/aarch64/aarch64-neon-builtins-base.cc (struct
> gimple_minmax): New struct.
> * config/aarch64/aarch64-neon-builtins-base.def (vmax, vmaxq,
> vmin, vminq): New intrinsic function definitions.
> * config/aarch64/aarch64-simd-builtins.def (smax, smin, umax,
> umin, fmax, fmin): Delete now-unused builtin function declarations.
> (fmax_nan, fmin_nan): Only define for float16_t, as they are
> only now called from `arm_fp16.h`.
> * config/aarch64/arm_fp16.h (vmaxh_f16, vminh_f16): Call the
> correct `_nan` variant of the `__aarch64_builtin` functions.
> (vmaxnmh_f16, vminnmh_f16): Use the platform-agnostic
> `__builtin_f{min,max}f16` functions rather than the now-deleted
> aarch64-specific builtins.
> * config/aarch64/arm_neon.h (vmax_f32, vmax_f64, vmaxq_f32,
> vmaxq_f64, vmin_f32, vmin_f64, vminq_f32, vminq_f64, vmax_f16,
> vmaxq_f16, vmin_f16, vminq_f16): Delete intrinsic function
> definitions.
> ---
> .../aarch64/aarch64-neon-builtins-base.cc     | 40 +++++++-
> .../aarch64/aarch64-neon-builtins-base.def    |  8 ++
> gcc/config/aarch64/aarch64-simd-builtins.def  | 14 +--
> gcc/config/aarch64/arm_fp16.h                 |  4 +-
> gcc/config/aarch64/arm_neon.h                 | 92 -------------------
> 5 files changed, 52 insertions(+), 106 deletions(-)
> 
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc 
> b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> index 4b66a93d0f0..8c3bcc6eb74 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
> @@ -1140,6 +1140,42 @@ public:
>   }
> };
> 
> +template <bool min_p>
> +struct gimple_minmax : public gimple_function_base
> +{
> +  rtx expand (function_expander &e) const override
> +  {
> +    auto ret_mode = e.result_mode ();
> +    auto singleton_p = (ret_mode == V1DFmode);
> +    auto unspec = min_p ? UNSPEC_FMIN : UNSPEC_FMAX;
> +
> +    if (singleton_p)
> +      {
> + for (int i = 0; i < 2; i++)
> +  e.args[i] = simplify_gen_subreg (DFmode, e.args[i], V1DFmode, 0);
> + ret_mode = DFmode;
> +      }
> +
> +    auto ret = gen_reg_rtx (ret_mode);
> +    auto args = gen_rtvec_v (e.args.length (), e.args.address ());
> +    emit_insn (gen_rtx_SET (ret, gen_rtx_UNSPEC (ret_mode, args, unspec)));
> +
> +    if (singleton_p)
> +      ret = simplify_gen_subreg (V1DFmode, ret, DFmode, 0);
> +
> +    return ret;
> +  }
> +
> +  gimple *fold (gimple_folder &f) const override {
> +    auto lhs = gimple_call_arg (f.call, 0);
> +    auto rhs = gimple_call_arg (f.call, 1);
> +    auto ret_type = TREE_TYPE (f.lhs);
> +    if (FLOAT_TYPE_P (ret_type))
> +      return nullptr;
> +    return gimple_build_assign (f.lhs, min_p ? MIN_EXPR : MAX_EXPR, lhs, 
> rhs);
> +  }
> +};
> +
> // Reinterpret
> NEON_FUNCTION (vreinterpret, vreinterpretq, gimple_reinterpret,)
> 
> @@ -1175,8 +1211,8 @@ NEON_FUNCTION (vqaddb, vqaddh, vqadds, vqaddd, vqadd, 
> vqaddq, gimple_ifn, (IFN_S
> NEON_FUNCTION (vqsubb, vqsubh, vqsubs, vqsubd, vqsub, vqsubq, gimple_ifn, 
> (IFN_SAT_SUB))
> 
> // Max/min
> -NEON_FUNCTION (vmax,   vmaxq,   gimple_expr, (MAX_EXPR))
> -NEON_FUNCTION (vmin,   vminq,   gimple_expr, (MIN_EXPR))
> +NEON_FUNCTION (vmax,   vmaxq,   gimple_minmax<false>,)
> +NEON_FUNCTION (vmin,   vminq,   gimple_minmax<true>,)
> NEON_FUNCTION (vmaxnm, vmaxnmq, gimple_ifn,  (IFN_FMAX))
> NEON_FUNCTION (vminnm, vminnmq, gimple_ifn,  (IFN_FMIN))
> 
> diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def 
> b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> index db9defc454c..e8edb2679b9 100644
> --- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
> +++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
> @@ -180,9 +180,13 @@ DEF_NEON_FUNCTION (vqsubq, all_integer, ("Q0,Q0,Q0"))
> // Max/min
> #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
> DEF_NEON_FUNCTION (vmax,    bhs_integer, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vmax,    sd_float,    ("D0,D0,D0"))
> DEF_NEON_FUNCTION (vmaxq,   bhs_integer, ("Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vmaxq,   sd_float,    ("Q0,Q0,Q0"))
> DEF_NEON_FUNCTION (vmin,    bhs_integer, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vmin,    sd_float,    ("D0,D0,D0"))
> DEF_NEON_FUNCTION (vminq,   bhs_integer, ("Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vminq,   sd_float,    ("Q0,Q0,Q0"))
> DEF_NEON_FUNCTION (vmaxnm,  sd_float,    ("D0,D0,D0"))
> DEF_NEON_FUNCTION (vmaxnmq, sd_float,    ("Q0,Q0,Q0"))
> DEF_NEON_FUNCTION (vminnm,  sd_float,    ("D0,D0,D0"))
> @@ -191,6 +195,10 @@ DEF_NEON_FUNCTION (vminnmq, sd_float,    ("Q0,Q0,Q0"))
> 
> // Max/min (FP16)
> #define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD | 
> AARCH64_FL_F16)
> +DEF_NEON_FUNCTION (vmax,    h_float, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vmaxq,   h_float, ("Q0,Q0,Q0"))
> +DEF_NEON_FUNCTION (vmin,    h_float, ("D0,D0,D0"))
> +DEF_NEON_FUNCTION (vminq,   h_float, ("Q0,Q0,Q0"))
> DEF_NEON_FUNCTION (vmaxnm,  h_float, ("D0,D0,D0"))
> DEF_NEON_FUNCTION (vmaxnmq, h_float, ("Q0,Q0,Q0"))
> DEF_NEON_FUNCTION (vminnm,  h_float, ("D0,D0,D0"))
> diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def 
> b/gcc/config/aarch64/aarch64-simd-builtins.def
> index 0a84dfd459d..d1a19cebe97 100644
> --- a/gcc/config/aarch64/aarch64-simd-builtins.def
> +++ b/gcc/config/aarch64/aarch64-simd-builtins.def
> @@ -503,17 +503,11 @@
>   BUILTIN_VHSDF (UNOP, reduc_smax_nan_scal_, 10, DEFAULT)
>   BUILTIN_VHSDF (UNOP, reduc_smin_nan_scal_, 10, DEFAULT)
> 
> -  /* Implemented by <optab><mode>3.  */
> -  BUILTIN_VDQ_BHSI (BINOP, smax, 3, DEFAULT)
> -  BUILTIN_VDQ_BHSI (BINOP, smin, 3, DEFAULT)
> -  BUILTIN_VDQ_BHSI (BINOP, umax, 3, DEFAULT)
> -  BUILTIN_VDQ_BHSI (BINOP, umin, 3, DEFAULT)
> -
>   /* Implemented by <fmaxmin><mode>3.  */
> -  BUILTIN_VHSDF_HSDF (BINOP, fmax, 3, FP)
> -  BUILTIN_VHSDF_HSDF (BINOP, fmin, 3, FP)
> -  BUILTIN_VHSDF_DF (BINOP, fmax_nan, 3, FP)
> -  BUILTIN_VHSDF_DF (BINOP, fmin_nan, 3, FP)
> +  VAR1 (BINOP, fmax, 3, FP, hf)
> +  VAR1 (BINOP, fmin, 3, FP, hf)
> +  VAR1 (BINOP, fmax_nan, 3, FP, hf)
> +  VAR1 (BINOP, fmin_nan, 3, FP, hf)
> 
>   /* Implemented by aarch64_<optab>p<mode>.  */
>   BUILTIN_VDQ_BHSI (BINOP, smaxp, 0, DEFAULT)
> diff --git a/gcc/config/aarch64/arm_fp16.h b/gcc/config/aarch64/arm_fp16.h
> index d932d8ab1c9..d353eea65ab 100644
> --- a/gcc/config/aarch64/arm_fp16.h
> +++ b/gcc/config/aarch64/arm_fp16.h
> @@ -588,7 +588,7 @@ __extension__ extern __inline float16_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vmaxh_f16 (float16_t __a, float16_t __b)
> {
> -  return __builtin_aarch64_fmaxhf (__a, __b);
> +  return __builtin_aarch64_fmax_nanhf (__a, __b);
> }
> 
> __extension__ extern __inline float16_t
> @@ -602,7 +602,7 @@ __extension__ extern __inline float16_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vminh_f16 (float16_t __a, float16_t __b)
> {
> -  return __builtin_aarch64_fminhf (__a, __b);
> +  return __builtin_aarch64_fmin_nanhf (__a, __b);
> }
> 
> __extension__ extern __inline float16_t
> diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
> index a0dca5e8da9..a8d1c4f61da 100644
> --- a/gcc/config/aarch64/arm_neon.h
> +++ b/gcc/config/aarch64/arm_neon.h
> @@ -10613,38 +10613,6 @@ vld4q_lane_p64 (const poly64_t * __ptr, poly64x2x4_t 
> __b, const int __c)
> (__builtin_aarch64_simd_di *) __ptr, __b, __c);
> }
> 
> -/* vmax */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmax_f32 (float32x2_t __a, float32x2_t __b)
> -{
> -  return __builtin_aarch64_fmax_nanv2sf (__a, __b);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmax_f64 (float64x1_t __a, float64x1_t __b)
> -{
> -    return (float64x1_t)
> -      { __builtin_aarch64_fmax_nandf (vget_lane_f64 (__a, 0),
> -      vget_lane_f64 (__b, 0)) };
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmaxq_f32 (float32x4_t __a, float32x4_t __b)
> -{
> -  return __builtin_aarch64_fmax_nanv4sf (__a, __b);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmaxq_f64 (float64x2_t __a, float64x2_t __b)
> -{
> -  return __builtin_aarch64_fmax_nanv2df (__a, __b);
> -}
> -
> /* vmulx */
> 
> __extension__ extern __inline float32x2_t
> @@ -11124,38 +11092,6 @@ vmaxvq_f64 (float64x2_t __a)
>   return __builtin_aarch64_reduc_smax_nan_scal_v2df (__a);
> }
> 
> -/* vmin  */
> -
> -__extension__ extern __inline float32x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmin_f32 (float32x2_t __a, float32x2_t __b)
> -{
> -  return __builtin_aarch64_fmin_nanv2sf (__a, __b);
> -}
> -
> -__extension__ extern __inline float64x1_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmin_f64 (float64x1_t __a, float64x1_t __b)
> -{
> -    return (float64x1_t)
> -  { __builtin_aarch64_fmin_nandf (vget_lane_f64 (__a, 0),
> -  vget_lane_f64 (__b, 0)) };
> -}
> -
> -__extension__ extern __inline float32x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vminq_f32 (float32x4_t __a, float32x4_t __b)
> -{
> -  return __builtin_aarch64_fmin_nanv4sf (__a, __b);
> -}
> -
> -__extension__ extern __inline float64x2_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vminq_f64 (float64x2_t __a, float64x2_t __b)
> -{
> -  return __builtin_aarch64_fmin_nanv2df (__a, __b);
> -}
> -
> /* vminv  */
> 
> __extension__ extern __inline float32_t
> @@ -17170,34 +17106,6 @@ vcvtq_n_u16_f16 (float16x8_t __a, const int __b)
>   return __builtin_aarch64_fcvtzuv8hf_uss (__a, __b);
> }
> 
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmax_f16 (float16x4_t __a, float16x4_t __b)
> -{
> -  return __builtin_aarch64_fmax_nanv4hf (__a, __b);
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmaxq_f16 (float16x8_t __a, float16x8_t __b)
> -{
> -  return __builtin_aarch64_fmax_nanv8hf (__a, __b);
> -}
> -
> -__extension__ extern __inline float16x4_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vmin_f16 (float16x4_t __a, float16x4_t __b)
> -{
> -  return __builtin_aarch64_fmin_nanv4hf (__a, __b);
> -}
> -
> -__extension__ extern __inline float16x8_t
> -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> -vminq_f16 (float16x8_t __a, float16x8_t __b)
> -{
> -  return __builtin_aarch64_fmin_nanv8hf (__a, __b);
> -}
> -
> __extension__ extern __inline float16x4_t
> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> vmulx_f16 (float16x4_t __a, float16x4_t __b)
> -- 
> 2.56.0
> 

Reply via email to