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.

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
 ])
 
 ;;
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")])
+
+; 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")]
+                                       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))]
+  "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