public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3 0/9] S/390: Use signaling FP comparison instructions
@ 2019-09-05 11:10 Ilya Leoshkevich
  2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
                   ` (8 more replies)
  0 siblings, 9 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:10 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, Ilya Leoshkevich

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

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

Patches 1-4 make it possible to query supported vcond rtxes and make
use of that for z13.

Patches 5-7 are preparation cleanups.

Patch 8 is an actual implementation.

Path 9 contains new tests, that make sure autovectorized comparisons use
proper instructions.

Ilya Leoshkevich (9):
  Allow COND_EXPR and VEC_COND_EXPR condtions to trap
  Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
  Introduce can_vector_compare_p function
  S/390: Do not use signaling vector comparisons on z13
  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

v1->v2:
Improve wording in documentation commit message.
Replace hook with optabs query.
Add signaling eq test.

v2->v3:
Allow COND_EXPR and VEC_COND_EXPR conditions to throw, while making
sure that GIMPLE_COND's condition still cannot throw.
Remove documentation patch (superseded by
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=275303).
Add PR target/77918 reference.

 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                        |  38 ++-
 gcc/config/s390/s390.md                       |  14 +
 gcc/config/s390/vector.md                     | 283 ++++++++++++------
 gcc/emit-rtl.c                                |  15 +-
 gcc/gengenrtl.c                               |  64 +++-
 gcc/gimple-expr.c                             |  25 +-
 gcc/gimple-expr.h                             |  11 +
 gcc/gimple.c                                  |   2 +
 gcc/gimplify.c                                |   5 +-
 gcc/optabs-tree.c                             |  41 ++-
 gcc/optabs.c                                  |  43 ++-
 gcc/optabs.h                                  |  16 +
 gcc/rtl.c                                     |   7 +-
 gcc/rtl.h                                     |  12 +
 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-eq-z13-finite.c  |  10 +
 .../zvector/autovec-double-signaling-eq-z13.c |   9 +
 .../zvector/autovec-double-signaling-eq.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-eq.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         |  41 +++
 gcc/tree-cfg.c                                |   5 +-
 gcc/tree-eh.c                                 |   8 +
 gcc/tree-ssa-forwprop.c                       |   7 +-
 gcc/tree-ssa-propagate.c                      |   9 +-
 76 files changed, 994 insertions(+), 191 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-eq-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.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-eq.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 v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-09-05 11:10 ` Ilya Leoshkevich
  2019-09-06 11:07   ` Richard Biener
  2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:10 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, Ilya Leoshkevich

Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
and introduces a temporary if this could happen, for example, generating

  _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
  _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;

from GENERIC

  VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
                  { -1, -1, -1, -1 } ,
		  { 0, 0, 0, 0 } >

This is not necessary and makes the resulting GIMPLE harder to analyze.
In particular, one of the next patches in series needs to get to
VEC_COND_EXPR's comparison code, which is not possible when a temporary
is introduced.

This patch takes special care to avoid introducing trapping comparisons
in GIMPLE_COND.  They are not allowed, because they would require 3
outgoing edges (then, else and EH), which is awkward to say the least.
Therefore, computations of such conditions should live in their own basic
blocks.

gcc/ChangeLog:

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

	PR target/77918
	* gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
	caller passes a non-trapping condition.
	(is_gimple_condexpr): Allow trapping conditions.
	(is_gimple_condexpr_1): New helper function.
	(is_gimple_condexpr_for_cond): New function, acts like old
	is_gimple_condexpr.
	* gimple-expr.h (is_gimple_condexpr_for_cond): New function.
	(gimple_ternary_operands_ok_p): New function to remove code
	duplication i verify_gimple_assign_ternary and
	valid_gimple_rhs_p.
	* gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
	VEC_COND_EXPR.
	* gimplify.c (gimplify_cond_expr): Use
	is_gimple_condexpr_for_cond.
	(gimplify_expr): Allow is_gimple_condexpr_for_cond.
	* tree-cfg.c (verify_gimple_assign_ternary): Use
	gimple_ternary_operands_ok_p.
	* tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
	VEC_COND_EXPR.
	(tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
	* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
	is_gimple_condexpr_for_cond, remove pointless tmp check
	(forward_propagate_into_cond): Remove pointless tmp check.
	* tree-ssa-propagate.c (valid_gimple_rhs_p): Use
	gimple_ternary_operands_ok_p.
---
 gcc/gimple-expr.c        | 25 +++++++++++++++++++++----
 gcc/gimple-expr.h        | 11 +++++++++++
 gcc/gimple.c             |  2 ++
 gcc/gimplify.c           |  5 +++--
 gcc/tree-cfg.c           |  5 +----
 gcc/tree-eh.c            |  8 ++++++++
 gcc/tree-ssa-forwprop.c  |  7 ++++---
 gcc/tree-ssa-propagate.c |  9 ++++-----
 8 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index b0c9f9b671a..46e5f000580 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -571,6 +571,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
 	      || TREE_CODE (cond) == TRUTH_NOT_EXPR
 	      || is_gimple_min_invariant (cond)
 	      || SSA_VAR_P (cond));
+  gcc_assert (!tree_could_throw_p (cond));
 
   extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
 
@@ -602,17 +603,33 @@ is_gimple_lvalue (tree t)
 	  || TREE_CODE (t) == BIT_FIELD_REF);
 }
 
-/*  Return true if T is a GIMPLE condition.  */
+/* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond.  */
 
-bool
-is_gimple_condexpr (tree t)
+static bool
+is_gimple_condexpr_1 (tree t, bool allow_traps)
 {
   return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
-				&& !tree_could_throw_p (t)
+				&& (allow_traps || !tree_could_throw_p (t))
 				&& is_gimple_val (TREE_OPERAND (t, 0))
 				&& is_gimple_val (TREE_OPERAND (t, 1))));
 }
 
+/*  Return true if T is a GIMPLE condition.  */
+
+bool
+is_gimple_condexpr (tree t)
+{
+  return is_gimple_condexpr_1 (t, true);
+}
+
+/* Like is_gimple_condexpr, but does not allow T to trap.  */
+
+bool
+is_gimple_condexpr_for_cond (tree t)
+{
+  return is_gimple_condexpr_1 (t, false);
+}
+
 /* Return true if T is a gimple address.  */
 
 bool
diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
index 1ad1432bd17..27190b1e5fe 100644
--- a/gcc/gimple-expr.h
+++ b/gcc/gimple-expr.h
@@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
 					   tree *);
 extern bool is_gimple_lvalue (tree);
 extern bool is_gimple_condexpr (tree);
+extern bool is_gimple_condexpr_for_cond (tree);
 extern bool is_gimple_address (const_tree);
 extern bool is_gimple_invariant_address (const_tree);
 extern bool is_gimple_ip_invariant_address (const_tree);
@@ -175,4 +176,14 @@ gimple_call_addr_fndecl (const_tree fn)
   return NULL_TREE;
 }
 
+static inline bool
+gimple_ternary_operands_ok_p (enum tree_code code, tree op1, tree op2, tree op3)
+{
+  return ((code == VEC_COND_EXPR || code == COND_EXPR)
+	  ? is_gimple_condexpr (op1)
+	  : is_gimple_val (op1))
+	 && is_gimple_val (op2)
+	 && is_gimple_val (op3);
+}
+
 #endif /* GCC_GIMPLE_EXPR_H */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 633ef512a19..fd14fbec15e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
       op = gimple_assign_rhs_code (s);
       if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
 	div = gimple_assign_rhs2 (s);
+      else if (op == COND_EXPR || op == VEC_COND_EXPR)
+	op = TREE_CODE (gimple_assign_rhs1 (s));
       return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
 				      (INTEGRAL_TYPE_P (t)
 				       && TYPE_OVERFLOW_TRAPS (t)),
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index daa0b71c191..920e423381c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4141,8 +4141,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
   /* Now do the normal gimplification.  */
 
   /* Gimplify condition.  */
-  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
-		       fb_rvalue);
+  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+		       is_gimple_condexpr_for_cond, fb_rvalue);
   if (ret == GS_ERROR)
     return GS_ERROR;
   gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
@@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   else if (gimple_test_f == is_gimple_val
            || gimple_test_f == is_gimple_call_addr
            || gimple_test_f == is_gimple_condexpr
+	   || gimple_test_f == is_gimple_condexpr_for_cond
            || gimple_test_f == is_gimple_mem_rhs
            || gimple_test_f == is_gimple_mem_rhs_or_call
            || gimple_test_f == is_gimple_reg_rhs
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b75fdb2e63f..4d2239e9d2f 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4121,10 +4121,7 @@ verify_gimple_assign_ternary (gassign *stmt)
       return true;
     }
 
-  if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
-       ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
-      || !is_gimple_val (rhs2)
-      || !is_gimple_val (rhs3))
+  if (!gimple_ternary_operands_ok_p (rhs_code, rhs1, rhs2, rhs3))
     {
       error ("invalid operands in ternary operation");
       return true;
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 5bb07e49d28..98dc95a07cd 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
   bool honor_snans = fp_operation && flag_signaling_nans != 0;
   bool handled;
 
+  /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
+     trap, because that depends on the respective condition op.  */
+  gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
+
   if (TREE_CODE_CLASS (op) != tcc_comparison
       && TREE_CODE_CLASS (op) != tcc_unary
       && TREE_CODE_CLASS (op) != tcc_binary)
@@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
   if (!expr)
     return false;
 
+  /* For COND_EXPR and VEC_COND_EXPR, only the condition may trap.  */
+  if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
+    expr = TREE_OPERAND (expr, 0);
+
   code = TREE_CODE (expr);
   t = TREE_TYPE (expr);
 
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index c464c899586..edc5417f455 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -524,9 +524,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
   tmp = forward_propagate_into_comparison_1 (stmt, code,
 					     boolean_type_node,
 					     rhs1, rhs2);
-  if (tmp)
+  if (tmp
+      && is_gimple_condexpr_for_cond (tmp))
     {
-      if (dump_file && tmp)
+      if (dump_file)
 	{
 	  fprintf (dump_file, "  Replaced '");
 	  print_gimple_expr (dump_file, stmt, 0);
@@ -604,7 +605,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
   if (tmp
       && is_gimple_condexpr (tmp))
     {
-      if (dump_file && tmp)
+      if (dump_file)
 	{
 	  fprintf (dump_file, "  Replaced '");
 	  print_generic_expr (dump_file, cond);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 7172ef8b4e6..be34e25fc40 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -523,11 +523,10 @@ valid_gimple_rhs_p (tree expr)
 	default:
 	  if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
 	    {
-	      if (((code == VEC_COND_EXPR || code == COND_EXPR)
-		   ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
-		   : !is_gimple_val (TREE_OPERAND (expr, 0)))
-		  || !is_gimple_val (TREE_OPERAND (expr, 1))
-		  || !is_gimple_val (TREE_OPERAND (expr, 2)))
+	      if (!gimple_ternary_operands_ok_p (code,
+	                                         TREE_OPERAND (expr, 0),
+	                                         TREE_OPERAND (expr, 1),
+	                                         TREE_OPERAND (expr, 2)))
 		return false;
 	      break;
 	    }
-- 
2.21.0

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

* [PATCH v3 3/9] Introduce can_vector_compare_p function
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (4 preceding siblings ...)
  2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
  2019-09-06 12:58   ` Richard Sandiford
  2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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 exists, which does not contain information about
