public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-08-20  9:19 ` Ilya Leoshkevich
  2019-08-20 15:43   ` Segher Boessenkool
  2019-08-20 16:13   ` Segher Boessenkool
  2019-08-20  9:20 ` [PATCH 4/8] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

Currently it's not clear whether or not min, max and ltgt should raise
floating point exceptions when dealing with qNaNs.

Right now a lot of code assumes that LTGT is signaling: in particular,
it's generated for ((x < y) || (x > y)), which is signaling. The
behavior of MIN/MAX is (intentionally?) left unspecified, according to
commit 64dd117734d0 ("Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN
intrinsics").

So document the status quo.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/91323
	* doc/generic.texi (LTGT_EXPR): Restore the original wording
	regarding floating point exceptions.
	(MIN_EXPR, MAX_EXPR): Document.
	* doc/md.texi (smin, smax): Add a clause regarding floating
	point exceptions.
	* doc/rtl.texi (smin, smax): Add a clause regarding floating
	point exceptions.
---
 gcc/doc/generic.texi | 16 +++++++++++++---
 gcc/doc/md.texi      |  3 ++-
 gcc/doc/rtl.texi     |  3 ++-
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index 8901d5f357e..d5ae20bd461 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -1331,6 +1331,8 @@ the byte offset of the field, but should not be used directly; call
 @tindex UNGE_EXPR
 @tindex UNEQ_EXPR
 @tindex LTGT_EXPR
+@tindex MIN_EXPR
+@tindex MAX_EXPR
 @tindex MODIFY_EXPR
 @tindex INIT_EXPR
 @tindex COMPOUND_EXPR
@@ -1602,13 +1604,21 @@ These operations take two floating point operands and determine whether
 the operands are unordered or are less than, less than or equal to,
 greater than, greater than or equal to, or equal respectively.  For
 example, @code{UNLT_EXPR} returns true if either operand is an IEEE
-NaN or the first operand is less than the second.  With the possible
-exception of @code{LTGT_EXPR}, all of these operations are guaranteed
-not to generate a floating point exception.  The result
+NaN or the first operand is less than the second.  Only @code{LTGT_EXPR}
+is expected to raise an invalid floating-point-operation trap when the
+outcome is unordered.  All other operations are guaranteed not to raise
+a floating point exception.  The result
 type of these expressions will always be of integral or boolean type.
 These operations return the result type's zero value for false,
 and the result type's one value for true.
 
+@item MIN_EXPR
+@itemx MAX_EXPR
+These nodes represent minimum and maximum operations.  When used with
+floating point, if both operands are zeros, or if either operand is
+@code{NaN}, then it is unspecified which of the two operands is returned
+as the result and whether or not a floating point exception is raised.
+
 @item MODIFY_EXPR
 These nodes represent assignment.  The left-hand side is the first
 operand; the right-hand side is the second operand.  The left-hand side
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 7751984bf5f..74f8ec84974 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5353,7 +5353,8 @@ in the rtl as
 @item @samp{smin@var{m}3}, @samp{smax@var{m}3}
 Signed minimum and maximum operations.  When used with floating point,
 if both operands are zeros, or if either operand is @code{NaN}, then
-it is unspecified which of the two operands is returned as the result.
+it is unspecified which of the two operands is returned as the result
+and whether or not a floating point exception is raised.
 
 @cindex @code{fmin@var{m}3} instruction pattern
 @cindex @code{fmax@var{m}3} instruction pattern
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 0814b66a486..e0628da893d 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -2596,7 +2596,8 @@ Represents the smaller (for @code{smin}) or larger (for @code{smax}) of
 @var{x} and @var{y}, interpreted as signed values in mode @var{m}.
 When used with floating point, if both operands are zeros, or if either
 operand is @code{NaN}, then it is unspecified which of the two operands
-is returned as the result.
+is returned as the result and whether or not a floating point exception
+is raised.
 
 @findex umin
 @findex umax
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 0/8] Use signaling FP comparison instructions
@ 2019-08-20  9:19 Ilya Leoshkevich
  2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

Bootstrapped and regtested on x86_64-redhat-linux and
s390x-redhat-linux.

This patch series adds signaling FP comparison support (both scalar and
vector) to s390 backend.

The first patch documents the current behavior of MIN, MAX and LTGT
operations with respect to signaling.

The second patch adds a hook in order to make it possible to support
only a subset of comparison rtxes in vcond, and the third patch makes
use of it for z13.

Patches 4-6 are preparation cleanups.

The seventh patch is an actual implementation.

The eighth patch contains new tests, that make sure autovectorized
comparisons use proper instructions.

Ilya Leoshkevich (8):
  Document signaling for min, max and ltgt operations
  Introduce vcond_supported_p hook
  S/390: Implement vcond_supported_p hook
  S/390: Implement vcond expander for V1TI,V1TF
  S/390: Remove code duplication in vec_unordered<mode>
  S/390: Remove code duplication in vec_* comparison expanders
  S/390: Use signaling FP comparison instructions
  S/390: Test signaling FP comparison instructions

 gcc/config/s390/2827.md                       |  14 +-
 gcc/config/s390/2964.md                       |  13 +-
 gcc/config/s390/3906.md                       |  17 +-
 gcc/config/s390/8561.md                       |  19 +-
 gcc/config/s390/s390-builtins.def             |  16 +-
 gcc/config/s390/s390-modes.def                |   8 +
 gcc/config/s390/s390.c                        |  62 ++++-
 gcc/config/s390/s390.md                       |  14 +
 gcc/config/s390/vector.md                     | 261 ++++++++++++------
 gcc/doc/generic.texi                          |  16 +-
 gcc/doc/md.texi                               |   3 +-
 gcc/doc/rtl.texi                              |   3 +-
 gcc/doc/tm.texi                               |   9 +
 gcc/doc/tm.texi.in                            |   2 +
 gcc/optabs-tree.c                             |   6 +-
 gcc/target.def                                |  11 +
 gcc/targhooks.c                               |  12 +
 gcc/targhooks.h                               |   1 +
 gcc/testsuite/gcc.target/s390/s390.exp        |   8 +
 .../gcc.target/s390/vector/vec-scalar-cmp-1.c |   8 +-
 .../s390/zvector/autovec-double-quiet-eq.c    |   8 +
 .../s390/zvector/autovec-double-quiet-ge.c    |   8 +
 .../s390/zvector/autovec-double-quiet-gt.c    |   8 +
 .../s390/zvector/autovec-double-quiet-le.c    |   8 +
 .../s390/zvector/autovec-double-quiet-lt.c    |   8 +
 .../zvector/autovec-double-quiet-ordered.c    |  10 +
 .../s390/zvector/autovec-double-quiet-uneq.c  |  10 +
 .../zvector/autovec-double-quiet-unordered.c  |  11 +
 .../autovec-double-signaling-ge-z13-finite.c  |  10 +
 .../zvector/autovec-double-signaling-ge-z13.c |   9 +
 .../zvector/autovec-double-signaling-ge.c     |   8 +
 .../autovec-double-signaling-gt-z13-finite.c  |  10 +
 .../zvector/autovec-double-signaling-gt-z13.c |   9 +
 .../zvector/autovec-double-signaling-gt.c     |   8 +
 .../autovec-double-signaling-le-z13-finite.c  |  10 +
 .../zvector/autovec-double-signaling-le-z13.c |   9 +
 .../zvector/autovec-double-signaling-le.c     |   8 +
 .../autovec-double-signaling-lt-z13-finite.c  |  10 +
 .../zvector/autovec-double-signaling-lt-z13.c |   9 +
 .../zvector/autovec-double-signaling-lt.c     |   8 +
 ...autovec-double-signaling-ltgt-z13-finite.c |   9 +
 .../autovec-double-signaling-ltgt-z13.c       |   9 +
 .../zvector/autovec-double-signaling-ltgt.c   |   9 +
 .../s390/zvector/autovec-double-smax-z13.F90  |  11 +
 .../s390/zvector/autovec-double-smax.F90      |   8 +
 .../s390/zvector/autovec-double-smin-z13.F90  |  11 +
 .../s390/zvector/autovec-double-smin.F90      |   8 +
 .../s390/zvector/autovec-float-quiet-eq.c     |   8 +
 .../s390/zvector/autovec-float-quiet-ge.c     |   8 +
 .../s390/zvector/autovec-float-quiet-gt.c     |   8 +
 .../s390/zvector/autovec-float-quiet-le.c     |   8 +
 .../s390/zvector/autovec-float-quiet-lt.c     |   8 +
 .../zvector/autovec-float-quiet-ordered.c     |  10 +
 .../s390/zvector/autovec-float-quiet-uneq.c   |  10 +
 .../zvector/autovec-float-quiet-unordered.c   |  11 +
 .../s390/zvector/autovec-float-signaling-ge.c |   8 +
 .../s390/zvector/autovec-float-signaling-gt.c |   8 +
 .../s390/zvector/autovec-float-signaling-le.c |   8 +
 .../s390/zvector/autovec-float-signaling-lt.c |   8 +
 .../zvector/autovec-float-signaling-ltgt.c    |   9 +
 .../gcc.target/s390/zvector/autovec-fortran.h |   7 +
 .../autovec-long-double-signaling-ge.c        |   8 +
 .../autovec-long-double-signaling-gt.c        |   8 +
 .../autovec-long-double-signaling-le.c        |   8 +
 .../autovec-long-double-signaling-lt.c        |   8 +
 .../gcc.target/s390/zvector/autovec.h         |  40 +++
 66 files changed, 795 insertions(+), 143 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec.h

-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 4/8] S/390: Implement vcond expander for V1TI,V1TF
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
  2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
@ 2019-08-20  9:20 ` Ilya Leoshkevich
  2019-08-20  9:20 ` [PATCH 3/8] S/390: Implement vcond_supported_p hook Ilya Leoshkevich
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:20 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

Currently gcc does not emit wf{c,k}* instructions when comparing long
double values.  Middle-end actually adds them in the first place, but
then veclower pass replaces them with floating point register pair
operations, because the corresponding expander is missing.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/vector.md (vcondv1tiv1tf): New variant of
	vcond$a$b expander.
---
 gcc/config/s390/vector.md | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 0702e1de835..7d90d97b006 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -629,6 +629,21 @@
   DONE;
 })
 
