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 >