the operation.

Introduce a function that checks whether back-end supports vector
comparisons with individual rtx codes by matching vcond expander's third
argument with a fake comparison with the corresponding rtx code.

gcc/ChangeLog:

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

	PR target/77918
	* optabs-tree.c (vcond_icode_p): New function.
	(vcond_eq_icode_p): New function.
	(expand_vec_cond_expr_p): Use vcond_icode_p and
	vcond_eq_icode_p.
	* optabs.c (can_vector_compare_p): New function.
	(get_rtx_code): Use get_rtx_code_safe.
	(get_rtx_code_safe): New function.
	* optabs.h (enum can_vector_compare_purpose): New enum.
	(can_vector_compare_p): New function.
	(get_rtx_code_safe): Likewise.
---
 gcc/optabs-tree.c | 41 +++++++++++++++++++++++++++++++++--------
 gcc/optabs.c      | 43 +++++++++++++++++++++++++++++++++++++++----
 gcc/optabs.h      | 16 ++++++++++++++++
 3 files changed, 88 insertions(+), 12 deletions(-)

diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..ff7237187dd 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -23,7 +23,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "target.h"
 #include "insn-codes.h"
+#include "rtl.h"
 #include "tree.h"
+#include "memmodel.h"
+#include "optabs.h"
 #include "optabs-tree.h"
 #include "stor-layout.h"
 
@@ -329,6 +332,34 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
   return false;
 }
 
+/* Return TRUE iff vcond_optab/vcondu_optab support the given tree
+   comparison.  */
+
+static bool
+vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+  enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
+  if (rcode == LAST_AND_UNUSED_RTX_CODE)
+    /* This may happen, for example, if code == SSA_NAME, in which case we
+       cannot be certain whether a vector insn is available.  */
+    return false;
+
+  return can_vector_compare_p (rcode, TYPE_MODE (value_type),
+			       TYPE_MODE (cmp_op_type), cvcp_vcond);
+}
+
+/* Return TRUE iff vcondeq_optab supports the given tree comparison.  */
+
+static bool
+vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+  if (code != EQ_EXPR && code != NE_EXPR)
+    return false;
+
+  return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
+	 != CODE_FOR_nothing;
+}
+
 /* Return TRUE iff, appropriate vector insns are available
    for vector cond expr with vector type VALUE_TYPE and a comparison
    with operand vector types in CMP_OP_TYPE.  */
@@ -347,14 +378,8 @@ 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
-      && ((code != EQ_EXPR && code != NE_EXPR)
-	  || get_vcond_eq_icode (TYPE_MODE (value_type),
-				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
-    return false;
-
-  return true;
+  return vcond_icode_p (value_type, cmp_op_type, code)
+	 || vcond_eq_icode_p (value_type, cmp_op_type, code);
 }
 
 /* Use the current target and options to initialize
diff --git a/gcc/optabs.c b/gcc/optabs.c
index cdd07f3e53f..479789570a9 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
   return 0;
 }
 
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+   CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+   in order to achieve a PURPOSE.  */
+
+bool
+can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
+		      machine_mode cmp_op_mode,
+		      enum can_vector_compare_purpose purpose)
+{
+  enum insn_code icode;
+  bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
+  rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
+  rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
+  rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
+
+  if (purpose == cvcp_vcond
+      && (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+	 != CODE_FOR_nothing
+      && insn_operand_matches (icode, 3, test))
+    return true;
+
+  return false;
+}
+
 /* This function is called when we are going to emit a compare instruction that
    compares the values found in X and Y, using the rtl operator COMPARISON.
 
@@ -5348,11 +5372,11 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
   return insn;
 }
 
-/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
-   or unsigned operation code.  */
+/* Return rtx code for TCODE or LAST_AND_UNUSED_RTX_CODE if it has no RTL
+   counterpart.  Use UNSIGNEDP to select signed or unsigned operation code.  */
 
 enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_safe (enum tree_code tcode, bool unsignedp)
 {
   enum rtx_code code;
   switch (tcode)
@@ -5410,11 +5434,22 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
       break;
 
     default:
-      gcc_unreachable ();
+      code = LAST_AND_UNUSED_RTX_CODE;
+      break;
     }
   return code;
 }
 
+/* Like get_rtx_code_safe, but asserts when given unsupported tree codes.  */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+  enum rtx_code code = get_rtx_code_safe (tcode, unsignedp);
+  gcc_assert (code != LAST_AND_UNUSED_RTX_CODE);
+  return code;
+}
+
 /* Return a comparison rtx of mode CMP_MODE for COND.  Use UNSIGNEDP to
    select signed or unsigned operators.  OPNO holds the index of the
    first comparison operand for insn ICODE.  Do not generate the
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 897bb5d4443..712470a0245 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -242,6 +242,21 @@ enum can_compare_purpose
    (without splitting it into pieces).  */
 extern int can_compare_p (enum rtx_code, machine_mode,
 			  enum can_compare_purpose);
+
+/* The various uses that a vector comparison can have; used by
+   can_vector_compare_p.  So far only vcond is defined, vec_cmp is a possible
+   future extension.  */
+enum can_vector_compare_purpose
+{
+  cvcp_vcond
+};
+
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+   CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+   in order to achieve a PURPOSE.  */
+extern bool can_vector_compare_p (enum rtx_code, machine_mode, machine_mode,
+				  enum can_vector_compare_purpose);
+
 extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
 			    machine_mode, int);
 /* Emit a pair of rtl insns to compare two rtx's and to jump
@@ -356,6 +371,7 @@ extern void expand_insn (enum insn_code icode, unsigned int nops,
 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
 			      class expand_operand *ops);
 
+extern enum rtx_code get_rtx_code_safe (enum tree_code tcode, bool unsignedp);
 extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
 
 #endif /* GCC_OPTABS_H */
-- 
2.21.0

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

* [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode>
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
  2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
  2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
  2019-09-30 14:41   ` Andreas Krebbel
  2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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>

	PR target/77918
	* 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 ca5ec0dd3b0..1b66b8be61f 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1581,15 +1581,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 v3 4/9] S/390: Do not use signaling vector comparisons on z13
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (2 preceding siblings ...)
  2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
  2019-09-06 10:34   ` Segher Boessenkool
  2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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 more restrictive operator predicate in
vcond<V_HW:mode><V_HW2:mode>.

gcc/ChangeLog:

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

	PR target/77918
	* config/s390/vector.md (vcond_comparison_operator): New
	predicate.
	(vcond<V_HW:mode><V_HW2:mode>): Use vcond_comparison_operator.
---
 gcc/config/s390/vector.md | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 0702e1de835..d7a266c5605 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -614,10 +614,30 @@
   operands[2] = GEN_INT (GET_MODE_NUNITS (<MODE>mode) - 1);
 })
 