+(define_expand "vcondv1tiv1tf"
+  [(set (match_operand:V1TI 0 "register_operand" "")
+	(if_then_else:V1TI
+	 (match_operator 3 "comparison_operator"
+			 [(match_operand:V1TF 4 "register_operand" "")
+			  (match_operand:V1TF 5 "nonmemory_operand" "")])
+	 (match_operand:V1TI 1 "nonmemory_operand" "")
+	 (match_operand:V1TI 2 "nonmemory_operand" "")))]
+  "TARGET_VXE"
+{
+  s390_expand_vcond (operands[0], operands[1], operands[2],
+		     GET_CODE (operands[3]), operands[4], operands[5]);
+  DONE;
+})
+
 (define_expand "vcondu<V_HW:mode><V_HW2:mode>"
   [(set (match_operand:V_HW 0 "register_operand" "")
 	(if_then_else:V_HW
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 3/8] S/390: Implement vcond_supported_p hook
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
  2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
  2019-08-20  9:20 ` [PATCH 4/8] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
@ 2019-08-20  9:20 ` Ilya Leoshkevich
  2019-08-20  9:20 ` [PATCH 2/8] Introduce " Ilya Leoshkevich
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:20 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

z13 supports only non-signaling vector comparisons.  This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.  Notify
middle-end about this using vcond_supported_p hook.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/s390.c (s390_vcond_supported_p): Implement
	vcond_supported_p.
	(TARGET_VCOND_SUPPORTED_P): Likewise.
---
 gcc/config/s390/s390.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index fa17d7d5d08..675360f5a71 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -16030,6 +16030,27 @@ s390_vector_alignment (const_tree type)
   return MIN (64, tree_to_shwi (TYPE_SIZE (type)));
 }
 
+/* Return true if vcond$a$b expander supports given vector comparison.  */
+
+static bool
+s390_vcond_supported_p (machine_mode, machine_mode op_mode, int code)
+{
+  if (!HONOR_NANS (op_mode))
+    return true;
+  switch (code)
+    {
+    case LE_EXPR:
+    case LT_EXPR:
+    case GE_EXPR:
+    case GT_EXPR:
+    case LTGT_EXPR:
+      /* Signaling vector comparisons are supported only on z14+.  */
+      return TARGET_Z14;
+    default:
+      return true;
+    }
+}
+
 /* Implement TARGET_CONSTANT_ALIGNMENT.  Alignment on even addresses for
    LARL instruction.  */
 
@@ -16660,6 +16681,9 @@ s390_shift_truncation_mask (machine_mode mode)
 #undef TARGET_VECTOR_ALIGNMENT
 #define TARGET_VECTOR_ALIGNMENT s390_vector_alignment
 
+#undef TARGET_VCOND_SUPPORTED_P
+#define TARGET_VCOND_SUPPORTED_P s390_vcond_supported_p
+
 #undef TARGET_INVALID_BINARY_OP
 #define TARGET_INVALID_BINARY_OP s390_invalid_binary_op
 
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 2/8] Introduce vcond_supported_p hook
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (2 preceding siblings ...)
  2019-08-20  9:20 ` [PATCH 3/8] S/390: Implement vcond_supported_p hook Ilya Leoshkevich
@ 2019-08-20  9:20 ` Ilya Leoshkevich
  2019-08-20 11:37   ` Richard Sandiford
  2019-08-20  9:26 ` [PATCH 5/8] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:20 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

z13 supports only non-signaling vector comparisons.  This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
However, we cannot express this restriction today: the code only checks
whether vcond$a$b optab, which does not contain information about the
operation.

Introduce a hook that tells whether target supports certain vector
comparison operations with certain modes.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document.
	* doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document.
	* optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p
	in addition to get_vcond_icode.
	* target.def (vcond_supported_p): New hook.
	* targhooks.c (default_vcond_supported_p): Likewise.
	* targhooks.h (default_vcond_supported_p): Likewise.
---
 gcc/doc/tm.texi    |  9 +++++++++
 gcc/doc/tm.texi.in |  2 ++
 gcc/optabs-tree.c  |  6 ++++--
 gcc/target.def     | 11 +++++++++++
 gcc/targhooks.c    | 12 ++++++++++++
 gcc/targhooks.h    |  1 +
 6 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4eadd0c9300..23ccce1d3f4 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4326,6 +4326,15 @@ insns involving vector mode @var{mode}.  At the very least, it
 must have move patterns for this mode.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_VCOND_SUPPORTED_P (machine_mode @var{result_mode}, machine_mode @var{op_mode}, int @var{code})
+Define this to restrict which vector comparison operations are supported by
+vcond$a$b expander.  An operation is represented by its operand machine mode
+@code{OP_MODE}, its result machine mode @code{RESULT_MODE} and @code{enum
+tree_code CODE}.  The main use of this hook is to support machines which
+provide only certain vector comparison instructions, e.g. only non-signaling
+ones.  The default is that all operations are supported.
+@end deftypefn
+
 @deftypefn {Target Hook} opt_machine_mode TARGET_ARRAY_MODE (machine_mode @var{mode}, unsigned HOST_WIDE_INT @var{nelems})
 Return the mode that GCC should use for an array that has
 @var{nelems} elements, with each element having mode @var{mode}.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 04f236f611e..a4399cd9d12 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3366,6 +3366,8 @@ stack.
 
 @hook TARGET_VECTOR_MODE_SUPPORTED_P
 
+@hook TARGET_VCOND_SUPPORTED_P
+
 @hook TARGET_ARRAY_MODE
 
 @hook TARGET_ARRAY_MODE_SUPPORTED_P
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..de62e3d2765 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -347,8 +347,10 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
       || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
     return false;
 
-  if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
-		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
+  if (((get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
+		         TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
+       || !targetm.vcond_supported_p (TYPE_MODE (value_type),
+                                      TYPE_MODE (cmp_op_type), code))
       && ((code != EQ_EXPR && code != NE_EXPR)
 	  || get_vcond_eq_icode (TYPE_MODE (value_type),
 				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
diff --git a/gcc/target.def b/gcc/target.def
index b2332d8215c..4cd2a964c0e 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3379,6 +3379,17 @@ the vector element type.",
  HOST_WIDE_INT, (const_tree type),
  default_vector_alignment)
 
+DEFHOOK
+(vcond_supported_p,
+ "Define this to restrict which vector comparison operations are supported by\n\
+vcond$a$b expander.  An operation is represented by its operand machine mode\n\
+@code{OP_MODE}, its result machine mode @code{RESULT_MODE} and @code{enum\n\
+tree_code CODE}.  The main use of this hook is to support machines which\n\
+provide only certain vector comparison instructions, e.g. only non-signaling\n\
+ones.  The default is that all operations are supported.",
+ bool, (machine_mode result_mode, machine_mode op_mode, int code),
+ default_vcond_supported_p)
+
 DEFHOOK
 (array_mode,
  "Return the mode that GCC should use for an array that has\n\
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 1d12ec54704..2b9a5d12bab 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -448,6 +448,18 @@ default_scalar_mode_supported_p (scalar_mode mode)
     }
 }
 
+/* Return true if vcond$a$b expander supports vector comparisons using the CODE
+   of type enum tree_code, in which the operands have machine mode OP_MODE and
+   the result has machine mode RESULT_MODE.  */
+
+bool
+default_vcond_supported_p (machine_mode result_mode ATTRIBUTE_UNUSED,
+                           machine_mode op_mode ATTRIBUTE_UNUSED,
+                           int code ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
 /* Return true if libgcc supports floating-point mode MODE (known to
    be supported as a scalar mode).  */
 
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 20a6e79d2d2..771a0996567 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -76,6 +76,7 @@ extern tree default_mangle_assembler_name (const char *);
 
 extern machine_mode default_translate_mode_attribute (machine_mode);
 extern bool default_scalar_mode_supported_p (scalar_mode);
+extern bool default_vcond_supported_p (machine_mode, machine_mode, int);
 extern bool default_libgcc_floating_mode_supported_p (scalar_float_mode);
 extern opt_scalar_float_mode default_floatn_mode (int, bool);
 extern bool default_floatn_builtin_p (int);
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 5/8] S/390: Remove code duplication in vec_unordered<mode>
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (3 preceding siblings ...)
  2019-08-20  9:20 ` [PATCH 2/8] Introduce " Ilya Leoshkevich
@ 2019-08-20  9:26 ` Ilya Leoshkevich
  2019-08-20  9:51 ` [PATCH 7/8] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:26 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

vec_unordered<mode> is vec_ordered<mode> plus a negation at the end.
Reuse vec_unordered<mode> logic.

gcc/ChangeLog:

2019-08-13  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/vector.md (vec_unordered<mode>): Call
	gen_vec_ordered<mode>.
---
 gcc/config/s390/vector.md | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 7d90d97b006..5f1b82beb6c 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1561,15 +1561,15 @@
 
 ; UNORDERED (a, b): !ORDERED (a, b)
 (define_expand "vec_unordered<mode>"
-  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
-	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
-		 (match_operand:VFT 2 "register_operand"  "v")))
-   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
-   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
+  [(match_operand:<tointvec> 0 "register_operand" "=v")
+   (match_operand:VFT        1 "register_operand" "v")
+   (match_operand:VFT        2 "register_operand" "v")]
   "TARGET_VX"
 {
-  operands[3] = gen_reg_rtx (<tointvec>mode);
+  emit_insn (gen_vec_ordered<mode> (operands[0], operands[1], operands[2]));
+  emit_insn (gen_rtx_SET (operands[0],
+	     gen_rtx_NOT (<tointvec>mode, operands[0])));
+  DONE;
 })
 
 (define_expand "vec_unordered"
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 6/8] S/390: Remove code duplication in vec_* comparison expanders
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (6 preceding siblings ...)
  2019-08-20  9:51 ` [PATCH 8/8] S/390: Test " Ilya Leoshkevich
@ 2019-08-20  9:51 ` Ilya Leoshkevich
  2019-08-23 20:41 ` [PATCH 0/8] Use signaling FP comparison instructions Joseph Myers
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:51 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

s390.md uses a lot of near-identical expanders that perform dispatching
to other expanders based on operand types. Since the following patch
would require even more of these, avoid copy-pasting the code by
generating these expanders using an iterator.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/s390.c (s390_expand_vec_compare): Use
	gen_vec_cmpordered and gen_vec_cmpunordered.
	* config/s390/vector.md (vec_cmpuneq, vec_cmpltgt, vec_ordered,
	vec_unordered): Delete.
	(vec_ordered<mode>): Rename to vec_cmpordered<mode>.
	(vec_unordered<mode>): Rename to vec_cmpunordered<mode>.
	(vec_cmp<code>): Generic dispatcher.
---
 gcc/config/s390/s390.c    |  4 +--
 gcc/config/s390/vector.md | 67 +++++++--------------------------------
 2 files changed, 13 insertions(+), 58 deletions(-)

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 675360f5a71..afd81cdc24b 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6523,10 +6523,10 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
 	  emit_insn (gen_vec_cmpltgt (target, cmp_op1, cmp_op2));
 	  return;
 	case ORDERED:
-	  emit_insn (gen_vec_ordered (target, cmp_op1, cmp_op2));
+	  emit_insn (gen_vec_cmpordered (target, cmp_op1, cmp_op2));
 	  return;
 	case UNORDERED:
-	  emit_insn (gen_vec_unordered (target, cmp_op1, cmp_op2));
+	  emit_insn (gen_vec_cmpunordered (target, cmp_op1, cmp_op2));
 	  return;
 	default: break;
 	}
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 5f1b82beb6c..43a913bbf27 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1487,22 +1487,6 @@
   operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
-(define_expand "vec_cmpuneq"
-  [(match_operand 0 "register_operand" "")
-   (match_operand 1 "register_operand" "")
-   (match_operand 2 "register_operand" "")]
-  "TARGET_VX"
-{
-  if (GET_MODE (operands[1]) == V4SFmode)
-    emit_insn (gen_vec_cmpuneqv4sf (operands[0], operands[1], operands[2]));
-  else if (GET_MODE (operands[1]) == V2DFmode)
-    emit_insn (gen_vec_cmpuneqv2df (operands[0], operands[1], operands[2]));
-  else
-    gcc_unreachable ();
-
-  DONE;
-})
-
 ; LTGT a <> b -> a > b | b > a
 (define_expand "vec_cmpltgt<mode>"
   [(set (match_operand:<tointvec>         0 "register_operand" "=v")
@@ -1515,24 +1499,8 @@
   operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
-(define_expand "vec_cmpltgt"
-  [(match_operand 0 "register_operand" "")
-   (match_operand 1 "register_operand" "")
-   (match_operand 2 "register_operand" "")]
-  "TARGET_VX"
-{
-  if (GET_MODE (operands[1]) == V4SFmode)
-    emit_insn (gen_vec_cmpltgtv4sf (operands[0], operands[1], operands[2]));
-  else if (GET_MODE (operands[1]) == V2DFmode)
-    emit_insn (gen_vec_cmpltgtv2df (operands[0], operands[1], operands[2]));
-  else
-    gcc_unreachable ();
-
-  DONE;
-})
-
 ; ORDERED (a, b): a >= b | b > a
-(define_expand "vec_ordered<mode>"
+(define_expand "vec_cmpordered<mode>"
   [(set (match_operand:<tointvec>          0 "register_operand" "=v")
 	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
 		 (match_operand:VFT 2 "register_operand"  "v")))
@@ -1543,45 +1511,32 @@
   operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
-(define_expand "vec_ordered"
-  [(match_operand 0 "register_operand" "")
-   (match_operand 1 "register_operand" "")
-   (match_operand 2 "register_operand" "")]
-  "TARGET_VX"
-{
-  if (GET_MODE (operands[1]) == V4SFmode)
-    emit_insn (gen_vec_orderedv4sf (operands[0], operands[1], operands[2]));
-  else if (GET_MODE (operands[1]) == V2DFmode)
-    emit_insn (gen_vec_orderedv2df (operands[0], operands[1], operands[2]));
-  else
-    gcc_unreachable ();
-
-  DONE;
-})
-
 ; UNORDERED (a, b): !ORDERED (a, b)
-(define_expand "vec_unordered<mode>"
+(define_expand "vec_cmpunordered<mode>"
   [(match_operand:<tointvec> 0 "register_operand" "=v")
    (match_operand:VFT        1 "register_operand" "v")
    (match_operand:VFT        2 "register_operand" "v")]
   "TARGET_VX"
 {
-  emit_insn (gen_vec_ordered<mode> (operands[0], operands[1], operands[2]));
+  emit_insn (gen_vec_cmpordered<mode> (operands[0], operands[1], operands[2]));
   emit_insn (gen_rtx_SET (operands[0],
 	     gen_rtx_NOT (<tointvec>mode, operands[0])));
   DONE;
 })
 
-(define_expand "vec_unordered"
+(define_code_iterator VEC_CODE_WITH_COMPLEX_EXPAND
+  [uneq ltgt ordered unordered])
+
+(define_expand "vec_cmp<code>"
   [(match_operand 0 "register_operand" "")
-   (match_operand 1 "register_operand" "")
-   (match_operand 2 "register_operand" "")]
+   (VEC_CODE_WITH_COMPLEX_EXPAND (match_operand 1 "register_operand" "")
+				 (match_operand 2 "register_operand" ""))]
   "TARGET_VX"
 {
   if (GET_MODE (operands[1]) == V4SFmode)
-    emit_insn (gen_vec_unorderedv4sf (operands[0], operands[1], operands[2]));
+    emit_insn (gen_vec_cmp<code>v4sf (operands[0], operands[1], operands[2]));
   else if (GET_MODE (operands[1]) == V2DFmode)
-    emit_insn (gen_vec_unorderedv2df (operands[0], operands[1], operands[2]));
+    emit_insn (gen_vec_cmp<code>v2df (operands[0], operands[1], operands[2]));
   else
     gcc_unreachable ();
 
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 8/8] S/390: Test signaling FP comparison instructions
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (5 preceding siblings ...)
  2019-08-20  9:51 ` [PATCH 7/8] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-08-20  9:51 ` Ilya Leoshkevich
  2019-08-20  9:51 ` [PATCH 6/8] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
  2019-08-23 20:41 ` [PATCH 0/8] Use signaling FP comparison instructions Joseph Myers
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:51 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

gcc/testsuite/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* gcc.target/s390/s390.exp: Enable Fortran tests.
	* gcc.target/s390/zvector/autovec-double-quiet-eq.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-ge.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-gt.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-le.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-lt.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-ordered.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-uneq.c: New test.
	* gcc.target/s390/zvector/autovec-double-quiet-unordered.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ge.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-gt.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-le-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-le.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-lt.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-ltgt.c: New test.
	* gcc.target/s390/zvector/autovec-double-smax-z13.F90: New test.
	* gcc.target/s390/zvector/autovec-double-smax.F90: New test.
	* gcc.target/s390/zvector/autovec-double-smin-z13.F90: New test.
	* gcc.target/s390/zvector/autovec-double-smin.F90: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-eq.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-ge.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-gt.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-le.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-lt.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-ordered.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-uneq.c: New test.
	* gcc.target/s390/zvector/autovec-float-quiet-unordered.c: New test.
	* gcc.target/s390/zvector/autovec-float-signaling-ge.c: New test.
	* gcc.target/s390/zvector/autovec-float-signaling-gt.c: New test.
	* gcc.target/s390/zvector/autovec-float-signaling-le.c: New test.
	* gcc.target/s390/zvector/autovec-float-signaling-lt.c: New test.
	* gcc.target/s390/zvector/autovec-float-signaling-ltgt.c: New test.
	* gcc.target/s390/zvector/autovec-fortran.h: New test.
	* gcc.target/s390/zvector/autovec-long-double-signaling-ge.c: New test.
	* gcc.target/s390/zvector/autovec-long-double-signaling-gt.c: New test.
	* gcc.target/s390/zvector/autovec-long-double-signaling-le.c: New test.
	* gcc.target/s390/zvector/autovec-long-double-signaling-lt.c: New test.
	* gcc.target/s390/zvector/autovec.h: New test.
---
 gcc/testsuite/gcc.target/s390/s390.exp        |  8 ++++
 .../s390/zvector/autovec-double-quiet-eq.c    |  8 ++++
 .../s390/zvector/autovec-double-quiet-ge.c    |  8 ++++
 .../s390/zvector/autovec-double-quiet-gt.c    |  8 ++++
 .../s390/zvector/autovec-double-quiet-le.c    |  8 ++++
 .../s390/zvector/autovec-double-quiet-lt.c    |  8 ++++
 .../zvector/autovec-double-quiet-ordered.c    | 10 +++++
 .../s390/zvector/autovec-double-quiet-uneq.c  | 10 +++++
 .../zvector/autovec-double-quiet-unordered.c  | 11 +++++
 .../autovec-double-signaling-ge-z13-finite.c  | 10 +++++
 .../zvector/autovec-double-signaling-ge-z13.c |  9 +++++
 .../zvector/autovec-double-signaling-ge.c     |  8 ++++
 .../autovec-double-signaling-gt-z13-finite.c  | 10 +++++
 .../zvector/autovec-double-signaling-gt-z13.c |  9 +++++
 .../zvector/autovec-double-signaling-gt.c     |  8 ++++
 .../autovec-double-signaling-le-z13-finite.c  | 10 +++++
 .../zvector/autovec-double-signaling-le-z13.c |  9 +++++
 .../zvector/autovec-double-signaling-le.c     |  8 ++++
 .../autovec-double-signaling-lt-z13-finite.c  | 10 +++++
 .../zvector/autovec-double-signaling-lt-z13.c |  9 +++++
 .../zvector/autovec-double-signaling-lt.c     |  8 ++++
 ...autovec-double-signaling-ltgt-z13-finite.c |  9 +++++
 .../autovec-double-signaling-ltgt-z13.c       |  9 +++++
 .../zvector/autovec-double-signaling-ltgt.c   |  9 +++++
 .../s390/zvector/autovec-double-smax-z13.F90  | 11 +++++
 .../s390/zvector/autovec-double-smax.F90      |  8 ++++
 .../s390/zvector/autovec-double-smin-z13.F90  | 11 +++++
 .../s390/zvector/autovec-double-smin.F90      |  8 ++++
 .../s390/zvector/autovec-float-quiet-eq.c     |  8 ++++
 .../s390/zvector/autovec-float-quiet-ge.c     |  8 ++++
 .../s390/zvector/autovec-float-quiet-gt.c     |  8 ++++
 .../s390/zvector/autovec-float-quiet-le.c     |  8 ++++
 .../s390/zvector/autovec-float-quiet-lt.c     |  8 ++++
 .../zvector/autovec-float-quiet-ordered.c     | 10 +++++
 .../s390/zvector/autovec-float-quiet-uneq.c   | 10 +++++
 .../zvector/autovec-float-quiet-unordered.c   | 11 +++++
 .../s390/zvector/autovec-float-signaling-ge.c |  8 ++++
 .../s390/zvector/autovec-float-signaling-gt.c |  8 ++++
 .../s390/zvector/autovec-float-signaling-le.c |  8 ++++
 .../s390/zvector/autovec-float-signaling-lt.c |  8 ++++
 .../zvector/autovec-float-signaling-ltgt.c    |  9 +++++
 .../gcc.target/s390/zvector/autovec-fortran.h |  7 ++++
 .../autovec-long-double-signaling-ge.c        |  8 ++++
 .../autovec-long-double-signaling-gt.c        |  8 ++++
 .../autovec-long-double-signaling-le.c        |  8 ++++
 .../autovec-long-double-signaling-lt.c        |  8 ++++
 .../gcc.target/s390/zvector/autovec.h         | 40 +++++++++++++++++++
 47 files changed, 443 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec.h

diff --git a/gcc/testsuite/gcc.target/s390/s390.exp b/gcc/testsuite/gcc.target/s390/s390.exp
index 86f7e4398eb..925eb568832 100644
--- a/gcc/testsuite/gcc.target/s390/s390.exp
+++ b/gcc/testsuite/gcc.target/s390/s390.exp
@@ -27,6 +27,7 @@ if ![istarget s390*-*-*] then {
 # Load support procs.
 load_lib gcc-dg.exp
 load_lib target-supports.exp
+load_lib gfortran-dg.exp
 
 # Return 1 if the the assembler understands .machine and .machinemode.  The
 # target attribute needs that feature to work.
@@ -193,6 +194,10 @@ global DEFAULT_CFLAGS
 if ![info exists DEFAULT_CFLAGS] then {
     set DEFAULT_CFLAGS " -ansi -pedantic-errors"
 }
+global DEFAULT_FFLAGS
+if ![info exists DEFAULT_FFLAGS] then {
+    set DEFAULT_FFLAGS " -pedantic-errors"
+}
 
 # Initialize `dg'.
 dg-init
@@ -209,6 +214,9 @@ dg-runtest [lsort [prune [glob -nocomplain $srcdir/$subdir/*.{c,S}] \
 dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*vector*/*.{c,S}]] \
 	"" $DEFAULT_CFLAGS
 
+gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*vector*/*.F90]] \
+	"" $DEFAULT_FFLAGS
+
 dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/target-attribute/*.{c,S}]] \
 	"" $DEFAULT_CFLAGS
 
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
new file mode 100644
index 00000000000..dad138770c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-eq.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_EQ);
+
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
new file mode 100644
index 00000000000..9fddb62573f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_GE);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
new file mode 100644
index 00000000000..eb512f84c47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_GT);
+
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
new file mode 100644
index 00000000000..c049f8b7dee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_LE);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
new file mode 100644
index 00000000000..b6f7702ecd0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_LT);
+
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
new file mode 100644
index 00000000000..bf8ebd4ab6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-ordered.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_ORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
new file mode 100644
index 00000000000..421fb5e7ba5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_UNEQ);
+
+/* { dg-final { scan-assembler-times {\n\tvfchdb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
+/* { dg-final { scan-assembler {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
new file mode 100644
index 00000000000..c42f7930ad8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-unordered.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
+/* combine prefers to reorder vsel args instead of using vno.  */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
new file mode 100644
index 00000000000..b301d1b739b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* We can use non-signaling vector comparison instructions with
+   -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
new file mode 100644
index 00000000000..ee83f3405c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
new file mode 100644
index 00000000000..bcb4c868a15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\tvfkhedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
new file mode 100644
index 00000000000..c49764447f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* We can use non-signaling vector comparison instructions with
+   -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
new file mode 100644
index 00000000000..6b9c11997a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
new file mode 100644
index 00000000000..e423ed0f78c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\tvfkhdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
new file mode 100644
index 00000000000..7fa559b5701
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* We can use non-signaling vector comparison instructions with
+   -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfchedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
new file mode 100644
index 00000000000..a80ac20b905
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
new file mode 100644
index 00000000000..b97bebaaf8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\tvfkhedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
new file mode 100644
index 00000000000..3305a98379c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13-finite.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* We can use non-signaling vector comparison instructions with
+   -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfchdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
new file mode 100644
index 00000000000..8b398a28c37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
new file mode 100644
index 00000000000..b01272d00a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\tvfkhdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
new file mode 100644
index 00000000000..76730d70968
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13-finite.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector -ffinite-math-only" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* ltgt is the same as eq with -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
new file mode 100644
index 00000000000..d466697499a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
new file mode 100644
index 00000000000..645f299a9fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_LTGT);
+
+/* { dg-final { scan-assembler-times {\n\tvfkhdb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
new file mode 100644
index 00000000000..b114082df59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax-z13.F90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z13 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (max)
+
+! Fortran's max does not specify whether or not an exception should be raised in
+! face of qNaNs, and neither does gcc's smax.  Vectorize max using quiet
+! comparison, because that's the only one we have on z13.
+! { dg-final { scan-assembler {\n\tvfchdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
new file mode 100644
index 00000000000..1698ec4f4db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smax.F90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z14 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (max)
+
+! { dg-final { scan-assembler {\n\tvfmaxdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
new file mode 100644
index 00000000000..fc56e9d6879
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin-z13.F90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z13 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (min)
+
+! Fortran's min does not specify whether or not an exception should be raised in
+! face of qNaNs, and neither does gcc's smin.  Vectorize min using quiet
+! comparison, because that's the only one we have on z13.
+! { dg-final { scan-assembler {\n\tvfchdb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90 b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
new file mode 100644
index 00000000000..0dd1a33bb84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-smin.F90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! { dg-options "-ffree-line-length-256 -O3 -march=z14 -mzvector" }
+
+#include "autovec-fortran.h"
+
+AUTOVEC_FORTRAN (min)
+
+! { dg-final { scan-assembler {\n\tvfmindb\t} } }
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
new file mode 100644
index 00000000000..c74927dd028
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-eq.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_EQ);
+
+/* { dg-final { scan-assembler {\n\tvfcesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
new file mode 100644
index 00000000000..4c7cb09eed5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_GE);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
new file mode 100644
index 00000000000..dd787929b9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_GT);
+
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
new file mode 100644
index 00000000000..5bd1e3e98e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_LE);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
new file mode 100644
index 00000000000..4938dcfb430
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_LT);
+
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
new file mode 100644
index 00000000000..222e9efb5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-ordered.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
new file mode 100644
index 00000000000..ab5dcac9c34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNEQ);
+
+/* { dg-final { scan-assembler-times {\n\tvfchsb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
+/* { dg-final { scan-assembler {\n\tvx\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
new file mode 100644
index 00000000000..c800dce2d7b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-unordered.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (QUIET_UNORDERED);
+
+/* { dg-final { scan-assembler {\n\tvfchesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfchsb\t} } } */
+/* combine prefers to reorder vsel args instead of using vno.  */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
new file mode 100644
index 00000000000..0f98c5467e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\tvfkhesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
new file mode 100644
index 00000000000..762c4c2030c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\tvfkhsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
new file mode 100644
index 00000000000..ccf0c5c24d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\tvfkhesb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
new file mode 100644
index 00000000000..b428e5fc52e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\tvfkhsb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
new file mode 100644
index 00000000000..bf15242a4d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_LTGT);
+
+/* { dg-final { scan-assembler-times {\n\tvfkhsb\t} 2 } } */
+/* { dg-final { scan-assembler {\n\tvo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h b/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
new file mode 100644
index 00000000000..8e44cb2dd31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-fortran.h
@@ -0,0 +1,7 @@
+#define AUTOVEC_FORTRAN(OP) subroutine f (r, x, y); \
+  real(kind=kind (1.0d0)) :: r(1000000), x(1000000), y(1000000); \
+  integer :: i; \
+  do i = 1, 1000000; \
+    r(i) = OP (x(i), y(i)); \
+  end do; \
+end
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
new file mode 100644
index 00000000000..684a6a9b2e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-ge.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_GE);
+
+/* { dg-final { scan-assembler {\n\twfkhexb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
new file mode 100644
index 00000000000..76ade12c7f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-gt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_GT);
+
+/* { dg-final { scan-assembler {\n\twfkhxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
new file mode 100644
index 00000000000..a15960ec86a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-le.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_LE);
+
+/* { dg-final { scan-assembler {\n\twfkhexb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
new file mode 100644
index 00000000000..046d5487af8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-long-double-signaling-lt.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_LONG_DOUBLE (SIGNALING_LT);
+
+/* { dg-final { scan-assembler {\n\twfkhxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec.h b/gcc/testsuite/gcc.target/s390/zvector/autovec.h
new file mode 100644
index 00000000000..3e7617d3670
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec.h
@@ -0,0 +1,40 @@
+#ifndef AUTOVEC_H
+#define AUTOVEC_H 1
+
+#define QUIET_EQ(x, y) ((x) == (y))
+#define QUIET_GE __builtin_isgreaterequal
+#define QUIET_GT __builtin_isgreater
+#define QUIET_LE __builtin_islessequal
+#define QUIET_LT __builtin_isless
+#define QUIET_ORDERED(x, y) (!__builtin_isunordered ((x), (y)))
+#define QUIET_UNEQ(x, y) (__builtin_isless ((x), (y)) \
+                          || __builtin_isgreater ((x), (y)))
+#define QUIET_UNORDERED __builtin_isunordered
+#define SIGNALING_GE(x, y) ((x) >= (y))
+#define SIGNALING_GT(x, y) ((x) > (y))
+#define SIGNALING_LE(x, y) ((x) <= (y))
+#define SIGNALING_LT(x, y) ((x) < (y))
+#define SIGNALING_LTGT(x, y) (((x) < (y)) || ((x) > (y)))
+
+#define AUTOVEC(RESULT_TYPE, OP_TYPE, OP) void \
+f (RESULT_TYPE *r, const OP_TYPE *x, const OP_TYPE *y) \
+{ \
+  int i; \
+\
+  for (i = 0; i < 1000000; i++) \
+    { \
+      OP_TYPE xi = x[i], yi = y[i]; \
+\
+      r[i] = OP (xi, yi); \
+    } \
+}
+
+#define AUTOVEC_DOUBLE(OP) AUTOVEC (long, double, OP)
+
+#define AUTOVEC_FLOAT(OP) AUTOVEC (int, float, OP)
+
+typedef __int128 v1ti __attribute__ ((vector_size (16)));
+typedef long double v1tf __attribute__ ((vector_size (16)));
+#define AUTOVEC_LONG_DOUBLE(OP) AUTOVEC (v1ti, v1tf, OP)
+
+#endif
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 7/8] S/390: Use signaling FP comparison instructions
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (4 preceding siblings ...)
  2019-08-20  9:26 ` [PATCH 5/8] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
@ 2019-08-20  9:51 ` Ilya Leoshkevich
  2019-08-20  9:51 ` [PATCH 8/8] S/390: Test " Ilya Leoshkevich
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20  9:51 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ilya Leoshkevich

dg-torture.exp=inf-compare-1.c is failing, because (qNaN > +Inf)
comparison is compiled to CDB instruction, which does not signal an
invalid operation exception. KDB should have been used instead.

This patch introduces a new CCmode and a new pattern in order to
generate signaling instructions in this and similar cases.

gcc/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/2827.md: Add new opcodes.
	* config/s390/2964.md: Likewise.
	* config/s390/3906.md: Likewise.
	* config/s390/8561.md: Likewise.
	* config/s390/s390-builtins.def (s390_vfchesb): Use
	the new vec_cmpgev4sf_quiet_nocc.
	(s390_vfchedb): Use the new vec_cmpgev2df_quiet_nocc.
	(s390_vfchsb): Use the new vec_cmpgtv4sf_quiet_nocc.
	(s390_vfchdb): Use the new vec_cmpgtv2df_quiet_nocc.
	(vec_cmplev4sf): Use the new vec_cmplev4sf_quiet_nocc.
	(vec_cmplev2df): Use the new vec_cmplev2df_quiet_nocc.
	(vec_cmpltv4sf): Use the new vec_cmpltv4sf_quiet_nocc.
	(vec_cmpltv2df): Use the new vec_cmpltv2df_quiet_nocc.
	* config/s390/s390-modes.def (CCSFPS): New mode.
	* config/s390/s390.c (s390_match_ccmode_set): Support CCSFPS.
	(s390_select_ccmode): Return CCSFPS for LT, LE, GT, GE and LTGT.
	(s390_branch_condition_mask): Reuse CCS for CCSFPS.
	(s390_expand_vec_compare): Use non-signaling patterns where
	necessary.
	(s390_reverse_condition): Support CCSFPS.
	* config/s390/s390.md (*cmp<mode>_ccsfps): New pattern.
	* config/s390/vector.md: (VFCMP_HW_OP): Remove.
	(asm_fcmp_op): Likewise.
	(*smaxv2df3_vx): Use pattern for quiet comparison.
	(*sminv2df3_vx): Likewise.
	(*vec_cmp<VFCMP_HW_OP:code><mode>_nocc): Remove.
	(*vec_cmpeq<mode>_quiet_nocc): New pattern.
	(vec_cmpgt<mode>_quiet_nocc): Likewise.
	(vec_cmplt<mode>_quiet_nocc): New expander.
	(vec_cmpge<mode>_quiet_nocc): New pattern.
	(vec_cmple<mode>_quiet_nocc): New expander.
	(*vec_cmpeq<mode>_signaling_nocc): New pattern.
	(*vec_cmpgt<mode>_signaling_nocc): Likewise.
	(*vec_cmpgt<mode>_signaling_finite_nocc): Likewise.
	(*vec_cmpge<mode>_signaling_nocc): Likewise.
	(*vec_cmpge<mode>_signaling_finite_nocc): Likewise.
	(vec_cmpungt<mode>): New expander.
	(vec_cmpunge<mode>): Likewise.
	(vec_cmpuneq<mode>): Use quiet patterns.
	(vec_cmpltgt<mode>): Allow only on z14+.
	(vec_cmpordered<mode>): Use quiet patterns.
	(vec_cmpunordered<mode>): Likewise.
	(VEC_CODE_WITH_COMPLEX_EXPAND): Add ungt and unge.

gcc/testsuite/ChangeLog:

2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>

	* gcc.target/s390/vector/vec-scalar-cmp-1.c: Adjust
	expectations.
---
 gcc/config/s390/2827.md                       |  14 +-
 gcc/config/s390/2964.md                       |  13 +-
 gcc/config/s390/3906.md                       |  17 +-
 gcc/config/s390/8561.md                       |  19 +-
 gcc/config/s390/s390-builtins.def             |  16 +-
 gcc/config/s390/s390-modes.def                |   8 +
 gcc/config/s390/s390.c                        |  34 ++--
 gcc/config/s390/s390.md                       |  14 ++
 gcc/config/s390/vector.md                     | 171 +++++++++++++++---
 .../gcc.target/s390/vector/vec-scalar-cmp-1.c |   8 +-
 10 files changed, 240 insertions(+), 74 deletions(-)

diff --git a/gcc/config/s390/2827.md b/gcc/config/s390/2827.md
index 3f63f82284d..aafe8e27339 100644
--- a/gcc/config/s390/2827.md
+++ b/gcc/config/s390/2827.md
@@ -44,7 +44,7 @@
 
 (define_insn_reservation "zEC12_normal_fp" 8
   (and (eq_attr "cpu" "zEC12")
-       (eq_attr "mnemonic" "lnebr,sdbr,sebr,clfxtr,adbr,aebr,celfbr,clfebr,lpebr,msebr,lndbr,clfdbr,cebr,maebr,ltebr,clfdtr,cdlgbr,cxlftr,lpdbr,cdfbr,lcebr,clfxbr,msdbr,cdbr,madbr,meebr,clgxbr,clgdtr,ledbr,cegbr,cdlftr,cdlgtr,mdbr,clgebr,ltdbr,cdlfbr,cdgbr,clgxtr,lcdbr,celgbr,clgdbr,ldebr,cefbr,fidtr,fixtr,madb,msdb,mseb,fiebra,fidbra,aeb,mdb,seb,cdb,tcdb,sdb,adb,tceb,maeb,ceb,meeb,ldeb")) "nothing")
+       (eq_attr "mnemonic" "lnebr,sdbr,sebr,clfxtr,adbr,aebr,celfbr,clfebr,lpebr,msebr,lndbr,clfdbr,cebr,maebr,ltebr,clfdtr,cdlgbr,cxlftr,lpdbr,cdfbr,lcebr,clfxbr,msdbr,cdbr,madbr,meebr,clgxbr,clgdtr,ledbr,cegbr,cdlftr,cdlgtr,mdbr,clgebr,ltdbr,cdlfbr,cdgbr,clgxtr,lcdbr,celgbr,clgdbr,ldebr,cefbr,fidtr,fixtr,madb,msdb,mseb,fiebra,fidbra,aeb,mdb,seb,cdb,tcdb,sdb,adb,tceb,maeb,ceb,meeb,ldeb,keb,kebr,kdb,kdbr")) "nothing")
 
 (define_insn_reservation "zEC12_cgdbr" 2
   (and (eq_attr "cpu" "zEC12")
@@ -426,6 +426,10 @@
   (and (eq_attr "cpu" "zEC12")
        (eq_attr "mnemonic" "cxbr")) "nothing")
 
+(define_insn_reservation "zEC12_kxbr" 18
+  (and (eq_attr "cpu" "zEC12")
+       (eq_attr "mnemonic" "kxbr")) "nothing")
+
 (define_insn_reservation "zEC12_ddbr" 36
   (and (eq_attr "cpu" "zEC12")
        (eq_attr "mnemonic" "ddbr")) "nothing")
@@ -578,10 +582,18 @@
   (and (eq_attr "cpu" "zEC12")
        (eq_attr "mnemonic" "cdtr")) "nothing")
 
+(define_insn_reservation "zEC12_kdtr" 11
+  (and (eq_attr "cpu" "zEC12")
+       (eq_attr "mnemonic" "kdtr")) "nothing")
+
 (define_insn_reservation "zEC12_cxtr" 14
   (and (eq_attr "cpu" "zEC12")
        (eq_attr "mnemonic" "cxtr")) "nothing")
 
+(define_insn_reservation "zEC12_kxtr" 14
+  (and (eq_attr "cpu" "zEC12")
+       (eq_attr "mnemonic" "kxtr")) "nothing")
+
 (define_insn_reservation "zEC12_slbg" 3
   (and (eq_attr "cpu" "zEC12")
        (eq_attr "mnemonic" "slbg")) "nothing")
diff --git a/gcc/config/s390/2964.md b/gcc/config/s390/2964.md
index a7897bcf58a..4396e3ba1c0 100644
--- a/gcc/config/s390/2964.md
+++ b/gcc/config/s390/2964.md
@@ -69,7 +69,7 @@ ng,ni,niy,ntstg,ny,o,og,oi,oiy,oy,s,sar,sdb,seb,sfpc,sg,sgf,sh,shy,sl,\
 slb,slbg,slg,slgf,sly,sqdb,sqeb,st,stc,stcy,std,stdy,ste,stey,stg,stgrl,\
 sth,sthrl,sthy,stoc,stocg,strl,strv,strvg,strvh,sty,sy,tabort,tm,tmy,vl,\
 vlbb,vleb,vlef,vleg,vleh,vll,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,\
-vlrepf,vlrepg,vlreph,vst,vstl,x,xg,xi,xiy,xy")
+vlrepf,vlrepg,vlreph,vst,vstl,x,xg,xi,xiy,xy,kdb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z13_unit_vfu" ""
@@ -109,7 +109,8 @@ vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,wcdgb,wcdlgb,wcgdb,wclgdb,wfadb,\
 wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexbs,wfchdb,wfchedb,wfchesb,wfchexb,\
 wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfisb,wfixb,wflcdb,wflcsb,wflcxb,wflld,\
 wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmadb,wfmasb,wfmaxb,wfmdb,wfmsb,\
-wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb")
+wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb,kebr,kdb,kdbr,kxbr,\
+kdtr,kxtr,wfkdb,wfksb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z13_cracked" ""
@@ -131,7 +132,7 @@ stmg,stmy,tbegin,tbeginc")
 cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
 lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,ml,mlg,\
 mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,oc,sfpc,slb,slbg,slbgr,slbr,\
-sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z13_endgroup" ""
@@ -198,7 +199,7 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
 vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
 vistrh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlvgp,\
 vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,vslb,vsrab,vsrlb,wfcdb,wfcexbs,\
-wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfchexbs,wfchxbs,wfcsb,kebr,kdb,kdbr,wfkdb,wfksb")) "nothing")
 
 (define_insn_reservation "z13_3" 3
   (and (eq_attr "cpu" "z13")
@@ -232,7 +233,7 @@ wfmdb,wfmsb,wfmsdb,wfmssb,wfmsxb,wfmxb,wfsdb,wfssb,wfsxb,wldeb,wledb")) "nothing
   (and (eq_attr "cpu" "z13")
 (eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,msg,msgr,sdtr,tdcdt,tdcet,\
 vcdgb,vcdlgb,vcgdb,vclgdb,vfadb,vfasb,vfidb,vfisb,vfmadb,vfmasb,vfmdb,vfmsb,\
-vfmsdb,vfmssb,vfsdb,vfssb,vldeb,vledb")) "nothing")
+vfmsdb,vfmssb,vfsdb,vfssb,vldeb,vledb,kdtr")) "nothing")
 
 (define_insn_reservation "z13_8" 8
   (and (eq_attr "cpu" "z13")
@@ -254,7 +255,7 @@ celgbr,flogr,m,madb,maeb,maebr,mfy,ml,mlr,mr,msdb,mseb,msebr")) "nothing")
 (define_insn_reservation "z13_12" 12
   (and (eq_attr "cpu" "z13")
 (eq_attr "mnemonic" "cfdbr,cfebr,cgdbr,cgebr,clfdbr,clfebr,clgdbr,\
-clgebr,cxbr,cxtr,mlg,mlgr,tcxb,tdcxt")) "nothing")
+clgebr,cxbr,cxtr,mlg,mlgr,tcxb,tdcxt,kxbr,kxtr")) "nothing")
 
 (define_insn_reservation "z13_13" 13
   (and (eq_attr "cpu" "z13")
diff --git a/gcc/config/s390/3906.md b/gcc/config/s390/3906.md
index 8cb4565ee22..1212d8b61f1 100644
--- a/gcc/config/s390/3906.md
+++ b/gcc/config/s390/3906.md
@@ -71,7 +71,7 @@ sgh,sh,shy,sl,slb,slbg,slg,slgf,sly,sqdb,sqeb,st,stc,stcy,std,stdy,ste,\
 stey,stg,stgrl,sth,sthrl,sthy,stoc,stocg,strl,strv,strvg,strvh,sty,sy,\
 tabort,tm,tmy,vl,vlbb,vleb,vlef,vleg,vleh,vll,vllezb,vllezf,vllezg,vllezh,\
 vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlrl,vlrlr,vst,vstl,vstrl,vstrlr,x,xg,xi,\
-xiy,xy")
+xiy,xy,kdb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z14_unit_vfu" ""
@@ -113,7 +113,8 @@ wfadb,wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexbs,wfchdb,wfchedb,wfchesb,\
 wfchexb,wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfisb,wfixb,wflcdb,wflcsb,wflcxb,\
 wflld,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmadb,wfmasb,wfmaxb,\
 wfmaxxb,wfmdb,wfminxb,wfmsb,wfmsdb,wfmssb,wfmsxb,wfmxb,wfnmaxb,wfnmsxb,wfsdb,\
-wfssb,wfsxb,wldeb,wledb")
+wfssb,wfsxb,wldeb,wledb,kebr,kdb,kdbr,kxbr,kdtr,kxtr,wfkdb,wfksb,vfkesb,\
+vfkedb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z14_cracked" ""
@@ -135,7 +136,7 @@ stmg,stmy,tbegin,tbeginc")
 cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
 lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,mg,mgrk,\
 ml,mlg,mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,oc,ppa,sfpc,slb,slbg,\
-slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
  (const_int 1)] (const_int 0)))
 
 (define_attr "z14_endgroup" ""
@@ -192,7 +193,8 @@ vrepig,vrepih,vsb,vsbiq,vscbib,vscbif,vscbig,vscbih,vscbiq,vsegb,vsegf,vsegh,\
 vsel,vsf,vsg,vsh,vsl,vslb,vsldb,vsq,vsra,vsrab,vsrl,vsrlb,vuphb,vuphf,\
 vuphh,vuplb,vuplf,vuplhb,vuplhf,vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,\
 wfcedb,wfcesb,wfchdb,wfchedb,wfchesb,wfchexb,wfchsb,wfchxb,wflcdb,wflcsb,\
-wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,xiy")) "nothing")
+wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,xiy,\
+vfkesb,vfkedb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb")) "nothing")
 
 (define_insn_reservation "z14_2" 2
   (and (eq_attr "cpu" "z14")
@@ -204,7 +206,7 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
 vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
 vistrh,vlgvf,vlgvg,vlgvh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,\
 vlrepg,vlreph,vlrl,vlvgp,vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,wfcdb,\
-wfcexbs,wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfcexbs,wfchexbs,wfchxbs,wfcsb,kebr,kdb,kdbr,wfkdb,wfksb")) "nothing")
 
 (define_insn_reservation "z14_3" 3
   (and (eq_attr "cpu" "z14")
@@ -238,7 +240,8 @@ wfmasb,wfmdb,wfmsb,wfmsdb,wfmssb,wfsdb,wfssb,wldeb,wledb")) "nothing")
 (define_insn_reservation "z14_7" 7
   (and (eq_attr "cpu" "z14")
 (eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,msgrkc,sdtr,tdcdt,tdcet,\
-vfasb,vfisb,vfmasb,vfmsb,vfmssb,vfnmssb,vfssb,vgef,vgeg,wflld")) "nothing")
+vfasb,vfisb,vfmasb,vfmsb,vfmssb,vfnmssb,vfssb,vgef,vgeg,wflld,kdtr"))
+"nothing")
 
 (define_insn_reservation "z14_8" 8
   (and (eq_attr "cpu" "z14")
@@ -261,7 +264,7 @@ celgbr,madb,maeb,maebr,msdb,mseb,msebr,vscef,vsceg")) "nothing")
 (define_insn_reservation "z14_12" 12
   (and (eq_attr "cpu" "z14")
 (eq_attr "mnemonic" "cfdbr,cfebr,cgdbr,cgebr,clfdbr,clfebr,clgdbr,\
-clgebr,cxbr,cxtr,tcxb,tdcxt")) "nothing")
+clgebr,cxbr,cxtr,tcxb,tdcxt,kxbr,kxtr")) "nothing")
 
 (define_insn_reservation "z14_13" 13
   (and (eq_attr "cpu" "z14")
diff --git a/gcc/config/s390/8561.md b/gcc/config/s390/8561.md
index e5a345f4dba..91a92b6bc5c 100644
--- a/gcc/config/s390/8561.md
+++ b/gcc/config/s390/8561.md
@@ -70,7 +70,7 @@ sar,sdb,seb,sfpc,sg,sgf,sgh,sh,shy,sl,slb,slbg,slg,slgf,sly,sqdb,sqeb,st,\
 stc,stcy,std,stdy,ste,stey,stg,stgrl,sth,sthrl,sthy,stoc,stocg,strl,strv,\
 strvg,strvh,sty,sy,tabort,tm,tmy,vl,vlbb,vleb,vlef,vleg,vleh,vll,vllezb,\
 vllezf,vllezg,vllezh,vllezlf,vlrepb,vlrepf,vlrepg,vlreph,vlrl,vlrlr,vst,\
-vstef,vsteg,vstl,vstrl,vstrlr,x,xg,xi,xiy,xy")
+vstef,vsteg,vstl,vstrl,vstrlr,x,xg,xi,xiy,xy,keb,kdb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "arch13_unit_vfu" ""
@@ -112,7 +112,9 @@ vupllf,vupllh,vx,vzero,wfadb,wfasb,wfaxb,wfcdb,wfcedb,wfcesb,wfcexb,wfcexbs,\
 wfchdb,wfchedb,wfchesb,wfchexb,wfchexbs,wfchsb,wfchxb,wfchxbs,wfcsb,wfidb,\
 wfisb,wfixb,wflcdb,wflcsb,wflcxb,wflld,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,\
 wflpxb,wfmadb,wfmasb,wfmaxb,wfmaxxb,wfmdb,wfminxb,wfmsb,wfmsdb,wfmssb,wfmsxb,\
-wfmxb,wfnmaxb,wfnmsxb,wfsdb,wfssb,wfsxb,wldeb,wledb")
+wfmxb,wfnmaxb,wfnmsxb,wfsdb,wfssb,wfsxb,wldeb,wledb,keb,kebr,kdb,kdbr,kxbr,\
+kdtr,kxtr,wfkdb,wfksb,vfkesb,vfkedb,wfkexb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,\
+vfkhedb,wfkhexb")
  (const_int 1)] (const_int 0)))
 
 (define_attr "arch13_cracked" ""
@@ -134,7 +136,7 @@ stam,stm,stmg,stmy,tbegin,tbeginc")
 cxtr,dlgr,dlr,dr,dsgfr,dsgr,dxbr,dxtr,fixbr,fixbra,fixtr,flogr,lcxbr,lnxbr,\
 lpxbr,ltxbr,ltxtr,lxdb,lxdbr,lxdtr,lxeb,lxebr,m,madb,maeb,maebr,mfy,mg,mgrk,\
 ml,mlg,mlgr,mlr,mr,msdb,mseb,msebr,mvc,mxbr,mxtr,nc,oc,ppa,sfpc,slb,slbg,\
-slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc")
+slbgr,slbr,sqxbr,sxbr,sxtr,tabort,tcxb,tdcxt,tend,xc,kxbr,kxtr")
  (const_int 1)] (const_int 0)))
 
 (define_attr "arch13_endgroup" ""
@@ -194,7 +196,8 @@ vsel,vsf,vsg,vsh,vsl,vslb,vsldb,vsq,vsra,vsrab,vsrl,vsrlb,vuphb,vuphf,\
 vuphh,vuplb,vuplf,vuplhb,vuplhf,vuplhh,vuplhw,vupllb,vupllf,vupllh,vx,vzero,\
 wfcedb,wfcesb,wfcexb,wfchdb,wfchedb,wfchesb,wfchexb,wfchsb,wfchxb,wflcdb,\
 wflcsb,wflcxb,wflndb,wflnsb,wflnxb,wflpdb,wflpsb,wflpxb,wfmaxxb,wfminxb,xi,\
-xiy")) "nothing")
+xiy,vfkesb,vfkedb,wfkexb,vfkhsb,vfkhdb,wfkhxb,vfkhesb,vfkhedb,wfkhexb"))
+"nothing")
 
 (define_insn_reservation "arch13_2" 2
   (and (eq_attr "cpu" "arch13")
@@ -206,7 +209,8 @@ vchlhs,vfcedbs,vfcesbs,vfchdbs,vfchedbs,vfchesbs,vfchsbs,vfeeb,vfeef,vfeeh,\
 vfeneb,vfenef,vfeneh,vfenezb,vfenezf,vfenezh,vftcidb,vftcisb,vistrb,vistrf,\
 vistrh,vlgvb,vlgvf,vlgvg,vlgvh,vllezb,vllezf,vllezg,vllezh,vllezlf,vlrepb,\
 vlrepf,vlrepg,vlreph,vlrl,vlvgp,vpklsfs,vpklsgs,vpklshs,vpksfs,vpksgs,vpkshs,\
-wfcdb,wfcexbs,wfchexbs,wfchxbs,wfcsb")) "nothing")
+wfcdb,wfcexbs,wfchexbs,wfchxbs,wfcsb,keb,kebr,kdb,kdbr,wfkdb,wfksb"))
+"nothing")
 
 (define_insn_reservation "arch13_3" 3
   (and (eq_attr "cpu" "arch13")
@@ -240,7 +244,7 @@ wfmasb,wfmdb,wfmsb,wfmsdb,wfmssb,wfsdb,wfssb,wldeb,wledb")) "nothing")
 (define_insn_reservation "arch13_7" 7
   (and (eq_attr "cpu" "arch13")
 (eq_attr "mnemonic" "adtr,cdtr,fidtr,ldetr,ltdtr,msgrkc,sdtr,tdcdt,\
-tdcet,vgef,vgeg")) "nothing")
+tdcet,vgef,vgeg,kdtr")) "nothing")
 
 (define_insn_reservation "arch13_8" 8
   (and (eq_attr "cpu" "arch13")
@@ -263,7 +267,8 @@ clgebr,mg,mgrk,mlg,mlgr")) "nothing")
 
 (define_insn_reservation "arch13_12" 12
   (and (eq_attr "cpu" "arch13")
-(eq_attr "mnemonic" "cxbr,cxftr,cxlftr,cxtr,tcxb,tdcxt")) "nothing")
+(eq_attr "mnemonic" "cxbr,cxftr,cxlftr,cxtr,tcxb,tdcxt,kxbr,kxtr"))
+"nothing")
 
 (define_insn_reservation "arch13_13" 13
   (and (eq_attr "cpu" "arch13")
diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def
index cfc69651b0d..013cac0206a 100644
--- a/gcc/config/s390/s390-builtins.def
+++ b/gcc/config/s390/s390-builtins.def
@@ -1495,8 +1495,8 @@ B_DEF      (vec_cmpgev4si,              vec_cmpgev4si,      0,
 B_DEF      (vec_cmpgeuv4si,             vec_cmpgeuv4si,     0,                  B_INT | B_VX,       0,                  BT_FN_V4SI_UV4SI_UV4SI)
 B_DEF      (vec_cmpgev2di,              vec_cmpgev2di,      0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
 B_DEF      (vec_cmpgeuv2di,             vec_cmpgeuv2di,     0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF      (s390_vfchesb,               vec_cmpgev4sf,      0,                  B_VXE,              0,                  BT_FN_V4SI_V4SF_V4SF)
-B_DEF      (s390_vfchedb,               vec_cmpgev2df,      0,                  B_VX,               0,                  BT_FN_V2DI_V2DF_V2DF)
+B_DEF      (s390_vfchesb,               vec_cmpgev4sf_quiet_nocc,0,             B_VXE,              0,                  BT_FN_V4SI_V4SF_V4SF)
+B_DEF      (s390_vfchedb,               vec_cmpgev2df_quiet_nocc,0,             B_VX,               0,                  BT_FN_V2DI_V2DF_V2DF)
 
 OB_DEF     (s390_vec_cmpgt,             s390_vec_cmpgt_s8,  s390_vec_cmpgt_dbl, B_VX,               BT_FN_OV4SI_OV4SI_OV4SI)
 OB_DEF_VAR (s390_vec_cmpgt_s8,          s390_vchb,          0,                  0,                  BT_OV_BV16QI_V16QI_V16QI)
@@ -1518,8 +1518,8 @@ B_DEF      (s390_vchf,                  vec_cmpgtv4si,      0,
 B_DEF      (s390_vchlf,                 vec_cmpgtuv4si,     0,                  B_VX,               0,                  BT_FN_V4SI_UV4SI_UV4SI)
 B_DEF      (s390_vchg,                  vec_cmpgtv2di,      0,                  B_VX,               0,                  BT_FN_V2DI_V2DI_V2DI)
 B_DEF      (s390_vchlg,                 vec_cmpgtuv2di,     0,                  B_VX,               0,                  BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF      (s390_vfchsb,                vec_cmpgtv4sf,      0,                  B_VXE,              0,                  BT_FN_V4SI_V4SF_V4SF)
-B_DEF      (s390_vfchdb,                vec_cmpgtv2df,      0,                  B_VX,               0,                  BT_FN_V2DI_V2DF_V2DF)
+B_DEF      (s390_vfchsb,                vec_cmpgtv4sf_quiet_nocc,0,             B_VXE,              0,                  BT_FN_V4SI_V4SF_V4SF)
+B_DEF      (s390_vfchdb,                vec_cmpgtv2df_quiet_nocc,0,             B_VX,               0,                  BT_FN_V2DI_V2DF_V2DF)
 
 OB_DEF     (s390_vec_cmple,             s390_vec_cmple_s8,  s390_vec_cmple_dbl, B_VX,               BT_FN_OV4SI_OV4SI_OV4SI)
 OB_DEF_VAR (s390_vec_cmple_s8,          vec_cmplev16qi,     0,                  0,                  BT_OV_BV16QI_V16QI_V16QI)
@@ -1541,8 +1541,8 @@ B_DEF      (vec_cmplev4si,              vec_cmplev4si,      0,
 B_DEF      (vec_cmpleuv4si,             vec_cmpleuv4si,     0,                  B_INT | B_VX,       0,                  BT_FN_V4SI_UV4SI_UV4SI)
 B_DEF      (vec_cmplev2di,              vec_cmplev2di,      0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
 B_DEF      (vec_cmpleuv2di,             vec_cmpleuv2di,     0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF      (vec_cmplev4sf,              vec_cmplev4sf,      0,                  B_INT | B_VXE,      0,                  BT_FN_V4SI_V4SF_V4SF)
-B_DEF      (vec_cmplev2df,              vec_cmplev2df,      0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_V2DF_V2DF)
+B_DEF      (vec_cmplev4sf,              vec_cmplev4sf_quiet_nocc,0,             B_INT | B_VXE,      0,                  BT_FN_V4SI_V4SF_V4SF)
+B_DEF      (vec_cmplev2df,              vec_cmplev2df_quiet_nocc,0,             B_INT | B_VX,       0,                  BT_FN_V2DI_V2DF_V2DF)
 
 OB_DEF     (s390_vec_cmplt,             s390_vec_cmplt_s8,  s390_vec_cmplt_dbl, B_VX,               BT_FN_OV4SI_OV4SI_OV4SI)
 OB_DEF_VAR (s390_vec_cmplt_s8,          vec_cmpltv16qi,     0,                  0,                  BT_OV_BV16QI_V16QI_V16QI)
@@ -1564,8 +1564,8 @@ B_DEF      (vec_cmpltv4si,              vec_cmpltv4si,      0,
 B_DEF      (vec_cmpltuv4si,             vec_cmpltuv4si,     0,                  B_INT | B_VX,       0,                  BT_FN_V4SI_UV4SI_UV4SI)
 B_DEF      (vec_cmpltv2di,              vec_cmpltv2di,      0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
 B_DEF      (vec_cmpltuv2di,             vec_cmpltuv2di,     0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_UV2DI_UV2DI)
-B_DEF      (vec_cmpltv4sf,              vec_cmpltv4sf,      0,                  B_INT | B_VXE,      0,                  BT_FN_V4SI_V4SF_V4SF)
-B_DEF      (vec_cmpltv2df,              vec_cmpltv2df,      0,                  B_INT | B_VX,       0,                  BT_FN_V2DI_V2DF_V2DF)
+B_DEF      (vec_cmpltv4sf,              vec_cmpltv4sf_quiet_nocc,0,             B_INT | B_VXE,      0,                  BT_FN_V4SI_V4SF_V4SF)
+B_DEF      (vec_cmpltv2df,              vec_cmpltv2df_quiet_nocc,0,             B_INT | B_VX,       0,                  BT_FN_V2DI_V2DF_V2DF)
 
 OB_DEF     (s390_vec_cntlz,             s390_vec_cntlz_s8,  s390_vec_cntlz_u64, B_VX,               BT_FN_OV4SI_OV4SI)
 OB_DEF_VAR (s390_vec_cntlz_s8,          s390_vclzb,         0,                  0,                  BT_OV_UV16QI_V16QI)
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index 7b7c1141449..2d9cd9b5945 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -52,6 +52,8 @@ CCS:  EQ          LT           GT          UNORDERED  (LTGFR, LTGR, LTR, ICM/Y,
                                                        ADB/R, AEB/R, SDB/R, SEB/R,
                                                        SRAG, SRA, SRDA)
 CCSR: EQ          GT           LT          UNORDERED  (CGF/R, CH/Y)
+CCSFPS: EQ        GT           LT          UNORDERED  (KEB/R, KDB/R, KXBR, KDTR,
+						       KXTR, WFK)
 
 Condition codes resulting from add with overflow
 
@@ -140,6 +142,11 @@ around. The following both modes can be considered as CCS and CCU modes with
 exchanged operands.
 
 
+CCSFPS
+
+This mode is used for signaling rtxes: LT, LE, GT, GE and LTGT.
+
+
 CCL1, CCL2
 
 These modes represent the result of overflow checks.
@@ -226,6 +233,7 @@ CC_MODE (CCU);
 CC_MODE (CCUR);
 CC_MODE (CCS);
 CC_MODE (CCSR);
+CC_MODE (CCSFPS);
 CC_MODE (CCT);
 CC_MODE (CCT1);
 CC_MODE (CCT2);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index afd81cdc24b..26c81fa0c70 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1376,6 +1376,7 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode)
     case E_CCZ1mode:
     case E_CCSmode:
     case E_CCSRmode:
+    case E_CCSFPSmode:
     case E_CCUmode:
     case E_CCURmode:
     case E_CCOmode:
@@ -1559,6 +1560,12 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
 	    else
 	      return CCAPmode;
 	  }
+
+	/* Fall through.  */
+      case LTGT:
+	if (HONOR_NANS (op0) || HONOR_NANS (op1))
+	  return CCSFPSmode;
+
 	/* Fall through.  */
       case UNORDERED:
       case ORDERED:
@@ -1567,7 +1574,6 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
       case UNLT:
       case UNGE:
       case UNGT:
-      case LTGT:
 	if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
 	    && GET_CODE (op1) != CONST_INT)
 	  return CCSRmode;
@@ -2082,6 +2088,7 @@ s390_branch_condition_mask (rtx code)
       break;
 
     case E_CCSmode:
+    case E_CCSFPSmode:
       switch (GET_CODE (code))
 	{
 	case EQ:	return CC0;
@@ -6504,18 +6511,23 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
 	{
 	  /* NE a != b -> !(a == b) */
 	case NE:   cond = EQ; neg_p = true;                break;
-	  /* UNGT a u> b -> !(b >= a) */
-	case UNGT: cond = GE; neg_p = true; swap_p = true; break;
-	  /* UNGE a u>= b -> !(b > a) */
-	case UNGE: cond = GT; neg_p = true; swap_p = true; break;
-	  /* LE: a <= b -> b >= a */
+	case UNGT:
+	  emit_insn (gen_vec_cmpungt (target, cmp_op1, cmp_op2));
+	  return;
+	case UNGE:
+	  emit_insn (gen_vec_cmpunge (target, cmp_op1, cmp_op2));
+	  return;
 	case LE:   cond = GE;               swap_p = true; break;
-	  /* UNLE: a u<= b -> !(a > b) */
-	case UNLE: cond = GT; neg_p = true;                break;
+	  /* UNLE: (a u<= b) -> (b u>= a).  */
+	case UNLE:
+	  emit_insn (gen_vec_cmpunge (target, cmp_op2, cmp_op1));
+	  return;
 	  /* LT: a < b -> b > a */
 	case LT:   cond = GT;               swap_p = true; break;
-	  /* UNLT: a u< b -> !(a >= b) */
-	case UNLT: cond = GE; neg_p = true;                break;
+	  /* UNLT: (a u< b) -> (b u> a).  */
+	case UNLT:
+	  emit_insn (gen_vec_cmpungt (target, cmp_op2, cmp_op1));
+	  return;
 	case UNEQ:
 	  emit_insn (gen_vec_cmpuneq (target, cmp_op1, cmp_op2));
 	  return;
@@ -6678,7 +6690,7 @@ s390_reverse_condition (machine_mode mode, enum rtx_code code)
 {
   /* Reversal of FP compares takes care -- an ordered compare
      becomes an unordered compare and vice versa.  */
-  if (mode == CCVFALLmode || mode == CCVFANYmode)
+  if (mode == CCVFALLmode || mode == CCVFANYmode || mode == CCSFPSmode)
     return reverse_condition_maybe_unordered (code);
   else if (mode == CCVIALLmode || mode == CCVIANYmode)
     return reverse_condition (code);
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index e4516f6c378..bf3e051dbae 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1424,6 +1424,20 @@
    (set_attr "cpu_facility" "*,*,vx,vxe")
    (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
 
+(define_insn "*cmp<mode>_ccsfps"
+  [(set (reg CC_REGNUM)
+	(compare (match_operand:FP 0 "register_operand" "f,f,v,v")
+		 (match_operand:FP 1 "general_operand"  "f,R,v,v")))]
+  "s390_match_ccmode (insn, CCSFPSmode) && TARGET_HARD_FLOAT"
+  "@
+   k<xde><bt>r\t%0,%1
+   k<xde>b\t%0,%1
+   wfkdb\t%0,%1
+   wfksb\t%0,%1"
+  [(set_attr "op_type" "RRE,RXE,VRR,VRR")
+   (set_attr "cpu_facility" "*,*,vx,vxe")
+   (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
+
 ; Compare and Branch instructions
 
 ; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 43a913bbf27..1af7b503a82 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -168,10 +168,6 @@
 (define_mode_attr vec_halfnumelts
   [(V4SF "V2SF") (V4SI "V2SI")])
 
-; The comparisons not setting CC iterate over the rtx code.
-(define_code_iterator VFCMP_HW_OP [eq gt ge])
-(define_code_attr asm_fcmp_op [(eq "e") (gt "h") (ge "he")])
-
 
 
 ; Comparison operators on int and fp compares which are directly
@@ -1372,7 +1368,8 @@
   "#"
   "&& 1"
   [(set (match_dup 3)
-	(gt:V2DI (match_dup 1) (match_dup 2)))
+	(not:V2DI
+	 (unge:V2DI (match_dup 2) (match_dup 1))))
    (set (match_dup 0)
 	(if_then_else:V2DF
 	 (eq (match_dup 3) (match_dup 4))
@@ -1407,7 +1404,8 @@
   "#"
   "&& 1"
   [(set (match_dup 3)
-	(gt:V2DI (match_dup 1) (match_dup 2)))
+	(not:V2DI
+	 (unge:V2DI (match_dup 2) (match_dup 1))))
    (set (match_dup 0)
 	(if_then_else:V2DF
 	 (eq (match_dup 3) (match_dup 4))
@@ -1461,27 +1459,134 @@
 ;; Floating point compares
 ;;
 
-; EQ, GT, GE
-; vfcesb, vfcedb, wfcexb, vfchsb, vfchdb, wfchxb, vfchesb, vfchedb, wfchexb
-(define_insn "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc"
-  [(set (match_operand:<tointvec>                  0 "register_operand" "=v")
-	(VFCMP_HW_OP:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
-			     (match_operand:VFT 2 "register_operand"  "v")))]
-   "TARGET_VX"
-   "<vw>fc<VFCMP_HW_OP:asm_fcmp_op><sdx>b\t%v0,%v1,%v2"
+; vfcesb, vfcedb, wfcexb: non-signaling "==" comparison (a == b)
+(define_insn "*vec_cmpeq<mode>_quiet_nocc"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(eq:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		       (match_operand:VFT 2 "register_operand" "v")))]
+  "TARGET_VX"
+  "<vw>fce<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+; vfchsb, vfchdb, wfchxb: non-signaling > comparison (!(b u>= a))
+(define_insn "vec_cmpgt<mode>_quiet_nocc"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unge:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+			  (match_operand:VFT 1 "register_operand" "v"))))]
+  "TARGET_VX"
+  "<vw>fch<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "vec_cmplt<mode>_quiet_nocc"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+			  (match_operand:VFT 2 "register_operand" "v"))))]
+  "TARGET_VX")
+
+; vfchesb, vfchedb, wfchexb: non-signaling >= comparison (!(a u< b))
+(define_insn "vec_cmpge<mode>_quiet_nocc"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+			  (match_operand:VFT 2 "register_operand" "v"))))]
+  "TARGET_VX"
+  "<vw>fche<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "vec_cmple<mode>_quiet_nocc"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+			  (match_operand:VFT 1 "register_operand" "v"))))]
+  "TARGET_VX")
+
+; vfkesb, vfkedb, wfkexb: signaling == comparison ((a >= b) & (b >= a))
+(define_insn "*vec_cmpeq<mode>_signaling_nocc"
+  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
+	(and:<tointvec>
+	 (ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+			(match_operand:VFT 2 "register_operand" "v"))
+	 (ge:<tointvec> (match_dup         2)
+			(match_dup         1))))]
+  "TARGET_VXE"
+  "<vw>fke<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+; vfkhsb, vfkhdb, wfkhxb: signaling > comparison (a > b)
+(define_insn "*vec_cmpgt<mode>_signaling_nocc"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		       (match_operand:VFT 2 "register_operand" "v")))]
+  "TARGET_VXE"
+  "<vw>fkh<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+(define_insn "*vec_cmpgt<mode>_signaling_finite_nocc"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(gt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		       (match_operand:VFT 2 "register_operand" "v")))]
+  "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
+  "<vw>fch<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+; vfkhesb, vfkhedb, wfkhexb: signaling >= comparison (a >= b)
+(define_insn "*vec_cmpge<mode>_signaling_nocc"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		       (match_operand:VFT 2 "register_operand" "v")))]
+  "TARGET_VXE"
+  "<vw>fkhe<sdx>b\t%v0,%v1,%v2"
+  [(set_attr "op_type" "VRR")])
+
+(define_insn "*vec_cmpge<mode>_signaling_finite_nocc"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(ge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		       (match_operand:VFT 2 "register_operand" "v")))]
+  "TARGET_VX && !TARGET_VXE && flag_finite_math_only"
+  "<vw>fche<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
 ; Expanders for not directly supported comparisons
