On Mon, Jun 23, 2025 at 09:51:13AM +0200, Juergen Christ wrote:
> On VXE targets, we can directly use the fp min/max instruction instead of
> calling into libm for fmin/fmax etc.
> 
> Provide fmin/fmax versions also for vectors even though it cannot be
> called directly.  This will be exploited with a follow-up patch when
> reductions are introduced.

This looks very similar to vfmin<mode> / vfmax<mode>.  Couldn't we merge
those by using appropriate mode iterators?  The expander for fmin<mode>
/ fmax<mode> could set the mask operand.

> 
> Bootstrapped and regtested on s390.
> 
> gcc/ChangeLog:
> 
>       * config/s390/s390.md (VFT_BFP): New iterator.
>       * config/s390/vector.md (fmax<mode>3): Implement.
>       (fmin<mode>3): Ditto.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/s390/fminmax-1.c: New test.
>       * gcc.target/s390/fminmax-2.c: New test.
> 
> Signed-off-by: Juergen Christ <jchr...@linux.ibm.com>
> ---
>  gcc/config/s390/s390.md                   |  3 +
>  gcc/config/s390/vector.md                 | 24 +++++++
>  gcc/testsuite/gcc.target/s390/fminmax-1.c | 77 +++++++++++++++++++++++
>  gcc/testsuite/gcc.target/s390/fminmax-2.c | 29 +++++++++
>  4 files changed, 133 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/s390/fminmax-1.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/fminmax-2.c
> 
> diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
> index 97a4bdf96b2d..c4e836dd4af4 100644
> --- a/gcc/config/s390/s390.md
> +++ b/gcc/config/s390/s390.md
> @@ -256,6 +256,9 @@
>  
>     UNSPEC_NNPA_VCFN_V8HI
>     UNSPEC_NNPA_VCNF_V8HI
> +
> +   UNSPEC_FMAX
> +   UNSPEC_FMIN

See above UNSPEC_VEC_VFMIN / UNSPEC_VEC_VFMAX.

>  ])
>  
>  ;;
> diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
> index 6f4e1929eb80..668e7475ef21 100644
> --- a/gcc/config/s390/vector.md
> +++ b/gcc/config/s390/vector.md
> @@ -3576,3 +3576,27 @@
>  ; vec_unpacks_float_lo
>  ; vec_unpacku_float_hi
>  ; vec_unpacku_float_lo
> +(define_mode_iterator VFT_BFP [SF DF
> +               (V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
> +                        V1DF V2DF
> +                        (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
> +

Whitespace.

> +; fmax
> +(define_insn "fmax<mode>3"
> +  [(set (match_operand:VFT_BFP 0 "register_operand" "=f")
> +        (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "f")
> +                             (match_operand:VFT_BFP 2 "register_operand" 
> "f")]

Whitespace.
We should use v constraint here.

> +                                     UNSPEC_FMAX))]
> +  "TARGET_VXE"
> +  "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
> +  [(set_attr "op_type" "VRR")])
> +
> +; fmin
> +(define_insn "fmin<mode>3"
> +  [(set (match_operand:VFT_BFP 0 "register_operand" "=f")
> +        (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "f")
> +                              (match_operand:VFT_BFP 2 "register_operand" 
> "f")]
> +                                     UNSPEC_FMIN))]

Ditto.

> +  "TARGET_VXE"
> +  "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
> +  [(set_attr "op_type" "VRR")])
> diff --git a/gcc/testsuite/gcc.target/s390/fminmax-1.c 
> b/gcc/testsuite/gcc.target/s390/fminmax-1.c
> new file mode 100644
> index 000000000000..df10905f037a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/fminmax-1.c
> @@ -0,0 +1,77 @@
> +/* Check fmin/fmax expanders for scalars on VXE targets.  */
> +
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=z14 -mzarch" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +/*
> +** dofmaxl:
> +**   vl      (%v.),0\(%r3\),3
> +**   vl      (%v.),0\(%r4\),3
> +**   wfmaxxb (%v.),\1,\2,4
> +**   vst     \3,0\(%r2\),3
> +**   br      %r14
> +*/
> +long double
> +dofmaxl (long double d1, long double d2)
> +{
> +  return __builtin_fmaxl (d1, d2);
> +}
> +
> +/*
> +** dofminl:
> +**   vl      (%v.),0\(%r3\),3
> +**   vl      (%v.),0\(%r4\),3
> +**   wfminxb (%v.),\1,\2,4
> +**   vst     \3,0\(%r2\),3
> +**   br      %r14
> +*/
> +long double
> +dofminl (long double d1, long double d2)
> +{
> +  return __builtin_fminl (d1, d2);
> +}
> +
> +/*
> +** dofmax:
> +**   wfmaxdb %v0,%v0,%v2,4
> +**   br      %r14
> +*/
> +double
> +dofmax (double d1, double d2)
> +{
> +  return __builtin_fmax (d1, d2);
> +}
> +
> +/*
> +** dofmin:
> +**   wfmindb %v0,%v0,%v2,4
> +**   br      %r14
> +*/
> +double
> +dofmin (double d1, double d2)
> +{
> +  return __builtin_fmin (d1, d2);
> +}
> +
> +/*
> +** dofmaxf:
> +**   wfmaxsb %v0,%v0,%v2,4
> +**   br      %r14
> +*/
> +float
> +dofmaxf (float f1, float f2)
> +{
> +  return __builtin_fmaxf (f1, f2);
> +}
> +
> +/*
> +** dofminf:
> +**   wfminsb %v0,%v0,%v2,4
> +**   br      %r14
> +*/
> +float
> +dofminf (float f1, float f2)
> +{
> +  return __builtin_fminf (f1, f2);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/fminmax-2.c 
> b/gcc/testsuite/gcc.target/s390/fminmax-2.c
> new file mode 100644
> index 000000000000..ea37a0a821de
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/fminmax-2.c
> @@ -0,0 +1,29 @@
> +/* Check fmin/fmax expanders for scalars on non-VXE targets.  */
> +
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=z13 -mzarch" } */
> +/* { dg-final { scan-assembler-times "jg" 4 } } */
> +
> +double
> +dofmax (double d1, double d2)
> +{
> +  return __builtin_fmax (d1, d2);
> +}
> +
> +double
> +dofmin (double d1, double d2)
> +{
> +  return __builtin_fmin (d1, d2);
> +}
> +
> +float
> +dofmaxf (float f1, float f2)
> +{
> +  return __builtin_fmaxf (f1, f2);
> +}
> +
> +float
> +dofminf (float f1, float f2)
> +{
> +  return __builtin_fminf (f1, f2);
> +}
> -- 
> 2.43.5
> 

Reply via email to