+(define_predicate "vcond_comparison_operator"
+  (match_operand 0 "comparison_operator")
+{
+  if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
+      && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
+    return true;
+  switch (GET_CODE (op))
+    {
+    case LE:
+    case LT:
+    case GE:
+    case GT:
+    case LTGT:
+      /* Signaling vector comparisons are supported only on z14+.  */
+      return TARGET_Z14;
+    default:
+      return true;
+    }
+})
+
 (define_expand "vcond<V_HW:mode><V_HW2:mode>"
   [(set (match_operand:V_HW 0 "register_operand" "")
 	(if_then_else:V_HW
-	 (match_operator 3 "comparison_operator"
+	 (match_operator 3 "vcond_comparison_operator"
 			 [(match_operand:V_HW2 4 "register_operand" "")
 			  (match_operand:V_HW2 5 "nonmemory_operand" "")])
 	 (match_operand:V_HW 1 "nonmemory_operand" "")
-- 
2.21.0

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

* [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (3 preceding siblings ...)
  2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
  2019-09-06 11:09   ` Richard Biener
  2019-09-06 12:40   ` Richard Sandiford
  2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, Ilya Leoshkevich

One of the next patches in series needs to frequently pass short-lived
fake rtxes to the back-end in order to test its capabilities.  In order
to reduce the load on GC, it is beneficial to allocate these rtxes on
stack.

Provide the macro counterparts of gen_* functions required by the next
patch in series.

gcc/ChangeLog:

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

	PR target/77918
	* emit-rtl.c (gen_raw_REG): Use init_raw_REG.
	(init_raw_REG): New function.
	* gengenrtl.c (gendef): Emit init_* functions and alloca_*
	macros.
	* rtl.c (rtx_alloc_stat_v): Use rtx_init.
	* rtl.h (rtx_init): New function.
	(rtx_alloca): New function.
	(init_raw_REG): New function.
	(alloca_raw_REG): New macro.
---
 gcc/emit-rtl.c  | 15 +++++++++---
 gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
 gcc/rtl.c       |  7 +-----
 gcc/rtl.h       | 12 ++++++++++
 4 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index a667cdab94e..ecfa3735bba 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
   set_regno_raw (x, regno, nregs);
 }
 
-/* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
+/* Initialize a REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
    don't attempt to share with the various global pieces of rtl (such as
    frame_pointer_rtx).  */
 
 rtx
-gen_raw_REG (machine_mode mode, unsigned int regno)
+init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
 {
-  rtx x = rtx_alloc (REG MEM_STAT_INFO);
   set_mode_and_regno (x, mode, regno);
   REG_ATTRS (x) = NULL;
   ORIGINAL_REGNO (x) = regno;
   return x;
 }
 
+/* Generate a new REG rtx.  */
+
+rtx
+gen_raw_REG (machine_mode mode, unsigned int regno)
+{
+  rtx x = rtx_alloc (REG MEM_STAT_INFO);
+  init_raw_REG (x, mode, regno);
+  return x;
+}
+
 /* There are some RTL codes that require special attention; the generation
    functions do the raw handling.  If you add to this list, modify
    special_rtx in gengenrtl.c as well.  */
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index 5c78fabfb50..cd314a68a83 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -231,8 +231,7 @@ genmacro (int idx)
   puts (")");
 }
 
-/* Generate the code for the function to generate RTL whose
-   format is FORMAT.  */
+/* Generate the code for functions to generate RTL whose format is FORMAT.  */
 
 static void
 gendef (const char *format)
@@ -240,22 +239,18 @@ gendef (const char *format)
   const char *p;
   int i, j;
 
-  /* Start by writing the definition of the function name and the types
+  /* Write the definition of the init function name and the types
      of the arguments.  */
 
-  printf ("static inline rtx\ngen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
+  puts ("static inline rtx");
+  printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
   for (p = format, i = 0; *p != 0; p++)
     if (*p != '0')
       printf (",\n\t%sarg%d", type_from_format (*p), i++);
+  puts (")");
 
-  puts (" MEM_STAT_DECL)");
-
-  /* Now write out the body of the function itself, which allocates
-     the memory and initializes it.  */
+  /* Now write out the body of the init function itself.  */
   puts ("{");
-  puts ("  rtx rt;");
-  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);\n");
-
   puts ("  PUT_MODE_RAW (rt, mode);");
 
   for (p = format, i = j = 0; *p ; ++p, ++i)
@@ -266,16 +261,55 @@ gendef (const char *format)
     else
       printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
 
-  puts ("\n  return rt;\n}\n");
+  puts ("  return rt;\n}\n");
+
+  /* Write the definition of the gen function name and the types
+     of the arguments.  */
+
+  puts ("static inline rtx");
+  printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
+  for (p = format, i = 0; *p != 0; p++)
+    if (*p != '0')
+      printf (",\n\t%sarg%d", type_from_format (*p), i++);
+  puts (" MEM_STAT_DECL)");
+
+  /* Now write out the body of the function itself, which allocates
+     the memory and initializes it.  */
+  puts ("{");
+  puts ("  rtx rt;\n");
+
+  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);");
+  printf ("  init_rtx_fmt_%s (rt, mode", format);
+  for (p = format, i = 0; *p != 0; p++)
+    if (*p != '0')
+      printf (", arg%d", i++);
+  puts (");\n");
+
+  puts ("  return rt;\n}\n");
+
+  /* Write the definition of gen macro.  */
+
   printf ("#define gen_rtx_fmt_%s(c, m", format);
   for (p = format, i = 0; *p != 0; p++)
     if (*p != '0')
-      printf (", p%i",i++);
-  printf (")\\\n        gen_rtx_fmt_%s_stat (c, m", format);
+      printf (", arg%d", i++);
+  printf (") \\\n  gen_rtx_fmt_%s_stat ((c), (m)", format);
   for (p = format, i = 0; *p != 0; p++)
     if (*p != '0')
-      printf (", p%i",i++);
+      printf (", (arg%d)", i++);
   printf (" MEM_STAT_INFO)\n\n");
+
+  /* Write the definition of alloca macro.  */
+
+  printf ("#define alloca_rtx_fmt_%s(c, m", format);
+  for (p = format, i = 0; *p != 0; p++)
+    if (*p != '0')
+      printf (", arg%d", i++);
+  printf (") \\\n  init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
+  for (p = format, i = 0; *p != 0; p++)
+    if (*p != '0')
+      printf (", (arg%d)", i++);
+  printf (")\n\n");
 }
 
 /* Generate the documentation header for files we write.  */
diff --git a/gcc/rtl.c b/gcc/rtl.c
index d7b8e9877c3..0be52d38d93 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -219,12 +219,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
   rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
 				   PASS_MEM_STAT);
 
-  /* We want to clear everything up to the FLD array.  Normally, this
-     is one int, but we don't want to assume that and it isn't very
-     portable anyway; this is.  */
-
-  memset (rt, 0, RTX_HDR_SIZE);
-  PUT_CODE (rt, code);
+  rtx_init (rt, code);
 
   if (GATHER_STATISTICS)
     {
diff --git a/gcc/rtl.h b/gcc/rtl.h
index efb9b3ce40d..cf1547196f2 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2933,6 +2933,15 @@ extern HOST_WIDE_INT get_stack_check_protect (void);
 
 /* In rtl.c */
 extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
+inline rtx
+rtx_init (rtx rt, RTX_CODE code)
+{
+  memset (rt, 0, RTX_HDR_SIZE);
+  PUT_CODE (rt, code);
+  return rt;
+}
+#define rtx_alloca(code) \
+  rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
 extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
 #define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
 #define const_wide_int_alloc(NWORDS)				\
@@ -3797,7 +3806,10 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
 extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
 extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
 extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
 extern rtx gen_raw_REG (machine_mode, unsigned int);
+#define alloca_raw_REG(mode, regno) \
+  init_raw_REG (rtx_alloca (REG), (mode), (regno))
 extern rtx gen_rtx_REG (machine_mode, unsigned int);
 extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
 extern rtx gen_rtx_MEM (machine_mode, rtx);
-- 
2.21.0

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

* [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
  2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
@ 2019-09-05 11:11 ` Ilya Leoshkevich
  2019-09-30 14:51   ` Andreas Krebbel
  2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:11 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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>

	PR target/77918
	* 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 d7a266c5605..ca5ec0dd3b0 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -649,6 +649,21 @@
   DONE;
 })
 
+(define_expand "vcondv1tiv1tf"
+  [(set (match_operand:V1TI 0 "register_operand" "")
+	(if_then_else:V1TI
+	 (match_operator 3 "vcond_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 v3 9/9] S/390: Test signaling FP comparison instructions
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (7 preceding siblings ...)
  2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, Ilya Leoshkevich

gcc/testsuite/ChangeLog:

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

	PR target/77918
	* 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-eq-z13-finite.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c: New test.
	* gcc.target/s390/zvector/autovec-double-signaling-eq.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-eq.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-eq-z13-finite.c  | 10 +++++
 .../zvector/autovec-double-signaling-eq-z13.c |  9 ++++
 .../zvector/autovec-double-signaling-eq.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-eq.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         | 41 +++++++++++++++++++
 51 files changed, 485 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-eq-z13-finite.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.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-eq.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-eq-z13-finite.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13-finite.c
new file mode 100644
index 00000000000..e3d42eaf3ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-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_EQ);
+
+/* We can use non-signaling vector comparison instructions with
+   -ffinite-math-only.  */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
new file mode 100644
index 00000000000..f6110328891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq-z13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z13 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_EQ);
+
+/* z13 does not have signaling vector comparison instructions.  */
+/* { dg-final { scan-assembler {\n\tkdbr\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
new file mode 100644
index 00000000000..32088cb55b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-eq.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_DOUBLE (SIGNALING_EQ);
+
+/* The vectorizer produces <= and ==, which rtl passes cannot turn into vfkedb
+   yet.  */
+/* { dg-final { scan-assembler {\n\tvfcedb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfkhedb\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-eq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
new file mode 100644
index 00000000000..ce3271c918c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-eq.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector" } */
+
+#include "autovec.h"
+
+AUTOVEC_FLOAT (SIGNALING_EQ);
+
+/* The vectorizer produces <= and ==, which rtl passes cannot turn into vfkesb
+   yet.  */
+/* { dg-final { scan-assembler {\n\tvfcesb\t} } } */
+/* { dg-final { scan-assembler {\n\tvfkhesb\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..d04e5d7e00e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/autovec.h
@@ -0,0 +1,41 @@
+#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_EQ(x, y) (((x) <= (y)) && ((x) >= (y)))
+#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 v3 8/9] S/390: Use signaling FP comparison instructions
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (5 preceding siblings ...)
  2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
  2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
  2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich
  8 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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>

	PR target/77918
	* 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 f36e12affd2..ae1545c39f7 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 a093ae5c565..7f33d34e726 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
@@ -1392,7 +1388,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))
@@ -1427,7 +1424,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))
@@ -1481,27 +1479,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);
@@ -1514,18 +1619,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);
@@ -1545,7 +1656,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

* [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders
  2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
                   ` (6 preceding siblings ...)
  2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
@ 2019-09-05 11:12 ` Ilya Leoshkevich
  2019-09-30 14:50   ` Andreas Krebbel
  2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich
  8 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-05 11:12 UTC (permalink / raw)
  To: gcc-patches
  Cc: richard.guenther, richard.sandiford, segher, joseph, krebbel,
	rdapp, 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>

	PR target/77918
	* 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 24784266848..f36e12affd2 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 1b66b8be61f..a093ae5c565 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -1507,22 +1507,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")
@@ -1535,24 +1519,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")))
@@ -1563,45 +1531,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

* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
  2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
@ 2019-09-06 10:34   ` Segher Boessenkool
  2019-09-30 13:36     ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Segher Boessenkool @ 2019-09-06 10:34 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: gcc-patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp

Hi Ilya,

On Thu, Sep 05, 2019 at 01:10:14PM +0200, Ilya Leoshkevich wrote:
> 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 more restrictive operator predicate in
> vcond<V_HW:mode><V_HW2:mode>.

> +(define_predicate "vcond_comparison_operator"
> +  (match_operand 0 "comparison_operator")
> +{
> +  if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
> +      && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
> +    return true;
> +  switch (GET_CODE (op))
> +    {
> +    case LE:
> +    case LT:
> +    case GE:
> +    case GT:
> +    case LTGT:
> +      /* Signaling vector comparisons are supported only on z14+.  */
> +      return TARGET_Z14;
> +    default:
> +      return true;
> +    }
> +})

Should you handle -fsignaling-nans here as well?


Segher

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

* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
  2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
@ 2019-09-06 11:07   ` Richard Biener
  2019-09-06 15:45     ` Ilya Leoshkevich
  0 siblings, 1 reply; 23+ messages in thread
From: Richard Biener @ 2019-09-06 11:07 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
	Joseph S. Myers, Andreas Krebbel, Robin Dapp

On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
> and introduces a temporary if this could happen, for example, generating
>
>   _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
>   _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
>
> from GENERIC
>
>   VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
>                   { -1, -1, -1, -1 } ,
>                   { 0, 0, 0, 0 } >
>
> This is not necessary and makes the resulting GIMPLE harder to analyze.
> In particular, one of the next patches in series needs to get to
> VEC_COND_EXPR's comparison code, which is not possible when a temporary
> is introduced.
>
> This patch takes special care to avoid introducing trapping comparisons
> in GIMPLE_COND.  They are not allowed, because they would require 3
> outgoing edges (then, else and EH), which is awkward to say the least.
> Therefore, computations of such conditions should live in their own basic
> blocks.

Comments inline (thanks for the work btw)

> gcc/ChangeLog:
>
> 2019-09-03  Ilya Leoshkevich  <iii@linux.ibm.com>
>
>         PR target/77918
>         * gimple-expr.c (gimple_cond_get_ops_from_tree): Assert that the
>         caller passes a non-trapping condition.
>         (is_gimple_condexpr): Allow trapping conditions.
>         (is_gimple_condexpr_1): New helper function.
>         (is_gimple_condexpr_for_cond): New function, acts like old
>         is_gimple_condexpr.
>         * gimple-expr.h (is_gimple_condexpr_for_cond): New function.
>         (gimple_ternary_operands_ok_p): New function to remove code
>         duplication i verify_gimple_assign_ternary and
>         valid_gimple_rhs_p.
>         * gimple.c (gimple_could_trap_p_1): Handle COND_EXPR and
>         VEC_COND_EXPR.
>         * gimplify.c (gimplify_cond_expr): Use
>         is_gimple_condexpr_for_cond.
>         (gimplify_expr): Allow is_gimple_condexpr_for_cond.
>         * tree-cfg.c (verify_gimple_assign_ternary): Use
>         gimple_ternary_operands_ok_p.
>         * tree-eh.c (operation_could_trap_p): Assert on COND_EXPR and
>         VEC_COND_EXPR.
>         (tree_could_trap_p): Handle COND_EXPR and VEC_COND_EXPR.
>         * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond): Use
>         is_gimple_condexpr_for_cond, remove pointless tmp check
>         (forward_propagate_into_cond): Remove pointless tmp check.
>         * tree-ssa-propagate.c (valid_gimple_rhs_p): Use
>         gimple_ternary_operands_ok_p.
> ---
>  gcc/gimple-expr.c        | 25 +++++++++++++++++++++----
>  gcc/gimple-expr.h        | 11 +++++++++++
>  gcc/gimple.c             |  2 ++
>  gcc/gimplify.c           |  5 +++--
>  gcc/tree-cfg.c           |  5 +----
>  gcc/tree-eh.c            |  8 ++++++++
>  gcc/tree-ssa-forwprop.c  |  7 ++++---
>  gcc/tree-ssa-propagate.c |  9 ++++-----
>  8 files changed, 54 insertions(+), 18 deletions(-)
>
> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> index b0c9f9b671a..46e5f000580 100644
> --- a/gcc/gimple-expr.c
> +++ b/gcc/gimple-expr.c
> @@ -571,6 +571,7 @@ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
>               || TREE_CODE (cond) == TRUTH_NOT_EXPR
>               || is_gimple_min_invariant (cond)
>               || SSA_VAR_P (cond));
> +  gcc_assert (!tree_could_throw_p (cond));