+; Signaling comparisons must be expressed via signaling rtxes only,
+; and quiet comparisons must be expressed via quiet rtxes only.
+
+; UNGT a u> b -> !!(b u< a)
+(define_expand "vec_cmpungt<mode>"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unlt:<tointvec> (match_operand:VFT 2 "register_operand" "v")
+			  (match_operand:VFT 1 "register_operand" "v"))))
+   (set (match_dup                           0)
+	(not:<tointvec> (match_dup           0)))]
+  "TARGET_VX")
 
-; UNEQ a u== b -> !(a > b | b > a)
+; UNGE a u>= b -> !!(a u>= b)
+(define_expand "vec_cmpunge<mode>"
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unge:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+			  (match_operand:VFT 2 "register_operand" "v"))))
+   (set (match_dup                           0)
+	(not:<tointvec> (match_dup           0)))]
+  "TARGET_VX")
+
+; UNEQ a u== b -> !(!(a u>= b) | !(b u>= a))
 (define_expand "vec_cmpuneq<mode>"
-  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
-	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
-		    (match_operand:VFT 2 "register_operand"  "v")))
-   (set (match_dup 3)
-	(gt:<tointvec> (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
-   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+		          (match_operand:VFT 2 "register_operand"  "v"))))
+   (set (match_dup                           3)
+	(not:<tointvec>
+	 (unge:<tointvec> (match_dup         2)
+	                  (match_dup         1))))
+   (set (match_dup                           0)
+	(ior:<tointvec> (match_dup           0)
+			(match_dup           3)))
+   (set (match_dup                           0)
+	(not:<tointvec> (match_dup           0)))]
   "TARGET_VX"
 {
   operands[3] = gen_reg_rtx (<tointvec>mode);
@@ -1494,18 +1599,24 @@
 		    (match_operand:VFT 2 "register_operand"  "v")))
    (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
    (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
-  "TARGET_VX"
+  "TARGET_VXE"
 {
   operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
-; ORDERED (a, b): a >= b | b > a
+; ORDERED (a, b): !(a u< b) | !(a u>= b)
 (define_expand "vec_cmpordered<mode>"
-  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
-	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
-		 (match_operand:VFT 2 "register_operand"  "v")))
-   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
+  [(set (match_operand:<tointvec>            0 "register_operand" "=v")
+	(not:<tointvec>
+	 (unlt:<tointvec> (match_operand:VFT 1 "register_operand" "v")
+		          (match_operand:VFT 2 "register_operand" "v"))))
+   (set (match_dup                           3)
+	(not:<tointvec>
+	 (unge:<tointvec> (match_dup         1)
+			  (match_dup         2))))
+   (set (match_dup                           0)
+	(ior:<tointvec> (match_dup           0)
+			(match_dup           3)))]
   "TARGET_VX"
 {
   operands[3] = gen_reg_rtx (<tointvec>mode);
@@ -1525,7 +1636,7 @@
 })
 
 (define_code_iterator VEC_CODE_WITH_COMPLEX_EXPAND
-  [uneq ltgt ordered unordered])
+  [ungt unge uneq ltgt ordered unordered])
 
 (define_expand "vec_cmp<code>"
   [(match_operand 0 "register_operand" "")
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
index ea51d0c86af..073d574aa5e 100644
--- a/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
+++ b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c
@@ -34,7 +34,7 @@ gt (double a, double b)
   return a > b;
 }
 
-/* { dg-final { scan-assembler "gt:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinh\t%r2,0" } } */
+/* { dg-final { scan-assembler "gt:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinh\t%r2,0" } } */
 
 int
 ge (double a, double b)
@@ -45,7 +45,7 @@ ge (double a, double b)
   return a >= b;
 }
 
