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. Ok for trunk?
gcc/ChangeLog:
* config/s390/s390.md: Update UNSPECs
* config/s390/vector.md (fmax<mode>3): New expander.
(fmin<mode>3): New expander.
* config/s390/vx-builtins.md (*fmin<mode>): New insn.
(vfmin<mode>): Redefined to use new insn.
(*fmax<mode>): New insn.
(vfmax<mode>): Redefined to use new insn.
gcc/testsuite/ChangeLog:
* gcc.target/s390/fminmax-1.c: New test.
* gcc.target/s390/fminmax-2.c: New test.
Signed-off-by: Juergen Christ <[email protected]>
---
gcc/config/s390/s390.md | 6 +-
gcc/config/s390/vector.md | 25 ++++++++
gcc/config/s390/vx-builtins.md | 29 ++++++---
gcc/testsuite/gcc.target/s390/fminmax-1.c | 77 +++++++++++++++++++++++
gcc/testsuite/gcc.target/s390/fminmax-2.c | 29 +++++++++
5 files changed, 156 insertions(+), 10 deletions(-)
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..1c88c9624b60 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -241,9 +241,6 @@
UNSPEC_VEC_MSUM
- UNSPEC_VEC_VFMIN
- UNSPEC_VEC_VFMAX
-
UNSPEC_VEC_VBLEND
UNSPEC_VEC_VEVAL
UNSPEC_VEC_VGEM
@@ -256,6 +253,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..8bda30624c22 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -89,6 +89,13 @@
(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")
(TF "TARGET_VXE")])
+; FP scalar and vector modes
+(define_mode_iterator VFT_BFP [SF DF
+ (V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF
"TARGET_VXE")
+ V1DF V2DF
+ (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
+
+
(define_mode_iterator V_8 [V1QI])
(define_mode_iterator V_16 [V2QI V1HI])
(define_mode_iterator V_32 [V4QI V2HI V1SI V1SF])
@@ -3576,3 +3583,21 @@
; vec_unpacks_float_lo
; vec_unpacku_float_hi
; vec_unpacku_float_lo
+
+; fmax
+(define_expand "fmax<mode>3"
+ [(set (match_operand:VFT_BFP 0 "register_operand" "=v")
+ (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v")
+ (match_operand:VFT_BFP 2 "register_operand" "v")
+ (const_int 4)]
+ UNSPEC_FMAX))]
+ "TARGET_VXE")
+
+; fmin
+(define_expand "fmin<mode>3"
+ [(set (match_operand:VFT_BFP 0 "register_operand" "=v")
+ (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v")
+ (match_operand:VFT_BFP 2 "register_operand" "v")
+ (const_int 4)]
+ UNSPEC_FMIN))]
+ "TARGET_VXE")
diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index a7bb7ff92f5e..0508df43b866 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -2136,15 +2136,32 @@
"<vw>fche<sdx>bs\t%v2,%v0,%v1"
[(set_attr "op_type" "VRR")])
+(define_insn "*fmin<mode>"
+ [(set (match_operand:VFT_BFP 0 "register_operand" "=v")
+ (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v")
+ (match_operand:VFT_BFP 2 "register_operand" "v")
+ (match_operand:QI 3 "const_mask_operand" "C")]
+ UNSPEC_FMIN))]
+ "TARGET_VXE"
+ "<vw>fmin<sdx>b\t%v0,%v1,%v2,%b3"
+ [(set_attr "op_type" "VRR")])
-(define_insn "vfmin<mode>"
+(define_expand "vfmin<mode>"
[(set (match_operand:VF_HW 0 "register_operand" "=v")
(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(match_operand:QI 3 "const_mask_operand" "C")]
- UNSPEC_VEC_VFMIN))]
+ UNSPEC_FMIN))]
+ "TARGET_VXE")
+
+(define_insn "*fmax<mode>"
+ [(set (match_operand:VFT_BFP 0 "register_operand" "=v")
+ (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v")
+ (match_operand:VFT_BFP 2 "register_operand" "v")
+ (match_operand:QI 3 "const_mask_operand" "C")]
+ UNSPEC_FMAX))]
"TARGET_VXE"
- "<vw>fmin<sdx>b\t%v0,%v1,%v2,%b3"
+ "<vw>fmax<sdx>b\t%v0,%v1,%v2,%b3"
[(set_attr "op_type" "VRR")])
(define_insn "vfmax<mode>"
@@ -2152,10 +2169,8 @@
(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v")
(match_operand:VF_HW 2 "register_operand" "v")
(match_operand:QI 3 "const_mask_operand" "C")]
- UNSPEC_VEC_VFMAX))]
- "TARGET_VXE"
- "<vw>fmax<sdx>b\t%v0,%v1,%v2,%b3"
- [(set_attr "op_type" "VRR")])
+ UNSPEC_FMAX))]
+ "TARGET_VXE")
; vec_insert (__builtin_bswap32 (*a), b, 1) set-element-bswap-2.c
; b[1] = __builtin_bswap32 (*a) set-element-bswap-3.c
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