make this gcc_checking_assert ()

>    extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
>
> @@ -602,17 +603,33 @@ is_gimple_lvalue (tree t)
>           || TREE_CODE (t) == BIT_FIELD_REF);
>  }
>
> -/*  Return true if T is a GIMPLE condition.  */
> +/* Helper for is_gimple_condexpr and is_gimple_condexpr_for_cond.  */
>
> -bool
> -is_gimple_condexpr (tree t)
> +static bool
> +is_gimple_condexpr_1 (tree t, bool allow_traps)
>  {
>    return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
> -                               && !tree_could_throw_p (t)
> +                               && (allow_traps || !tree_could_throw_p (t))
>                                 && is_gimple_val (TREE_OPERAND (t, 0))
>                                 && is_gimple_val (TREE_OPERAND (t, 1))));
>  }
>
> +/*  Return true if T is a GIMPLE condition.  */
> +
> +bool
> +is_gimple_condexpr (tree t)
> +{
> +  return is_gimple_condexpr_1 (t, true);
> +}
> +
> +/* Like is_gimple_condexpr, but does not allow T to trap.  */
> +
> +bool
> +is_gimple_condexpr_for_cond (tree t)
> +{
> +  return is_gimple_condexpr_1 (t, false);
> +}
> +
>  /* Return true if T is a gimple address.  */
>
>  bool
> diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
> index 1ad1432bd17..27190b1e5fe 100644
> --- a/gcc/gimple-expr.h
> +++ b/gcc/gimple-expr.h
> @@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
>                                            tree *);
>  extern bool is_gimple_lvalue (tree);
>  extern bool is_gimple_condexpr (tree);
> +extern bool is_gimple_condexpr_for_cond (tree);
>  extern bool is_gimple_address (const_tree);
>  extern bool is_gimple_invariant_address (const_tree);
>  extern bool is_gimple_ip_invariant_address (const_tree);
> @@ -175,4 +176,14 @@ gimple_call_addr_fndecl (const_tree fn)
>    return NULL_TREE;
>  }
>
> +static inline bool
> +gimple_ternary_operands_ok_p (enum tree_code code, tree op1, tree op2, tree op3)
> +{
> +  return ((code == VEC_COND_EXPR || code == COND_EXPR)
> +         ? is_gimple_condexpr (op1)
> +         : is_gimple_val (op1))
> +        && is_gimple_val (op2)
> +        && is_gimple_val (op3);
> +}