-/* { dg-final { scan-assembler "ge:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinhe\t%r2,0" } } */
+/* { dg-final { scan-assembler "ge:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinhe\t%r2,0" } } */
 
 int
 lt (double a, double b)
@@ -56,7 +56,7 @@ lt (double a, double b)
   return a < b;
 }
 
-/* { dg-final { scan-assembler "lt:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinl\t%r2,0" } } */
+/* { dg-final { scan-assembler "lt:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinl\t%r2,0" } } */
 
 int
 le (double a, double b)
@@ -67,4 +67,4 @@ le (double a, double b)
   return a <= b;
 }
 
-/* { dg-final { scan-assembler "le:\n\[^:\]*\twfcdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinle\t%r2,0" } } */
+/* { dg-final { scan-assembler "le:\n\[^:\]*\twfkdb\t%v\[0-9\]*,%v\[0-9\]*\n\t\[^:\]+\tlochinle\t%r2,0" } } */
-- 
2.21.0

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/8] Introduce vcond_supported_p hook
  2019-08-20  9:20 ` [PATCH 2/8] Introduce " Ilya Leoshkevich
@ 2019-08-20 11:37   ` Richard Sandiford
  2019-08-20 11:48     ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Sandiford @ 2019-08-20 11:37 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

Ilya Leoshkevich <iii@linux.ibm.com> writes:
> z13 supports only non-signaling vector comparisons.  This means we
> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
> However, we cannot express this restriction today: the code only checks
> whether vcond$a$b optab, which does not contain information about the
> operation.
>
> Introduce a hook that tells whether target supports certain vector
> comparison operations with certain modes.
>
> gcc/ChangeLog:
>
> 2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>
>
> 	* doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document.
> 	* doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document.
> 	* optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p
> 	in addition to get_vcond_icode.
> 	* target.def (vcond_supported_p): New hook.
> 	* targhooks.c (default_vcond_supported_p): Likewise.
> 	* targhooks.h (default_vcond_supported_p): Likewise.