Hmm, I don't like this too much, please simply adjust the
two places you use it (there's actually nothign to adjust?)

>  #endif /* GCC_GIMPLE_EXPR_H */
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index 633ef512a19..fd14fbec15e 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
>        op = gimple_assign_rhs_code (s);
>        if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
>         div = gimple_assign_rhs2 (s);
> +      else if (op == COND_EXPR || op == VEC_COND_EXPR)
> +       op = TREE_CODE (gimple_assign_rhs1 (s));

I think this is not correct since we can have

int i = fp > 1. ? intval1 : intval2

and thus FLOAT_TYPE_P (t)  is wrong.  You need to do

  t = TREE_TYPE (op);

as well I think.

OK with those changes - you can apply this independently of the rest of the
series btw.

Thanks,
Richard.

>        return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
>                                       (INTEGRAL_TYPE_P (t)
>                                        && TYPE_OVERFLOW_TRAPS (t)),
> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> index daa0b71c191..920e423381c 100644
> --- a/gcc/gimplify.c
> +++ b/gcc/gimplify.c
> @@ -4141,8 +4141,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
>    /* Now do the normal gimplification.  */
>
>    /* Gimplify condition.  */
> -  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, is_gimple_condexpr,
> -                      fb_rvalue);
> +  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
> +                      is_gimple_condexpr_for_cond, fb_rvalue);
>    if (ret == GS_ERROR)
>      return GS_ERROR;
>    gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
> @@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
>    else if (gimple_test_f == is_gimple_val
>             || gimple_test_f == is_gimple_call_addr
>             || gimple_test_f == is_gimple_condexpr
> +          || gimple_test_f == is_gimple_condexpr_for_cond
>             || gimple_test_f == is_gimple_mem_rhs
>             || gimple_test_f == is_gimple_mem_rhs_or_call
>             || gimple_test_f == is_gimple_reg_rhs
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index b75fdb2e63f..4d2239e9d2f 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -4121,10 +4121,7 @@ verify_gimple_assign_ternary (gassign *stmt)
>        return true;
>      }
>
> -  if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
> -       ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
> -      || !is_gimple_val (rhs2)
> -      || !is_gimple_val (rhs3))
> +  if (!gimple_ternary_operands_ok_p (rhs_code, rhs1, rhs2, rhs3))
>      {
>        error ("invalid operands in ternary operation");
>        return true;
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index 5bb07e49d28..98dc95a07cd 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv,
>    bool honor_snans = fp_operation && flag_signaling_nans != 0;
>    bool handled;
>
> +  /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could
> +     trap, because that depends on the respective condition op.  */
> +  gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR);
> +
>    if (TREE_CODE_CLASS (op) != tcc_comparison
>        && TREE_CODE_CLASS (op) != tcc_unary
>        && TREE_CODE_CLASS (op) != tcc_binary)
> @@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr)
>    if (!expr)
>      return false;
>
> +  /* For COND_EXPR and VEC_COND_EXPR, only the condition may trap.  */
> +  if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR)
> +    expr = TREE_OPERAND (expr, 0);
> +
>    code = TREE_CODE (expr);
>    t = TREE_TYPE (expr);
>
> diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
> index c464c899586..edc5417f455 100644
> --- a/gcc/tree-ssa-forwprop.c
> +++ b/gcc/tree-ssa-forwprop.c
> @@ -524,9 +524,10 @@ forward_propagate_into_gimple_cond (gcond *stmt)
>    tmp = forward_propagate_into_comparison_1 (stmt, code,
>                                              boolean_type_node,
>                                              rhs1, rhs2);
> -  if (tmp)
> +  if (tmp
> +      && is_gimple_condexpr_for_cond (tmp))
>      {
> -      if (dump_file && tmp)
> +      if (dump_file)
>         {
>           fprintf (dump_file, "  Replaced '");
>           print_gimple_expr (dump_file, stmt, 0);
> @@ -604,7 +605,7 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
>    if (tmp
>        && is_gimple_condexpr (tmp))
>      {
> -      if (dump_file && tmp)
> +      if (dump_file)
>         {
>           fprintf (dump_file, "  Replaced '");
>           print_generic_expr (dump_file, cond);
> diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
> index 7172ef8b4e6..be34e25fc40 100644
> --- a/gcc/tree-ssa-propagate.c
> +++ b/gcc/tree-ssa-propagate.c
> @@ -523,11 +523,10 @@ valid_gimple_rhs_p (tree expr)
>         default:
>           if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
>             {
> -             if (((code == VEC_COND_EXPR || code == COND_EXPR)
> -                  ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
> -                  : !is_gimple_val (TREE_OPERAND (expr, 0)))
> -                 || !is_gimple_val (TREE_OPERAND (expr, 1))
> -                 || !is_gimple_val (TREE_OPERAND (expr, 2)))
> +             if (!gimple_ternary_operands_ok_p (code,
> +                                                TREE_OPERAND (expr, 0),
> +                                                TREE_OPERAND (expr, 1),
> +                                                TREE_OPERAND (expr, 2)))
>                 return false;
>               break;
>             }
> --
> 2.21.0
>

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

* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
  2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
@ 2019-09-06 11:09   ` Richard Biener
  2019-09-06 12:40   ` Richard Sandiford
  1 sibling, 0 replies; 23+ messages in thread
From: Richard Biener @ 2019-09-06 11:09 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
	Joseph S. Myers, Andreas Krebbel, Robin Dapp

On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> One of the next patches in series needs to frequently pass short-lived
> fake rtxes to the back-end in order to test its capabilities.  In order
> to reduce the load on GC, it is beneficial to allocate these rtxes on
> stack.
>
> Provide the macro counterparts of gen_* functions required by the next
> patch in series.

I like it.  Richard S. should have the final say as gen* maintainer.

Thanks,
Richard.

> gcc/ChangeLog:
>
> 2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>
>
>         PR target/77918
>         * emit-rtl.c (gen_raw_REG): Use init_raw_REG.
>         (init_raw_REG): New function.
>         * gengenrtl.c (gendef): Emit init_* functions and alloca_*
>         macros.
>         * rtl.c (rtx_alloc_stat_v): Use rtx_init.
>         * rtl.h (rtx_init): New function.
>         (rtx_alloca): New function.
>         (init_raw_REG): New function.
>         (alloca_raw_REG): New macro.
> ---
>  gcc/emit-rtl.c  | 15 +++++++++---
>  gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
>  gcc/rtl.c       |  7 +-----
>  gcc/rtl.h       | 12 ++++++++++
>  4 files changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index a667cdab94e..ecfa3735bba 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
>    set_regno_raw (x, regno, nregs);
>  }
>
> -/* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
> +/* Initialize a REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
>     don't attempt to share with the various global pieces of rtl (such as
>     frame_pointer_rtx).  */
>
>  rtx
> -gen_raw_REG (machine_mode mode, unsigned int regno)
> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
>  {
> -  rtx x = rtx_alloc (REG MEM_STAT_INFO);
>    set_mode_and_regno (x, mode, regno);
>    REG_ATTRS (x) = NULL;
>    ORIGINAL_REGNO (x) = regno;
>    return x;
>  }
>
> +/* Generate a new REG rtx.  */
> +
> +rtx
> +gen_raw_REG (machine_mode mode, unsigned int regno)
> +{
> +  rtx x = rtx_alloc (REG MEM_STAT_INFO);
> +  init_raw_REG (x, mode, regno);
> +  return x;
> +}
> +
>  /* There are some RTL codes that require special attention; the generation
>     functions do the raw handling.  If you add to this list, modify
>     special_rtx in gengenrtl.c as well.  */
> diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
> index 5c78fabfb50..cd314a68a83 100644
> --- a/gcc/gengenrtl.c
> +++ b/gcc/gengenrtl.c
> @@ -231,8 +231,7 @@ genmacro (int idx)
>    puts (")");
>  }
>
> -/* Generate the code for the function to generate RTL whose
> -   format is FORMAT.  */
> +/* Generate the code for functions to generate RTL whose format is FORMAT.  */
>
>  static void
>  gendef (const char *format)
> @@ -240,22 +239,18 @@ gendef (const char *format)
>    const char *p;
>    int i, j;
>
> -  /* Start by writing the definition of the function name and the types
> +  /* Write the definition of the init function name and the types
>       of the arguments.  */
>
> -  printf ("static inline rtx\ngen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> +  puts ("static inline rtx");
> +  printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
>    for (p = format, i = 0; *p != 0; p++)
>      if (*p != '0')
>        printf (",\n\t%sarg%d", type_from_format (*p), i++);
> +  puts (")");
>
> -  puts (" MEM_STAT_DECL)");
> -
> -  /* Now write out the body of the function itself, which allocates
> -     the memory and initializes it.  */
> +  /* Now write out the body of the init function itself.  */
>    puts ("{");
> -  puts ("  rtx rt;");
> -  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);\n");
> -
>    puts ("  PUT_MODE_RAW (rt, mode);");
>
>    for (p = format, i = j = 0; *p ; ++p, ++i)
> @@ -266,16 +261,55 @@ gendef (const char *format)
>      else
>        printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>
> -  puts ("\n  return rt;\n}\n");
> +  puts ("  return rt;\n}\n");
> +
> +  /* Write the definition of the gen function name and the types
> +     of the arguments.  */
> +
> +  puts ("static inline rtx");
> +  printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (",\n\t%sarg%d", type_from_format (*p), i++);
> +  puts (" MEM_STAT_DECL)");
> +
> +  /* Now write out the body of the function itself, which allocates
> +     the memory and initializes it.  */
> +  puts ("{");
> +  puts ("  rtx rt;\n");
> +
> +  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);");
> +  printf ("  init_rtx_fmt_%s (rt, mode", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (", arg%d", i++);
> +  puts (");\n");
> +
> +  puts ("  return rt;\n}\n");
> +
> +  /* Write the definition of gen macro.  */
> +
>    printf ("#define gen_rtx_fmt_%s(c, m", format);
>    for (p = format, i = 0; *p != 0; p++)
>      if (*p != '0')
> -      printf (", p%i",i++);
> -  printf (")\\\n        gen_rtx_fmt_%s_stat (c, m", format);
> +      printf (", arg%d", i++);
> +  printf (") \\\n  gen_rtx_fmt_%s_stat ((c), (m)", format);
>    for (p = format, i = 0; *p != 0; p++)
>      if (*p != '0')
> -      printf (", p%i",i++);
> +      printf (", (arg%d)", i++);
>    printf (" MEM_STAT_INFO)\n\n");
> +
> +  /* Write the definition of alloca macro.  */
> +
> +  printf ("#define alloca_rtx_fmt_%s(c, m", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (", arg%d", i++);
> +  printf (") \\\n  init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (", (arg%d)", i++);
> +  printf (")\n\n");
>  }
>
>  /* Generate the documentation header for files we write.  */
> diff --git a/gcc/rtl.c b/gcc/rtl.c
> index d7b8e9877c3..0be52d38d93 100644
> --- a/gcc/rtl.c
> +++ b/gcc/rtl.c
> @@ -219,12 +219,7 @@ rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra)
>    rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra
>                                    PASS_MEM_STAT);
>
> -  /* We want to clear everything up to the FLD array.  Normally, this
> -     is one int, but we don't want to assume that and it isn't very
> -     portable anyway; this is.  */
> -
> -  memset (rt, 0, RTX_HDR_SIZE);
> -  PUT_CODE (rt, code);
> +  rtx_init (rt, code);
>
>    if (GATHER_STATISTICS)
>      {
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index efb9b3ce40d..cf1547196f2 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -2933,6 +2933,15 @@ extern HOST_WIDE_INT get_stack_check_protect (void);
>
>  /* In rtl.c */
>  extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
> +inline rtx
> +rtx_init (rtx rt, RTX_CODE code)
> +{
> +  memset (rt, 0, RTX_HDR_SIZE);
> +  PUT_CODE (rt, code);
> +  return rt;
> +}
> +#define rtx_alloca(code) \
> +  rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
>  extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
>  #define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
>  #define const_wide_int_alloc(NWORDS)                           \
> @@ -3797,7 +3806,10 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
>  extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
>  extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
>  extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
> +extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
>  extern rtx gen_raw_REG (machine_mode, unsigned int);
> +#define alloca_raw_REG(mode, regno) \
> +  init_raw_REG (rtx_alloca (REG), (mode), (regno))
>  extern rtx gen_rtx_REG (machine_mode, unsigned int);
>  extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
>  extern rtx gen_rtx_MEM (machine_mode, rtx);
> --
> 2.21.0
>

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

* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
  2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
  2019-09-06 11:09   ` Richard Biener
@ 2019-09-06 12:40   ` Richard Sandiford
  2019-09-30 15:00     ` Ilya Leoshkevich
  1 sibling, 1 reply; 23+ messages in thread
From: Richard Sandiford @ 2019-09-06 12:40 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: gcc-patches, richard.guenther, segher, joseph, krebbel, rdapp

Ilya Leoshkevich <iii@linux.ibm.com> writes:
> One of the next patches in series needs to frequently pass short-lived
> fake rtxes to the back-end in order to test its capabilities.  In order
> to reduce the load on GC, it is beneficial to allocate these rtxes on
> stack.
>
> Provide the macro counterparts of gen_* functions required by the next
> patch in series.
>
> gcc/ChangeLog:
>
> 2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>
>
> 	PR target/77918
> 	* emit-rtl.c (gen_raw_REG): Use init_raw_REG.
> 	(init_raw_REG): New function.
> 	* gengenrtl.c (gendef): Emit init_* functions and alloca_*
> 	macros.
> 	* rtl.c (rtx_alloc_stat_v): Use rtx_init.
> 	* rtl.h (rtx_init): New function.
> 	(rtx_alloca): New function.
> 	(init_raw_REG): New function.
> 	(alloca_raw_REG): New macro.
> ---
>  gcc/emit-rtl.c  | 15 +++++++++---
>  gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
>  gcc/rtl.c       |  7 +-----
>  gcc/rtl.h       | 12 ++++++++++
>  4 files changed, 74 insertions(+), 24 deletions(-)
>
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index a667cdab94e..ecfa3735bba 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
>    set_regno_raw (x, regno, nregs);
>  }
>  
> -/* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
> +/* Initialize a REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
>     don't attempt to share with the various global pieces of rtl (such as
>     frame_pointer_rtx).  */
>  
>  rtx
> -gen_raw_REG (machine_mode mode, unsigned int regno)
> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
>  {
> -  rtx x = rtx_alloc (REG MEM_STAT_INFO);
>    set_mode_and_regno (x, mode, regno);
>    REG_ATTRS (x) = NULL;
>    ORIGINAL_REGNO (x) = regno;
>    return x;
>  }
>  
> +/* Generate a new REG rtx.  */
> +
> +rtx
> +gen_raw_REG (machine_mode mode, unsigned int regno)
> +{
> +  rtx x = rtx_alloc (REG MEM_STAT_INFO);
> +  init_raw_REG (x, mode, regno);
> +  return x;
> +}
> +

I think we should keep the gen_raw_REG comment the same (including
the "Make sure..." bit).  The point is to contrast gen_raw_REG with
gen_rtx_REG, which does various bits of sharing.

Maybe the comment above init_raw_REG can instead be just:

/* Initialize a fresh REG rtx with mode MODE and register REGNO.  */

> [...]
> @@ -266,16 +261,55 @@ gendef (const char *format)
>      else
>        printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>  
> -  puts ("\n  return rt;\n}\n");
> +  puts ("  return rt;\n}\n");
> +
> +  /* Write the definition of the gen function name and the types
> +     of the arguments.  */
> +
> +  puts ("static inline rtx");
> +  printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (",\n\t%sarg%d", type_from_format (*p), i++);
> +  puts (" MEM_STAT_DECL)");
> +
> +  /* Now write out the body of the function itself, which allocates
> +     the memory and initializes it.  */
> +  puts ("{");
> +  puts ("  rtx rt;\n");
> +
> +  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);");
> +  printf ("  init_rtx_fmt_%s (rt, mode", format);
> +  for (p = format, i = 0; *p != 0; p++)
> +    if (*p != '0')
> +      printf (", arg%d", i++);
> +  puts (");\n");
> +
> +  puts ("  return rt;\n}\n");

Might as well make it:

  printf ("  return init_rtx_fmt_%s (rt, mode", format);

and drop the separate return, for consistency with the new
alloca code.

OK with those changes, thanks.

Richard

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

* Re: [PATCH v3 3/9] Introduce can_vector_compare_p function
  2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
@ 2019-09-06 12:58   ` Richard Sandiford
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Sandiford @ 2019-09-06 12:58 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: gcc-patches, richard.guenther, segher, joseph, krebbel, rdapp

Ilya Leoshkevich <iii@linux.ibm.com> writes:
> @@ -329,6 +332,34 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
>    return false;
>  }
>  
> +/* Return TRUE iff vcond_optab/vcondu_optab support the given tree
> +   comparison.  */

Nit: better to use "true" rather than "TRUE" in modern comments;
TRUE is a hold-over from C90 days.

> +
> +static bool
> +vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
> +{
> +  enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
> +  if (rcode == LAST_AND_UNUSED_RTX_CODE)
> +    /* This may happen, for example, if code == SSA_NAME, in which case we
> +       cannot be certain whether a vector insn is available.  */
> +    return false;

IMO expand_vec_cond_expr_p should exit early for SSA names before
calling this function (but after checking get_vcond_mask_icode).
Asserting for a comparison seems reasonable here.

> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index cdd07f3e53f..479789570a9 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
>    return 0;
>  }
>  
> +/* Return whether back-end can emit a vector comparison insn(s) using a give> +   CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
> +   in order to achieve a PURPOSE.  */

Maybe:

/* Return whether the backend can emit a vector comparison for code CODE,
   comparing operands of mode CMP_OP_MODE and producing a result
   with VALUE_MODE.  */

> +
> +bool
> +can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
> +		      machine_mode cmp_op_mode,
> +		      enum can_vector_compare_purpose purpose)

I think we should leave out the purpose argument until it's needed.
(Sorry if someone else said the opposite, can't remember now.)

Maybe can_vcond_compare_p would be more consistent with the other
function names in the patch.

Thanks,
Richard

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

* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
  2019-09-06 11:07   ` Richard Biener
@ 2019-09-06 15:45     ` Ilya Leoshkevich
  2019-09-09  8:43       ` Richard Biener
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-06 15:45 UTC (permalink / raw)
  To: Richard Biener
  Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
	Joseph S. Myers, Andreas Krebbel, Robin Dapp

> Am 06.09.2019 um 13:07 schrieb Richard Biener <richard.guenther@gmail.com>:
> 
> On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>> 
>> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
>> and introduces a temporary if this could happen, for example, generating
>> 
>>  _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
>>  _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
>> 
>> from GENERIC
>> 
>>  VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
>>                  { -1, -1, -1, -1 } ,
>>                  { 0, 0, 0, 0 } >
>> 
>> This is not necessary and makes the resulting GIMPLE harder to analyze.
>> In particular, one of the next patches in series needs to get to
>> VEC_COND_EXPR's comparison code, which is not possible when a temporary
>> is introduced.
>> 
>> This patch takes special care to avoid introducing trapping comparisons
>> in GIMPLE_COND.  They are not allowed, because they would require 3
>> outgoing edges (then, else and EH), which is awkward to say the least.
>> Therefore, computations of such conditions should live in their own basic
>> blocks.
> 
> Comments inline (thanks for the work btw)
> 
>> #endif /* GCC_GIMPLE_EXPR_H */
>> diff --git a/gcc/gimple.c b/gcc/gimple.c
>> index 633ef512a19..fd14fbec15e 100644
>> --- a/gcc/gimple.c
>> +++ b/gcc/gimple.c
>> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
>>       op = gimple_assign_rhs_code (s);
>>       if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
>>        div = gimple_assign_rhs2 (s);
>> +      else if (op == COND_EXPR || op == VEC_COND_EXPR)
>> +       op = TREE_CODE (gimple_assign_rhs1 (s));
> 
> I think this is not correct since we can have
> 
> int i = fp > 1. ? intval1 : intval2
> 
> and thus FLOAT_TYPE_P (t)  is wrong.  You need to do
> 
>  t = TREE_TYPE (op);
> 
> as well I think.

Doesn't this mean there is a problem with the existing logic too? If `s`
is

    int i = fp > 1.;

then

    t = gimple_expr_type (s);

would give us BOOLEAN_TYPE instead of REAL_TYPE.


Also, the new logic will probably be a bit more complicated, since I
will first have to do:

    tree cond = gimple_assign_rhs1 (s);

then see if `cond` is not e.g. an SSA_NAME, but rather a tcc_comparison,
and only then

    t = TREE_TYPE (TREE_OPERAND (cond, 0))

So I'd rather send a new version before merging this :-)

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

* Re: [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap
  2019-09-06 15:45     ` Ilya Leoshkevich
@ 2019-09-09  8:43       ` Richard Biener
  0 siblings, 0 replies; 23+ messages in thread
From: Richard Biener @ 2019-09-09  8:43 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: GCC Patches, Richard Sandiford, Segher Boessenkool,
	Joseph S. Myers, Andreas Krebbel, Robin Dapp

On Fri, Sep 6, 2019 at 5:45 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> > Am 06.09.2019 um 13:07 schrieb Richard Biener <richard.guenther@gmail.com>:
> >
> > On Thu, Sep 5, 2019 at 1:10 PM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
> >>
> >> Right now gimplifier does not allow VEC_COND_EXPR's condition to trap
> >> and introduces a temporary if this could happen, for example, generating
> >>
> >>  _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
> >>  _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
> >>
> >> from GENERIC
> >>
> >>  VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
> >>                  { -1, -1, -1, -1 } ,
> >>                  { 0, 0, 0, 0 } >
> >>
> >> This is not necessary and makes the resulting GIMPLE harder to analyze.
> >> In particular, one of the next patches in series needs to get to
> >> VEC_COND_EXPR's comparison code, which is not possible when a temporary
> >> is introduced.
> >>
> >> This patch takes special care to avoid introducing trapping comparisons
> >> in GIMPLE_COND.  They are not allowed, because they would require 3
> >> outgoing edges (then, else and EH), which is awkward to say the least.
> >> Therefore, computations of such conditions should live in their own basic
> >> blocks.
> >
> > Comments inline (thanks for the work btw)
> >
> >> #endif /* GCC_GIMPLE_EXPR_H */
> >> diff --git a/gcc/gimple.c b/gcc/gimple.c
> >> index 633ef512a19..fd14fbec15e 100644
> >> --- a/gcc/gimple.c
> >> +++ b/gcc/gimple.c
> >> @@ -2144,6 +2144,8 @@ gimple_could_trap_p_1 (gimple *s, bool include_mem, bool include_stores)
> >>       op = gimple_assign_rhs_code (s);
> >>       if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
> >>        div = gimple_assign_rhs2 (s);
> >> +      else if (op == COND_EXPR || op == VEC_COND_EXPR)
> >> +       op = TREE_CODE (gimple_assign_rhs1 (s));
> >
> > I think this is not correct since we can have
> >
> > int i = fp > 1. ? intval1 : intval2
> >
> > and thus FLOAT_TYPE_P (t)  is wrong.  You need to do
> >
> >  t = TREE_TYPE (op);
> >
> > as well I think.
>
> Doesn't this mean there is a problem with the existing logic too? If `s`
> is
>
>     int i = fp > 1.;
>
> then
>
>     t = gimple_expr_type (s);
>
> would give us BOOLEAN_TYPE instead of REAL_TYPE.

Yeah, that looks broken as well.

>
> Also, the new logic will probably be a bit more complicated, since I
> will first have to do:
>
>     tree cond = gimple_assign_rhs1 (s);
>
> then see if `cond` is not e.g. an SSA_NAME, but rather a tcc_comparison,
> and only then
>
>     t = TREE_TYPE (TREE_OPERAND (cond, 0))
>
> So I'd rather send a new version before merging this :-)

Fine with me ;)

Richard.

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

* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
  2019-09-06 10:34   ` Segher Boessenkool
@ 2019-09-30 13:36     ` Ilya Leoshkevich
  2019-10-01  0:24       ` Segher Boessenkool
  0 siblings, 1 reply; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-30 13:36 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: GCC Patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp

> Am 06.09.2019 um 12:34 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> 
> Hi Ilya,
> 
> On Thu, Sep 05, 2019 at 01:10:14PM +0200, Ilya Leoshkevich wrote:
>> 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 more restrictive operator predicate in
>> vcond<V_HW:mode><V_HW2:mode>.
> 
>> +(define_predicate "vcond_comparison_operator"
>> +  (match_operand 0 "comparison_operator")
>> +{
>> +  if (!HONOR_NANS (GET_MODE (XEXP (op, 0)))
>> +      && !HONOR_NANS (GET_MODE (XEXP (op, 1))))
>> +    return true;
>> +  switch (GET_CODE (op))
>> +    {
>> +    case LE:
>> +    case LT:
>> +    case GE:
>> +    case GT:
>> +    case LTGT:
>> +      /* Signaling vector comparisons are supported only on z14+.  */
>> +      return TARGET_Z14;
>> +    default:
>> +      return true;
>> +    }
>> +})
> 
> Should you handle -fsignaling-nans here as well?

Do you mean disabling vectorisation of LE/LT/GE/GT/LTGT when
-fsignaling-nans is in effect?  This makes sense to me.  I could do that
here, but wouldn't common code (e.g. expand_vec_cond_expr_p) be a better
place?

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

* Re: [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode>
  2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
@ 2019-09-30 14:41   ` Andreas Krebbel
  0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:41 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 05.09.19 13:10, Ilya Leoshkevich wrote:
> 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>
> 
> 	PR target/77918
> 	* config/s390/vector.md (vec_unordered<mode>): Call
> 	gen_vec_ordered<mode>.

Ok. Thanks!

Andreas

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

* Re: [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders
  2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
@ 2019-09-30 14:50   ` Andreas Krebbel
  0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:50 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 05.09.19 13:10, Ilya Leoshkevich wrote:
> 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>
> 
> 	PR target/77918
> 	* 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.

VEC_CODE_WITH_COMPLEX_EXPAND is pretty long and doesn't mention that it is about compare operators.
Perhaps VEC_CMP_EXPAND or something like this? Btw. could you please mention the new iterator in the
changelog.

Ok.

Andreas

> ---
>  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 24784266848..f36e12affd2 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 1b66b8be61f..a093ae5c565 100644
> --- a/gcc/config/s390/vector.md
> +++ b/gcc/config/s390/vector.md
> @@ -1507,22 +1507,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")
> @@ -1535,24 +1519,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")))
> @@ -1563,45 +1531,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 ();
>  
> 

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

* Re: [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF
  2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
@ 2019-09-30 14:51   ` Andreas Krebbel
  0 siblings, 0 replies; 23+ messages in thread
From: Andreas Krebbel @ 2019-09-30 14:51 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 05.09.19 13:10, Ilya Leoshkevich wrote:
> 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>
> 
> 	PR target/77918
> 	* config/s390/vector.md (vcondv1tiv1tf): New variant of
> 	vcond$a$b expander.

Couldn't you just add V1TI to V_HW and V_HW2 instead?

Andreas

> ---
>  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 d7a266c5605..ca5ec0dd3b0 100644
> --- a/gcc/config/s390/vector.md
> +++ b/gcc/config/s390/vector.md
> @@ -649,6 +649,21 @@
>    DONE;
>  })
>  
> +(define_expand "vcondv1tiv1tf"
> +  [(set (match_operand:V1TI 0 "register_operand" "")
> +	(if_then_else:V1TI
> +	 (match_operator 3 "vcond_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
> 

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

* Re: [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_*
  2019-09-06 12:40   ` Richard Sandiford
@ 2019-09-30 15:00     ` Ilya Leoshkevich
  0 siblings, 0 replies; 23+ messages in thread
From: Ilya Leoshkevich @ 2019-09-30 15:00 UTC (permalink / raw)
  To: Richard Sandiford
  Cc: GCC Patches, Richard Biener, segher, joseph, krebbel, rdapp

> Am 06.09.2019 um 14:40 schrieb Richard Sandiford <richard.sandiford@arm.com>:
> 
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>> One of the next patches in series needs to frequently pass short-lived
>> fake rtxes to the back-end in order to test its capabilities.  In order
>> to reduce the load on GC, it is beneficial to allocate these rtxes on
>> stack.
>> 
>> Provide the macro counterparts of gen_* functions required by the next
>> patch in series.
>> 
>> gcc/ChangeLog:
>> 
>> 2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>
>> 
>> 	PR target/77918
>> 	* emit-rtl.c (gen_raw_REG): Use init_raw_REG.
>> 	(init_raw_REG): New function.
>> 	* gengenrtl.c (gendef): Emit init_* functions and alloca_*
>> 	macros.
>> 	* rtl.c (rtx_alloc_stat_v): Use rtx_init.
>> 	* rtl.h (rtx_init): New function.
>> 	(rtx_alloca): New function.
>> 	(init_raw_REG): New function.
>> 	(alloca_raw_REG): New macro.
>> ---
>> gcc/emit-rtl.c  | 15 +++++++++---
>> gcc/gengenrtl.c | 64 +++++++++++++++++++++++++++++++++++++------------
>> gcc/rtl.c       |  7 +-----
>> gcc/rtl.h       | 12 ++++++++++
>> 4 files changed, 74 insertions(+), 24 deletions(-)
>> 
>> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
>> index a667cdab94e..ecfa3735bba 100644
>> --- a/gcc/emit-rtl.c
>> +++ b/gcc/emit-rtl.c
>> @@ -466,20 +466,29 @@ set_mode_and_regno (rtx x, machine_mode mode, unsigned int regno)
>>   set_regno_raw (x, regno, nregs);
>> }
>> 
>> -/* Generate a new REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
>> +/* Initialize a REG rtx.  Make sure ORIGINAL_REGNO is set properly, and
>>    don't attempt to share with the various global pieces of rtl (such as
>>    frame_pointer_rtx).  */
>> 
>> rtx
>> -gen_raw_REG (machine_mode mode, unsigned int regno)
>> +init_raw_REG (rtx x, machine_mode mode, unsigned int regno)
>> {
>> -  rtx x = rtx_alloc (REG MEM_STAT_INFO);
>>   set_mode_and_regno (x, mode, regno);
>>   REG_ATTRS (x) = NULL;
>>   ORIGINAL_REGNO (x) = regno;
>>   return x;
>> }
>> 
>> +/* Generate a new REG rtx.  */
>> +
>> +rtx
>> +gen_raw_REG (machine_mode mode, unsigned int regno)
>> +{
>> +  rtx x = rtx_alloc (REG MEM_STAT_INFO);
>> +  init_raw_REG (x, mode, regno);
>> +  return x;
>> +}
>> +
> 
> I think we should keep the gen_raw_REG comment the same (including
> the "Make sure..." bit).  The point is to contrast gen_raw_REG with
> gen_rtx_REG, which does various bits of sharing.
> 
> Maybe the comment above init_raw_REG can instead be just:
> 
> /* Initialize a fresh REG rtx with mode MODE and register REGNO.  */
> 
>> [...]
>> @@ -266,16 +261,55 @@ gendef (const char *format)
>>     else
>>       printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
>> 
>> -  puts ("\n  return rt;\n}\n");
>> +  puts ("  return rt;\n}\n");
>> +
>> +  /* Write the definition of the gen function name and the types
>> +     of the arguments.  */
>> +
>> +  puts ("static inline rtx");
>> +  printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
>> +  for (p = format, i = 0; *p != 0; p++)
>> +    if (*p != '0')
>> +      printf (",\n\t%sarg%d", type_from_format (*p), i++);
>> +  puts (" MEM_STAT_DECL)");
>> +
>> +  /* Now write out the body of the function itself, which allocates
>> +     the memory and initializes it.  */
>> +  puts ("{");
>> +  puts ("  rtx rt;\n");
>> +
>> +  puts ("  rt = rtx_alloc (code PASS_MEM_STAT);");
>> +  printf ("  init_rtx_fmt_%s (rt, mode", format);
>> +  for (p = format, i = 0; *p != 0; p++)
>> +    if (*p != '0')
>> +      printf (", arg%d", i++);
>> +  puts (");\n");
>> +
>> +  puts ("  return rt;\n}\n");
> 
> Might as well make it:
> 
>  printf ("  return init_rtx_fmt_%s (rt, mode", format);
> 
> and drop the separate return, for consistency with the new
> alloca code.
> 
> OK with those changes, thanks.

I've made the changes and committed the patch:

https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276303

Thanks for the review!

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

* Re: [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13
  2019-09-30 13:36     ` Ilya Leoshkevich
@ 2019-10-01  0:24       ` Segher Boessenkool
  0 siblings, 0 replies; 23+ messages in thread
From: Segher Boessenkool @ 2019-10-01  0:24 UTC (permalink / raw)
  To: Ilya Leoshkevich
  Cc: GCC Patches, richard.guenther, richard.sandiford, joseph, krebbel, rdapp

On Mon, Sep 30, 2019 at 03:36:41PM +0200, Ilya Leoshkevich wrote:
> > Am 06.09.2019 um 12:34 schrieb Segher Boessenkool <segher@kernel.crashing.org>:
> > Should you handle -fsignaling-nans here as well?
> 
> Do you mean disabling vectorisation of LE/LT/GE/GT/LTGT when
> -fsignaling-nans is in effect?  This makes sense to me.

I meant it sounds like you need to do *something* more than the generic
code does, here.

> I could do that
> here, but wouldn't common code (e.g. expand_vec_cond_expr_p) be a better
> place?

If it can be done there, all the better, sure.

Anyway, this is a separate issue, don't let me distract you :-)


Segher

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

end of thread, other threads:[~2019-10-01  0:24 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-05 11:10 [PATCH v3 0/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:10 ` [PATCH v3 1/9] Allow COND_EXPR and VEC_COND_EXPR condtions to trap Ilya Leoshkevich
2019-09-06 11:07   ` Richard Biener
2019-09-06 15:45     ` Ilya Leoshkevich
2019-09-09  8:43       ` Richard Biener
2019-09-05 11:11 ` [PATCH v3 5/9] S/390: Implement vcond expander for V1TI,V1TF Ilya Leoshkevich
2019-09-30 14:51   ` Andreas Krebbel
2019-09-05 11:11 ` [PATCH v3 6/9] S/390: Remove code duplication in vec_unordered<mode> Ilya Leoshkevich
2019-09-30 14:41   ` Andreas Krebbel
2019-09-05 11:11 ` [PATCH v3 4/9] S/390: Do not use signaling vector comparisons on z13 Ilya Leoshkevich
2019-09-06 10:34   ` Segher Boessenkool
2019-09-30 13:36     ` Ilya Leoshkevich
2019-10-01  0:24       ` Segher Boessenkool
2019-09-05 11:11 ` [PATCH v3 2/9] Introduce rtx_alloca, alloca_raw_REG and alloca_rtx_fmt_* Ilya Leoshkevich
2019-09-06 11:09   ` Richard Biener
2019-09-06 12:40   ` Richard Sandiford
2019-09-30 15:00     ` Ilya Leoshkevich
2019-09-05 11:11 ` [PATCH v3 3/9] Introduce can_vector_compare_p function Ilya Leoshkevich
2019-09-06 12:58   ` Richard Sandiford
2019-09-05 11:12 ` [PATCH v3 8/9] S/390: Use signaling FP comparison instructions Ilya Leoshkevich
2019-09-05 11:12 ` [PATCH v3 7/9] S/390: Remove code duplication in vec_* comparison expanders Ilya Leoshkevich
2019-09-30 14:50   ` Andreas Krebbel
2019-09-05 11:12 ` [PATCH v3 9/9] S/390: Test signaling FP comparison instructions Ilya Leoshkevich

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).