IMO it'd be cleaner to have a new optabs-query.[hc] helper that uses
the predicate for operand 3 to test whether a particular comparison
is supported.  I guess this would require a cached rtx to avoid
generating too much garbage rtl though (via GTY((cache))).

If the general feeling is that we should have a hook instead, I assume
the same restrictions would apply to the vec_cmp@var{m}@var{n} optab too,
on targets that use that.  It might be worth generalising the hook so
that it applies to both patterns.

> diff --git a/gcc/target.def b/gcc/target.def
> index b2332d8215c..4cd2a964c0e 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -3379,6 +3379,17 @@ the vector element type.",
>   HOST_WIDE_INT, (const_tree type),
>   default_vector_alignment)
>  
> +DEFHOOK
> +(vcond_supported_p,
> + "Define this to restrict which vector comparison operations are supported by\n\
> +vcond$a$b expander.  An operation is represented by its operand machine mode\n\

Maybe s/vcond$a$b expander/a @code{vcond@var{m}@var{n}} instruction pattern/
for consistency with the .md documentation.

> +@code{OP_MODE}, its result machine mode @code{RESULT_MODE} and @code{enum\n\
> +tree_code CODE}.  The main use of this hook is to support machines which\n\
> +provide only certain vector comparison instructions, e.g. only non-signaling\n\
> +ones.  The default is that all operations are supported.",

...if the associated pattern exists.

> + bool, (machine_mode result_mode, machine_mode op_mode, int code),
> + default_vcond_supported_p)
> +
>  DEFHOOK
>  (array_mode,
>   "Return the mode that GCC should use for an array that has\n\
> diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> index 1d12ec54704..2b9a5d12bab 100644
> --- a/gcc/targhooks.c
> +++ b/gcc/targhooks.c
> @@ -448,6 +448,18 @@ default_scalar_mode_supported_p (scalar_mode mode)
>      }
>  }
>  
> +/* Return true if vcond$a$b expander supports vector comparisons using the CODE
> +   of type enum tree_code, in which the operands have machine mode OP_MODE and
> +   the result has machine mode RESULT_MODE.  */
> +
> +bool
> +default_vcond_supported_p (machine_mode result_mode ATTRIBUTE_UNUSED,
> +                           machine_mode op_mode ATTRIBUTE_UNUSED,
> +                           int code ATTRIBUTE_UNUSED)

No need to repeat the documentation here -- just say which hook it's
the default for.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/8] Introduce vcond_supported_p hook
  2019-08-20 11:37   ` Richard Sandiford
@ 2019-08-20 11:48     ` Ilya Leoshkevich
  2019-08-20 12:54       ` Richard Sandiford
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20 11:48 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: GCC Patches

> Am 20.08.2019 um 12:13 schrieb Richard Sandiford <richard.sandiford@arm.com>:
> 
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>> z13 supports only non-signaling vector comparisons.  This means we
>> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
>> However, we cannot express this restriction today: the code only checks
>> whether vcond$a$b optab, which does not contain information about the
>> operation.
>> 
>> Introduce a hook that tells whether target supports certain vector
>> comparison operations with certain modes.
>> 
>> gcc/ChangeLog:
>> 
>> 2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>
>> 
>> 	* doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document.
>> 	* doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document.
>> 	* optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p
>> 	in addition to get_vcond_icode.
>> 	* target.def (vcond_supported_p): New hook.
>> 	* targhooks.c (default_vcond_supported_p): Likewise.
>> 	* targhooks.h (default_vcond_supported_p): Likewise.
> 
> IMO it'd be cleaner to have a new optabs-query.[hc] helper that uses
> the predicate for operand 3 to test whether a particular comparison
> is supported.  I guess this would require a cached rtx to avoid
> generating too much garbage rtl though (via GTY((cache))).

How can I implement such a predicate?  Would calling maybe_gen_insn with
a fake rtx be reasonable?  In this case, what would be the best way to
generate fake input operands?  The existing code that calls
maybe_gen_insn gets the corresponding rtxes from upper layers.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/8] Introduce vcond_supported_p hook
  2019-08-20 11:48     ` Ilya Leoshkevich
@ 2019-08-20 12:54       ` Richard Sandiford
  2019-08-21 12:00         ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Sandiford @ 2019-08-20 12:54 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: GCC Patches

Ilya Leoshkevich <iii@linux.ibm.com> writes:
>> Am 20.08.2019 um 12:13 schrieb Richard Sandiford <richard.sandiford@arm.com>:
>> 
>> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>>> z13 supports only non-signaling vector comparisons.  This means we
>>> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
>>> However, we cannot express this restriction today: the code only checks
>>> whether vcond$a$b optab, which does not contain information about the
>>> operation.
>>> 
>>> Introduce a hook that tells whether target supports certain vector
>>> comparison operations with certain modes.
>>> 
>>> gcc/ChangeLog:
>>> 
>>> 2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>
>>> 
>>> 	* doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document.
>>> 	* doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document.
>>> 	* optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p
>>> 	in addition to get_vcond_icode.
>>> 	* target.def (vcond_supported_p): New hook.
>>> 	* targhooks.c (default_vcond_supported_p): Likewise.
>>> 	* targhooks.h (default_vcond_supported_p): Likewise.
>> 
>> IMO it'd be cleaner to have a new optabs-query.[hc] helper that uses
>> the predicate for operand 3 to test whether a particular comparison
>> is supported.  I guess this would require a cached rtx to avoid
>> generating too much garbage rtl though (via GTY((cache))).
>
> How can I implement such a predicate?  Would calling maybe_gen_insn with
> a fake rtx be reasonable?  In this case, what would be the best way to
> generate fake input operands?  The existing code that calls
> maybe_gen_insn gets the corresponding rtxes from upper layers.

I was thinking of something like optabs.c:can_compare_p, but with
some caching to reduce the overhead, and comparing registers rather
than constants.  E.g.:

static rtx cached_binop GTY ((cached));

rtx
get_cached_binop (machine_mode mode, rtx_code code, machine_mode op_mode)
{
  ...create or modify cached_binop, with register operands...;
  return cached_binop;
}

/* ...maybe a different name if the overload seems like a bad idea... */
bool
vcond_supported_p (machine_mode value_mode, rtx_code cmp,
		   machine_mode cmp_op_mode)
{
  bool unsigned = (cmp == LTU || cmp == LEU || cmp == GTU || cmp == GEU);
  insn_code icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned);
  if (icode == CODE_FOR_nothing)
    return false;

  if (insn_operand_predicate_fn pred = insn_data[icode].operand[3].predicate)
    {
      machine_mode cmp_mode = insn_data[icode].operand[3].mode;
      rtx cmp = get_cached_binop (cmp_mode, cmp, cmp_op_mode);
      if (!pred (cmp, cmp_mode))
	return false;
    }

  return true;
}

(not attached to the names).

Then the target pattern would use a normal match_operator for operand 3,
with the predicate on the match_operand only allowing through the
comparisons it actually supports.

The get_cached_binop stuff makes it a bit cumbersome, but that part
would be reusable by other queries in future (and by can_compare_p
probably).

Thanks,
Richard

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
@ 2019-08-20 15:43   ` Segher Boessenkool
  2019-08-20 15:56     ` Ilya Leoshkevich
  2019-08-20 16:13   ` Segher Boessenkool
  1 sibling, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-08-20 15:43 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On Tue, Aug 20, 2019 at 11:18:38AM +0200, Ilya Leoshkevich wrote:
> Currently it's not clear whether or not min, max and ltgt should raise
> floating point exceptions when dealing with qNaNs.
> 
> Right now a lot of code assumes that LTGT is signaling: in particular,
> it's generated for ((x < y) || (x > y)), which is signaling. The
> behavior of MIN/MAX is (intentionally?) left unspecified, according to
> commit 64dd117734d0 ("Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN
> intrinsics").

The < and > operators separately already can cause exceptions, unless
you use -fno-trapping-math, in which case you cannot have LTGT at all.


Segher

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 15:43   ` Segher Boessenkool
@ 2019-08-20 15:56     ` Ilya Leoshkevich
  2019-08-20 16:02       ` Segher Boessenkool
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20 15:56 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-patches

> Am 20.08.2019 um 17:04 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> 
> On Tue, Aug 20, 2019 at 11:18:38AM +0200, Ilya Leoshkevich wrote:
>> Currently it's not clear whether or not min, max and ltgt should raise
>> floating point exceptions when dealing with qNaNs.
>> 
>> Right now a lot of code assumes that LTGT is signaling: in particular,
>> it's generated for ((x < y) || (x > y)), which is signaling. The
>> behavior of MIN/MAX is (intentionally?) left unspecified, according to
>> commit 64dd117734d0 ("Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN
>> intrinsics").
> 
> The < and > operators separately already can cause exceptions, unless
> you use -fno-trapping-math, in which case you cannot have LTGT at all.

Hmm, I've just tried compiling:

    int foo(float a, float b) { return ((a < b) || (a > b)); }

with -ftrapping-math and -fno-trapping-math with gcc 8.0.1, and got LTGT
on tree and rtl levels in both cases:

    232t.optimized: _1 = a_2(D) <> b_3(D);
    312r.final:        (if_then_else:SI (ltgt (reg:CCS 33 %cc)

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 15:56     ` Ilya Leoshkevich
@ 2019-08-20 16:02       ` Segher Boessenkool
  2019-08-20 18:00         ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-08-20 16:02 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On Tue, Aug 20, 2019 at 05:19:46PM +0200, Ilya Leoshkevich wrote:
> > Am 20.08.2019 um 17:04 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> > The < and > operators separately already can cause exceptions, unless
> > you use -fno-trapping-math, in which case you cannot have LTGT at all.
> 
> Hmm, I've just tried compiling:
> 
>     int foo(float a, float b) { return ((a < b) || (a > b)); }
> 
> with -ftrapping-math and -fno-trapping-math with gcc 8.0.1, and got LTGT
> on tree and rtl levels in both cases:
> 
>     232t.optimized: _1 = a_2(D) <> b_3(D);
>     312r.final:        (if_then_else:SI (ltgt (reg:CCS 33 %cc)

Hrm, it seems to need -ffinite-math-only, even?  Or just -ffast-math
of course.  (That'll teach me to post without testing for another year
or two, sorry!)


Segher

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
  2019-08-20 15:43   ` Segher Boessenkool
@ 2019-08-20 16:13   ` Segher Boessenkool
  2019-08-20 18:49     ` Ilya Leoshkevich
  1 sibling, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-08-20 16:13 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On Tue, Aug 20, 2019 at 11:18:38AM +0200, Ilya Leoshkevich wrote:
> Currently it's not clear whether or not min, max and ltgt should raise
> floating point exceptions when dealing with qNaNs.
> 
> Right now a lot of code assumes that LTGT is signaling: in particular,
> it's generated for ((x < y) || (x > y)), which is signaling. The
> behavior of MIN/MAX is (intentionally?) left unspecified, according to
> commit 64dd117734d0 ("Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN
> intrinsics").

Btw, this is not the difference between LTGT and NE, which is exactly
the same difference as that between LT and UNLT: if NaNs are allowed,
the first is false for unordered, while the second is true.  If NaNs
are not allowed, only one of the two is generated.

(0    UNORD)
LT    UNLT
EQ    UNEQ
LE    UNLE
GT    UNGT
LTGT  NE
GE    UNGE
(ORD  1)

There is currently no way to say (in trees or gimple or rtl) whether
comparisons are signaling ("ordered", generate a trap on an unordered
result).  I am working on this, but :-)


Segher

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 16:02       ` Segher Boessenkool
@ 2019-08-20 18:00         ` Ilya Leoshkevich
  0 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20 18:00 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: gcc-patches

> Am 20.08.2019 um 17:32 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> 
> On Tue, Aug 20, 2019 at 05:19:46PM +0200, Ilya Leoshkevich wrote:
>>> Am 20.08.2019 um 17:04 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
>>> The < and > operators separately already can cause exceptions, unless
>>> you use -fno-trapping-math, in which case you cannot have LTGT at all.
>> 
>> Hmm, I've just tried compiling:
>> 
>>    int foo(float a, float b) { return ((a < b) || (a > b)); }
>> 
>> with -ftrapping-math and -fno-trapping-math with gcc 8.0.1, and got LTGT
>> on tree and rtl levels in both cases:
>> 
>>    232t.optimized: _1 = a_2(D) <> b_3(D);
>>    312r.final:        (if_then_else:SI (ltgt (reg:CCS 33 %cc)
> 
> Hrm, it seems to need -ffinite-math-only, even?  Or just -ffast-math
> of course.  (That'll teach me to post without testing for another year
> or two, sorry!)

Ah, that's correct, and I have even added s390 tests for this: with
-ffinite-math-only the generated code is more "straightforward".  I
should update the commit message, but this isn't affecting the manual
update itself, right?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 16:13   ` Segher Boessenkool
@ 2019-08-20 18:49     ` Ilya Leoshkevich
  2019-08-20 19:56       ` Segher Boessenkool
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-20 18:49 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches

> Am 20.08.2019 um 17:50 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> 
> On Tue, Aug 20, 2019 at 11:18:38AM +0200, Ilya Leoshkevich wrote:
>> Currently it's not clear whether or not min, max and ltgt should raise
>> floating point exceptions when dealing with qNaNs.
>> 
>> Right now a lot of code assumes that LTGT is signaling: in particular,
>> it's generated for ((x < y) || (x > y)), which is signaling. The
>> behavior of MIN/MAX is (intentionally?) left unspecified, according to
>> commit 64dd117734d0 ("Unconditionally use MAX_EXPR/MIN_EXPR for MAX/MIN
>> intrinsics").
> 
> Btw, this is not the difference between LTGT and NE, which is exactly
> the same difference as that between LT and UNLT: if NaNs are allowed,
> the first is false for unordered, while the second is true.  If NaNs
> are not allowed, only one of the two is generated.
> 
> (0    UNORD)
> LT    UNLT
> EQ    UNEQ
> LE    UNLE
> GT    UNGT
> LTGT  NE
> GE    UNGE
> (ORD  1)

This matches my understanding (modulo signaling). cThis also doesn't
contradict the proposed manual update, right?

> There is currently no way to say (in trees or gimple or rtl) whether
> comparisons are signaling ("ordered", generate a trap on an unordered
> result).  I am working on this, but :-)

Isn't there?  This whole series is based on the following assumption:
LT, LE, GT, GE are definitely signaling; LTGT is most likely signaling
as well; the rest are not signaling.  This is based on gccint 11.6.3:
Unary and Binary Expressions.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 18:49     ` Ilya Leoshkevich
@ 2019-08-20 19:56       ` Segher Boessenkool
  2019-08-21 12:32         ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-08-20 19:56 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: GCC Patches

On Tue, Aug 20, 2019 at 06:13:00PM +0200, Ilya Leoshkevich wrote:
> > Am 20.08.2019 um 17:50 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> > There is currently no way to say (in trees or gimple or rtl) whether
> > comparisons are signaling ("ordered", generate a trap on an unordered
> > result).  I am working on this, but :-)
> 
> Isn't there?  This whole series is based on the following assumption:
> LT, LE, GT, GE are definitely signaling; LTGT is most likely signaling
> as well; the rest are not signaling.  This is based on gccint 11.6.3:
> Unary and Binary Expressions.

There is currently no way to implement, say, iseqsig.  And whether an
operation is signaling should be determined by the language frontend,
not separately by each backend!

(There should be a signaling and a non-signaling version of every float
comparison that can be unordered).


Segher

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/8] Introduce vcond_supported_p hook
  2019-08-20 12:54       ` Richard Sandiford
@ 2019-08-21 12:00         ` Ilya Leoshkevich
  0 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-21 12:00 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: GCC Patches

> Am 20.08.2019 um 13:54 schrieb Richard Sandiford <richard.sandiford@arm.com>:
> 
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>>> Am 20.08.2019 um 12:13 schrieb Richard Sandiford <richard.sandiford@arm.com>:
>>> 
>>> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>>>> z13 supports only non-signaling vector comparisons.  This means we
>>>> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
>>>> However, we cannot express this restriction today: the code only checks
>>>> whether vcond$a$b optab, which does not contain information about the
>>>> operation.
>>>> 
>>>> Introduce a hook that tells whether target supports certain vector
>>>> comparison operations with certain modes.
>>>> 
>>>> gcc/ChangeLog:
>>>> 
>>>> 2019-08-09  Ilya Leoshkevich  <iii@linux.ibm.com>
>>>> 
>>>> 	* doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document.
>>>> 	* doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document.
>>>> 	* optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p
>>>> 	in addition to get_vcond_icode.
>>>> 	* target.def (vcond_supported_p): New hook.
>>>> 	* targhooks.c (default_vcond_supported_p): Likewise.
>>>> 	* targhooks.h (default_vcond_supported_p): Likewise.
>>> 
>>> IMO it'd be cleaner to have a new optabs-query.[hc] helper that uses
>>> the predicate for operand 3 to test whether a particular comparison
>>> is supported.  I guess this would require a cached rtx to avoid
>>> generating too much garbage rtl though (via GTY((cache))).
>> 
>> How can I implement such a predicate?  Would calling maybe_gen_insn with
>> a fake rtx be reasonable?  In this case, what would be the best way to
>> generate fake input operands?  The existing code that calls
>> maybe_gen_insn gets the corresponding rtxes from upper layers.
> 
> I was thinking of something like optabs.c:can_compare_p, but with
> some caching to reduce the overhead, and comparing registers rather
> than constants.  E.g.:
> 
> static rtx cached_binop GTY ((cached));
> 
> rtx
> get_cached_binop (machine_mode mode, rtx_code code, machine_mode op_mode)
> {
>  ...create or modify cached_binop, with register operands...;
>  return cached_binop;
> }

Thanks, I got it working!  Still need to run the regtest, but the result
looks promising.

I have a question about caching.  If I define just `static rtx
cached_binop`, like you suggest, I would expect to see constant cache
misses.  Shouldn't it be something like `hash_map<tuple<enum rtx_code,
machine_mode, machine_mode>, rtx>`?

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-20 19:56       ` Segher Boessenkool
@ 2019-08-21 12:32         ` Ilya Leoshkevich
  2019-08-21 12:59           ` Segher Boessenkool
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-08-21 12:32 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: GCC Patches



> Am 20.08.2019 um 19:13 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> 
> On Tue, Aug 20, 2019 at 06:13:00PM +0200, Ilya Leoshkevich wrote:
>>> Am 20.08.2019 um 17:50 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
>>> There is currently no way to say (in trees or gimple or rtl) whether
>>> comparisons are signaling ("ordered", generate a trap on an unordered
>>> result).  I am working on this, but :-)
>> 
>> Isn't there?  This whole series is based on the following assumption:
>> LT, LE, GT, GE are definitely signaling; LTGT is most likely signaling
>> as well; the rest are not signaling.  This is based on gccint 11.6.3:
>> Unary and Binary Expressions.
> 
> There is currently no way to implement, say, iseqsig.  And whether an
> operation is signaling should be determined by the language frontend,
> not separately by each backend!

Wouldn't expressing it as ((x <= y) && (x >= y)) work?

In any case, I'll need to check whether my patch series handles iseqsig
in at least remotely sane way..

> 
> (There should be a signaling and a non-signaling version of every float
> comparison that can be unordered).

I wholeheartedly agree.  I had to write quite a few ugly patterns to
work around the lack of e.g. non-signaling GT.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/8] Document signaling for min, max and ltgt operations
  2019-08-21 12:32         ` Ilya Leoshkevich
@ 2019-08-21 12:59           ` Segher Boessenkool
  0 siblings, 0 replies; 23+ messages in thread
From: Segher Boessenkool @ 2019-08-21 12:59 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: GCC Patches

On Wed, Aug 21, 2019 at 02:00:10PM +0200, Ilya Leoshkevich wrote:
> > Am 20.08.2019 um 19:13 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> > On Tue, Aug 20, 2019 at 06:13:00PM +0200, Ilya Leoshkevich wrote:
> >>> Am 20.08.2019 um 17:50 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> >>> There is currently no way to say (in trees or gimple or rtl) whether
> >>> comparisons are signaling ("ordered", generate a trap on an unordered
> >>> result).  I am working on this, but :-)
> >> 
> >> Isn't there?  This whole series is based on the following assumption:
> >> LT, LE, GT, GE are definitely signaling; LTGT is most likely signaling
> >> as well; the rest are not signaling.  This is based on gccint 11.6.3:
> >> Unary and Binary Expressions.
> > 
> > There is currently no way to implement, say, iseqsig.  And whether an
> > operation is signaling should be determined by the language frontend,
> > not separately by each backend!
> 
> Wouldn't expressing it as ((x <= y) && (x >= y)) work?

That is optimised only partially (on gimple) (first a compare for <=,
then a branch if false, then return "==").

I meant it cannot be implemented directly as one RTL (or gimple) insn,
although it can be done as one machine insn on many architectures.

> > (There should be a signaling and a non-signaling version of every float
> > comparison that can be unordered).
> 
> I wholeheartedly agree.  I had to write quite a few ugly patterns to
> work around the lack of e.g. non-signaling GT.

Ooh, buy in, I like it.  Thanks for the encouragement :-)


Segher

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 0/8] Use signaling FP comparison instructions
  2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (7 preceding siblings ...)
  2019-08-20  9:51 ` [PATCH 6/8] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
@ 2019-08-23 20:41 ` Joseph Myers
  8 siblings, 0 replies; 23+ messages in thread
From: Joseph Myers @ 2019-08-23 20:41 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

I'd expect this series to mention

	PR target/77918

in its ChangeLog entries (and then once it's in, glibc's 
sysdeps/s390/fpu/fix-fp-int-compare-invalid.h can be updated accordingly 
with a __GNUC_PREREQ conditional like in the x86 version).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2019-08-23 19:58 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-20  9:19 [PATCH 0/8] Use signaling FP comparison instructions Ilya Leoshkevich
2019-08-20  9:19 ` [PATCH 1/8] Document signaling for min, max and ltgt operations Ilya Leoshkevich
2019-08-20 15:43   ` Segher Boessenkool
2019-08-20 15:56     ` Ilya Leoshkevich
2019-08-20 16:02       ` Segher Boessenkool
2019-08-20 18:00         ` Ilya Leoshkevich
2019-08-20 16:13   ` Segher Boessenkool
2019-08-20 18:49     ` Ilya Leoshkevich
2019-08-20 19:56       ` Segher Boessenkool
2019-08-21 12:32         ` Ilya Leoshkevich
2019-08-21 12:59           ` Segher Boessenkool
2019-08-20  9:20 ` [PATCH 4/8] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
2019-08-20  9:20 ` [PATCH 3/8] S/390: Implement vcond_supported_p hook Ilya Leoshkevich
2019-08-20  9:20 ` [PATCH 2/8] Introduce " Ilya Leoshkevich
2019-08-20 11:37   ` Richard Sandiford
2019-08-20 11:48     ` Ilya Leoshkevich
2019-08-20 12:54       ` Richard Sandiford
2019-08-21 12:00         ` Ilya Leoshkevich
2019-08-20  9:26 ` [PATCH 5/8] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
2019-08-20  9:51 ` [PATCH 7/8] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-08-20  9:51 ` [PATCH 8/8] S/390: Test " Ilya Leoshkevich
2019-08-20  9:51 ` [PATCH 6/8] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
2019-08-23 20:41 ` [PATCH 0/8] Use signaling FP comparison instructions Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).