public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible
@ 2020-11-03 21:36 Ilya Leoshkevich
  2020-11-03 21:36 ` [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs Ilya Leoshkevich
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-03 21:36 UTC (permalink / raw)
  To: krebbel; +Cc: gcc-patches, Ilya Leoshkevich

Bootstrapped and regtested on s390x-redhat-linux with --with-mode=zarch
--with-arch=z14.  Ok for master?

This patch series implements storing long doubles in vector registers
on z14+.  Patches 1 and 2 are initial cleanups.  Patch 3 is the actual
implementation, patch 4 adds tests.

Ilya Leoshkevich (4):
  IBM Z: Remove unused RRe and RXe mode_attrs
  IBM Z: Unhardcode NR_C_MODES
  IBM Z: Store long doubles in vector registers when possible
  IBM Z: Test long doubles in vector registers

 gcc/config/s390/s390-modes.def                |   5 +-
 gcc/config/s390/s390-protos.h                 |   1 +
 gcc/config/s390/s390.c                        |  67 ++-
 gcc/config/s390/s390.h                        |  28 ++
 gcc/config/s390/s390.md                       | 214 ++++++----
 gcc/config/s390/s390.opt                      |  11 +
 gcc/config/s390/vector.md                     | 382 ++++++++++++++++--
 gcc/config/s390/vx-builtins.md                |  38 +-
 .../zvector/long-double-callee-abi-scan.c     |  20 +
 .../s390/zvector/long-double-caller-abi-run.c |   4 +
 .../zvector/long-double-caller-abi-scan.c     |  13 +
 .../s390/zvector/long-double-copysign-run.c   |  14 +
 .../s390/zvector/long-double-copysign-scan.c  |  11 +
 .../s390/zvector/long-double-fprx2-constant.c |  11 +
 .../zvector/long-double-from-double-run.c     |  12 +
 .../zvector/long-double-from-double-scan.c    |   9 +
 .../s390/zvector/long-double-from-float-run.c |  12 +
 .../zvector/long-double-from-float-scan.c     |  10 +
 .../s390/zvector/long-double-from-i16-run.c   |  12 +
 .../s390/zvector/long-double-from-i16-scan.c  |  11 +
 .../s390/zvector/long-double-from-i32-run.c   |  12 +
 .../s390/zvector/long-double-from-i32-scan.c  |  11 +
 .../s390/zvector/long-double-from-i64-run.c   |  12 +
 .../s390/zvector/long-double-from-i64-scan.c  |  11 +
 .../s390/zvector/long-double-from-i8-run.c    |  12 +
 .../s390/zvector/long-double-from-i8-scan.c   |  11 +
 .../s390/zvector/long-double-from-u16-run.c   |  12 +
 .../s390/zvector/long-double-from-u16-scan.c  |  11 +
 .../s390/zvector/long-double-from-u32-run.c   |  12 +
 .../s390/zvector/long-double-from-u32-scan.c  |  11 +
 .../s390/zvector/long-double-from-u64-run.c   |  12 +
 .../s390/zvector/long-double-from-u64-scan.c  |  11 +
 .../s390/zvector/long-double-from-u8-run.c    |  12 +
 .../s390/zvector/long-double-from-u8-scan.c   |  11 +
 .../s390/zvector/long-double-to-double-run.c  |  12 +
 .../s390/zvector/long-double-to-double-scan.c |   9 +
 .../s390/zvector/long-double-to-float-run.c   |  12 +
 .../s390/zvector/long-double-to-float-scan.c  |  10 +
 .../s390/zvector/long-double-to-i16-run.c     |  12 +
 .../s390/zvector/long-double-to-i16-scan.c    |  11 +
 .../s390/zvector/long-double-to-i32-run.c     |  12 +
 .../s390/zvector/long-double-to-i32-scan.c    |  11 +
 .../s390/zvector/long-double-to-i64-run.c     |  12 +
 .../s390/zvector/long-double-to-i64-scan.c    |  13 +
 .../s390/zvector/long-double-to-i8-run.c      |  12 +
 .../s390/zvector/long-double-to-i8-scan.c     |  11 +
 .../s390/zvector/long-double-to-u16-run.c     |  13 +
 .../s390/zvector/long-double-to-u16-scan.c    |  11 +
 .../s390/zvector/long-double-to-u32-run.c     |  13 +
 .../s390/zvector/long-double-to-u32-scan.c    |  11 +
 .../s390/zvector/long-double-to-u64-run.c     |  13 +
 .../s390/zvector/long-double-to-u64-scan.c    |  11 +
 .../s390/zvector/long-double-to-u8-run.c      |  13 +
 .../s390/zvector/long-double-to-u8-scan.c     |  11 +
 .../s390/zvector/long-double-vec-duplicate.c  |  13 +
 .../gcc.target/s390/zvector/long-double-wf.h  |  60 +++
 .../s390/zvector/long-double-wfaxb-run.c      |  11 +
 .../s390/zvector/long-double-wfaxb-scan.c     |  10 +
 .../s390/zvector/long-double-wfaxb.c          |   8 +
 .../s390/zvector/long-double-wfcxb-0001.c     |  10 +
 .../s390/zvector/long-double-wfcxb-0111.c     |  10 +
 .../s390/zvector/long-double-wfcxb-1011.c     |  10 +
 .../s390/zvector/long-double-wfcxb-1101.c     |  10 +
 .../s390/zvector/long-double-wfdxb-run.c      |  11 +
 .../s390/zvector/long-double-wfdxb-scan.c     |  10 +
 .../s390/zvector/long-double-wfdxb.c          |   8 +
 .../s390/zvector/long-double-wfixb.c          |   8 +
 .../s390/zvector/long-double-wfkxb-0111.c     |  10 +
 .../s390/zvector/long-double-wfkxb-1011.c     |  10 +
 .../s390/zvector/long-double-wfkxb-1101.c     |  10 +
 .../s390/zvector/long-double-wflcxb.c         |   8 +
 .../s390/zvector/long-double-wflpxb.c         |   8 +
 .../s390/zvector/long-double-wfmaxb-2.c       |  24 ++
 .../s390/zvector/long-double-wfmaxb-3.c       |  14 +
 .../zvector/long-double-wfmaxb-disabled.c     |   9 +
 .../s390/zvector/long-double-wfmaxb.c         |   8 +
 .../zvector/long-double-wfmsxb-disabled.c     |   9 +
 .../s390/zvector/long-double-wfmsxb.c         |   8 +
 .../s390/zvector/long-double-wfmxb.c          |   8 +
 .../zvector/long-double-wfnmaxb-disabled.c    |  10 +
 .../s390/zvector/long-double-wfnmaxb.c        |   8 +
 .../zvector/long-double-wfnmsxb-disabled.c    |  10 +
 .../s390/zvector/long-double-wfnmsxb.c        |   8 +
 .../s390/zvector/long-double-wfsqxb.c         |   8 +
 .../s390/zvector/long-double-wfsxb-1.c        |  21 +
 .../s390/zvector/long-double-wfsxb.c          |   8 +
 .../s390/zvector/long-double-wftcixb-1.c      |  15 +
 .../s390/zvector/long-double-wftcixb.c        |   8 +
 88 files changed, 1534 insertions(+), 146 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c

-- 
2.25.4


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

* [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs
  2020-11-03 21:36 [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
@ 2020-11-03 21:36 ` Ilya Leoshkevich
  2020-11-04 17:14   ` Andreas Krebbel
  2020-11-03 21:45 ` [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES Ilya Leoshkevich
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-03 21:36 UTC (permalink / raw)
  To: krebbel; +Cc: gcc-patches, Ilya Leoshkevich

gcc/ChangeLog:

2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/s390.md (RRe): Remove.
	(RXe): Remove.
---
 gcc/config/s390/s390.md | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 18edea1ce47..050374980ae 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -721,11 +721,6 @@ (define_mode_attr xde [(TF "x") (DF "d") (SF "e") (TD "x") (DD "d") (SD "e") (V4
 ;; SDmode.
 (define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")])
 
-;; In FP templates, "<RRe>" will expand to "RRE" in TFmode and "RR" otherwise.
-;; Likewise for "<RXe>".
-(define_mode_attr RRe [(TF "RRE") (DF "RR") (SF "RR")])
-(define_mode_attr RXe [(TF "RXE") (DF "RX") (SF "RX")])
-
 ;; The decimal floating point variants of add, sub, div and mul support 3
 ;; fp register operands.  The following attributes allow to merge the bfp and
 ;; dfp variants in a single insn definition.
-- 
2.25.4


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

* [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES
  2020-11-03 21:36 [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
  2020-11-03 21:36 ` [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs Ilya Leoshkevich
@ 2020-11-03 21:45 ` Ilya Leoshkevich
  2020-11-04 17:14   ` Andreas Krebbel
  2020-11-03 21:45 ` [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
  2020-11-03 21:46 ` [PATCH 4/4] IBM Z: Test long doubles in vector registers Ilya Leoshkevich
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-03 21:45 UTC (permalink / raw)
  To: krebbel; +Cc: gcc-patches, Ilya Leoshkevich

gcc/ChangeLog:

2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/s390.c (NR_C_MODES): Unhardcode.
	(s390_alloc_pool): Use size_t for iterating from 0 to
	NR_C_MODES.
	(s390_add_constant): Likewise.
	(s390_find_constant): Likewise.
	(s390_dump_pool): Likewise.
	(s390_free_pool): Likewise.
---
 gcc/config/s390/s390.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3c3feb2769b..b8961a315aa 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -8621,8 +8621,7 @@ replace_constant_pool_ref (rtx_insn *insn, rtx ref, rtx offset)
 /* We keep a list of constants which we have to add to internal
    constant tables in the middle of large functions.  */
 
-#define NR_C_MODES 32
-machine_mode constant_modes[NR_C_MODES] =
+static machine_mode constant_modes[] =
 {
   TFmode, TImode, TDmode,
   V16QImode, V8HImode, V4SImode, V2DImode, V1TImode,
@@ -8636,6 +8635,7 @@ machine_mode constant_modes[NR_C_MODES] =
   QImode,
   V1QImode
 };
+#define NR_C_MODES (sizeof (constant_modes) / sizeof (constant_modes[0]))
 
 struct constant
 {
@@ -8664,7 +8664,7 @@ static struct constant_pool *
 s390_alloc_pool (void)
 {
   struct constant_pool *pool;
-  int i;
+  size_t i;
 
   pool = (struct constant_pool *) xmalloc (sizeof *pool);
   pool->next = NULL;
@@ -8743,7 +8743,7 @@ static void
 s390_add_constant (struct constant_pool *pool, rtx val, machine_mode mode)
 {
   struct constant *c;
-  int i;
+  size_t i;
 
   for (i = 0; i < NR_C_MODES; i++)
     if (constant_modes[i] == mode)
@@ -8788,7 +8788,7 @@ s390_find_constant (struct constant_pool *pool, rtx val,
 		    machine_mode mode)
 {
   struct constant *c;
-  int i;
+  size_t i;
 
   for (i = 0; i < NR_C_MODES; i++)
     if (constant_modes[i] == mode)
@@ -8895,7 +8895,7 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
 {
   struct constant *c;
   rtx_insn *insn = pool->pool_insn;
-  int i;
+  size_t i;
 
   /* Switch to rodata section.  */
   insn = emit_insn_after (gen_pool_section_start (), insn);
@@ -8966,7 +8966,7 @@ static void
 s390_free_pool (struct constant_pool *pool)
 {
   struct constant *c, *next;
-  int i;
+  size_t i;
 
   for (i = 0; i < NR_C_MODES; i++)
     for (c = pool->constants[i]; c; c = next)
-- 
2.25.4


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

* [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible
  2020-11-03 21:36 [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
  2020-11-03 21:36 ` [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs Ilya Leoshkevich
  2020-11-03 21:45 ` [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES Ilya Leoshkevich
@ 2020-11-03 21:45 ` Ilya Leoshkevich
  2020-11-04 17:16   ` Andreas Krebbel
  2020-11-03 21:46 ` [PATCH 4/4] IBM Z: Test long doubles in vector registers Ilya Leoshkevich
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-03 21:45 UTC (permalink / raw)
  To: krebbel; +Cc: gcc-patches, Ilya Leoshkevich

On z14+, there are instructions for working with 128-bit floats (long
doubles) in vector registers.  It's beneficial to use them instead of
instructions that operate on floating point register pairs, because it
allows to store 4 times more data in registers at a time, relieveing
register pressure.  The performance of new instructions is almost the
same.

Implement by storing TFmode values in vector registers on z14+.  Since
not all operations are available with the new instructions, keep the old
ones using the new FPRX2 mode, and convert between it and TFmode when
necessary (this is called "forwarder" expanders below).  Change the
existing TFmode expanders to call either new- or old-style ones
depending on whether we are on z14+ or older machines ("dispatcher"
expanders).

gcc/ChangeLog:

2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>

	* config/s390/s390-modes.def (FPRX2): New mode.
	* config/s390/s390-protos.h (s390_fma_allowed_p): New function.
	* config/s390/s390.c (s390_fma_allowed_p): Likewise.
	(s390_build_signbit_mask): Support 128-bit masks.
	(print_operand): Support printing the second word of a TFmode
	operand as vector register.
	(constant_modes): Add FPRX2mode.
	(s390_class_max_nregs): Return 1 for TFmode on z14+.
	(s390_is_fpr128): New function.
	(s390_is_vr128): Likewise.
	(s390_can_change_mode_class): Use s390_is_fpr128 and
	s390_is_vr128 in order to determine whether mode refers to a FPR
	pair or to a VR.
	* config/s390/s390.h (EXPAND_MOVTF): New macro.
	(EXPAND_TF): Likewise.
	* config/s390/s390.md (PFPO_OP_TYPE_FPRX2): PFPO_OP_TYPE_TF
	alias.
	(ALL): Add FPRX2.
	(FP_ALL): Add FPRX2 for z14+, restrict TFmode to z13-.
	(FP): Likewise.
	(FP_ANYTF): New mode iterator.
	(BFP): Add FPRX2 for z14+, restrict TFmode to z13-.
	(TD_TF): Likewise.
	(xde): Add FPRX2.
	(nBFP): Likewise.
	(nDFP): Likewise.
	(DSF): Likewise.
	(DFDI): Likewise.
	(SFSI): Likewise.
	(DF): Likewise.
	(SF): Likewise.
	(fT0): Likewise.
	(bt): Likewise.
	(_d): Likewise.
	(HALF_TMODE): Likewise.
	(tf_fpr): New mode_attr.
	(type): New mode_attr.
	(*cmp<mode>_ccz_0): Use type instead of mode with fsimp.
	(*cmp<mode>_ccs_0_fastmath): Likewise.
	(*cmptf_ccs): New pattern for wfcxb.
	(*cmptf_ccsfps): New pattern for wfkxb.
	(mov<mode>): Rename to mov<mode><tf_fpr>.
	(signbit<mode>2): Rename to signbit<mode>2<tf_fpr>.
	(isinf<mode>2): Renamed to isinf<mode>2<tf_fpr>.
	(*TDC_insn_<mode>): Use type instead of mode with fsimp.
	(fixuns_trunc<FP:mode><GPR:mode>2): Rename to
	fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>.
	(fix_trunctf<mode>2): Rename to fix_trunctf<mode>2_fpr.
	(floatdi<mode>2): Rename to floatdi<mode>2<tf_fpr>, use type
	instead of mode with itof.
	(floatsi<mode>2): Rename to floatsi<mode>2<tf_fpr>, use type
	instead of mode with itof.
	(*floatuns<GPR:mode><FP:mode>2): Use type instead of mode for
	itof.
	(floatuns<GPR:mode><FP:mode>2): Rename to
	floatuns<GPR:mode><FP:mode>2<tf_fpr>.
	(trunctf<mode>2): Rename to trunctf<mode>2_fpr, use type instead
	of mode with fsimp.
	(extend<DSF:mode><BFP:mode>2): Rename to
	extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>.
	(<FPINT:fpint_name><BFP:mode>2): Rename to
	<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>, use type instead of
	mode with fsimp.
	(rint<BFP:mode>2): Rename to rint<BFP:mode>2<BFP:tf_fpr>, use
	type instead of mode with fsimp.
	(<FPINT:fpint_name><DFP:mode>2): Use type instead of mode for
	fsimp.
	(rint<DFP:mode>2): Likewise.
	(trunc<BFP:mode><DFP_ALL:mode>2): Rename to
	trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
	(trunc<DFP_ALL:mode><BFP:mode>2): Rename to
	trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
	(extend<BFP:mode><DFP_ALL:mode>2): Rename to
	extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
	(extend<DFP_ALL:mode><BFP:mode>2): Rename to
	extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
	(add<mode>3): Rename to add<mode>3<tf_fpr>, use type instead of
	mode with fsimp.
	(*add<mode>3_cc): Use type instead of mode with fsimp.
	(*add<mode>3_cconly): Likewise.
	(sub<mode>3): Rename to sub<mode>3<tf_fpr>, use type instead of
	mode with fsimp.
	(*sub<mode>3_cc): Use type instead of mode with fsimp.
	(*sub<mode>3_cconly): Likewise.
	(mul<mode>3): Rename to mul<mode>3<tf_fpr>, use type instead of
	mode with fsimp.
	(fma<mode>4): Restrict using s390_fma_allowed_p.
	(fms<mode>4): Restrict using s390_fma_allowed_p.
	(div<mode>3): Rename to div<mode>3<tf_fpr>, use type instead of
	mode with fdiv.
	(neg<mode>2): Rename to neg<mode>2<tf_fpr>.
	(*neg<mode>2_cc): Use type instead of mode with fsimp.
	(*neg<mode>2_cconly): Likewise.
	(*neg<mode>2_nocc): Likewise.
	(*neg<mode>2): Likeiwse.
	(abs<mode>2): Rename to abs<mode>2<tf_fpr>, use type instead of
	mode with fdiv.
	(*abs<mode>2_cc): Use type instead of mode with fsimp.
	(*abs<mode>2_cconly): Likewise.
	(*abs<mode>2_nocc): Likewise.
	(*abs<mode>2): Likewise.
	(*negabs<mode>2_cc): Likewise.
	(*negabs<mode>2_cconly): Likewise.
	(*negabs<mode>2_nocc): Likewise.
	(*negabs<mode>2): Likewise.
	(sqrt<mode>2): Rename to sqrt<mode>2<tf_fpr>, use type instead
	of mode with fsqrt.
	(cbranch<mode>4): Use FP_ANYTF instead of FP.
	(copysign<mode>3): Rename to copysign<mode>3<tf_fpr>, use type
	instead of mode with fsimp.
	* config/s390/s390.opt (flag_vx_long_double_fma): New
	undocumented option.
	* config/s390/vector.md (V_HW): Add TF for z14+.
	(V_HW2): Likewise.
	(VFT): Likewise.
	(VF_HW): Likewise.
	(V_128): Likewise.
	(tf_vr): New mode_attr.
	(tointvec): Add TF.
	(mov<mode>): Rename to mov<mode><tf_vr>.
	(movetf): New dispatcher.
	(*vec_tf_to_v1tf): Rename to *vec_tf_to_v1tf_fpr, restrict to
	z13-.
	(*vec_tf_to_v1tf_vr): New pattern for z14+.
	(*fprx2_to_tf): Likewise.
	(*mov_tf_to_fprx2_0): Likewise.
	(*mov_tf_to_fprx2_1): Likewise.
	(add<mode>3): Rename to add<mode>3<tf_vr>.
	(addtf3): New dispatcher.
	(sub<mode>3): Rename to sub<mode>3<tf_vr>.
	(subtf3): New dispatcher.
	(mul<mode>3): Rename to mul<mode>3<tf_vr>.
	(multf3): New dispatcher.
	(div<mode>3): Rename to div<mode>3<tf_vr>.
	(divtf3): New dispatcher.
	(sqrt<mode>2): Rename to sqrt<mode>2<tf_vr>.
	(sqrttf2): New dispatcher.
	(fma<mode>4): Restrict using s390_fma_allowed_p.
	(fms<mode>4): Likewise.
	(neg_fma<mode>4): Likewise.
	(neg_fms<mode>4): Likewise.
	(neg<mode>2): Rename to neg<mode>2<tf_vr>.
	(negtf2): New dispatcher.
	(abs<mode>2): Rename to abs<mode>2<tf_vr>.
	(abstf2): New dispatcher.
	(float<mode>tf2_vr): New forwarder.
	(float<mode>tf2): New dispatcher.
	(floatuns<mode>tf2_vr): New forwarder.
	(floatuns<mode>tf2): New dispatcher.
	(fix_trunctf<mode>2_vr): New forwarder.
	(fix_trunctf<mode>2): New dispatcher.
	(fixuns_trunctf<mode>2_vr): New forwarder.
	(fixuns_trunctf<mode>2): New dispatcher.
	(<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>): New pattern.
	(<FPINT:fpint_name>tf2): New forwarder.
	(rint<mode>2<tf_vr>): New pattern.
	(rinttf2): New forwarder.
	(*trunctfdf2_vr): New pattern.
	(trunctfdf2_vr): New forwarder.
	(trunctfdf2): New dispatcher.
	(trunctfsf2_vr): New forwarder.
	(trunctfsf2): New dispatcher.
	(extenddftf2_vr): New pattern.
	(extenddftf2): New dispatcher.
	(extendsftf2_vr): New forwarder.
	(extendsftf2): New dispatcher.
	(signbittf2_vr): New forwarder.
	(signbittf2): New dispatchers.
	(isinftf2_vr): New forwarder.
	(isinftf2): New dispatcher.
	* config/s390/vx-builtins.md (*vftci<mode>_cconly): Use VF_HW
	instead of VECF_HW, add missing constraint, add vw support.
	(vftci<mode>_intcconly): Use VF_HW instead of VECF_HW.
	(*vftci<mode>): Rename to vftci<mode>, use VF_HW instead of
	VECF_HW, and vw support.
	(vftci<mode>_intcc): Use VF_HW instead of VECF_HW.
---
 gcc/config/s390/s390-modes.def |   5 +-
 gcc/config/s390/s390-protos.h  |   1 +
 gcc/config/s390/s390.c         |  53 ++++-
 gcc/config/s390/s390.h         |  28 +++
 gcc/config/s390/s390.md        | 209 +++++++++++-------
 gcc/config/s390/s390.opt       |  11 +
 gcc/config/s390/vector.md      | 382 ++++++++++++++++++++++++++++++---
 gcc/config/s390/vx-builtins.md |  38 ++--
 8 files changed, 593 insertions(+), 134 deletions(-)

diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index b1f8e1fc9e3..316ca5cf58b 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -22,9 +22,12 @@ along with GCC; see the file COPYING3.  If not see
 /* 256-bit integer mode is needed for STACK_SAVEAREA_MODE.  */
 INT_MODE (OI, 32);
 
-/* Define TFmode to work around reload problem PR 20927.  */
+/* 128-bit float stored in a VR on z14+ or a FPR pair on older machines.  */
 FLOAT_MODE (TF, 16, ieee_quad_format);
 
+/* 128-bit float stored in a FPR pair.  */
+FLOAT_MODE (FPRX2, 16, ieee_quad_format);
+
 /* Add any extra modes needed to represent the condition code.  */
 
 /*
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 029f7289fac..ad2f7f77c18 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -51,6 +51,7 @@ extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
 extern int s390_class_max_nregs (enum reg_class, machine_mode);
 extern bool s390_function_arg_vector (machine_mode, const_tree);
 extern bool s390_return_addr_from_memory(void);
+extern bool s390_fma_allowed_p (machine_mode);
 #if S390_USE_TARGET_ATTRIBUTE
 extern tree s390_valid_target_attribute_tree (tree args,
 					      struct gcc_options *opts,
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b8961a315aa..7c21217580d 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -456,6 +456,16 @@ s390_return_addr_from_memory ()
   return cfun_gpr_save_slot(RETURN_REGNUM) == SAVE_SLOT_STACK;
 }
 
+/* Return nonzero if it's OK to use fused multiply-add for MODE.  */
+bool
+s390_fma_allowed_p (machine_mode mode)
+{
+  if (TARGET_VXE && mode == TFmode)
+    return flag_vx_long_double_fma;
+
+  return true;
+}
+
 /* Indicate which ABI has been used for passing vector args.
    0 - no vector type arguments have been passed where the ABI is relevant
    1 - the old ABI has been used
@@ -6959,6 +6969,13 @@ s390_expand_vec_init (rtx target, rtx vals)
 extern rtx
 s390_build_signbit_mask (machine_mode mode)
 {
+  if (mode == TFmode && TARGET_VXE)
+    {
+      wide_int mask_val = wi::set_bit_in_zero (127, 128);
+      rtx mask = immed_wide_int_const (mask_val, TImode);
+      return gen_lowpart (TFmode, mask);
+    }
+
   /* Generate the integral element mask value.  */
   machine_mode inner_mode = GET_MODE_INNER (mode);
   int inner_bitsize = GET_MODE_BITSIZE (inner_mode);
@@ -7902,6 +7919,7 @@ print_operand_address (FILE *file, rtx addr)
 	 CONST_VECTOR: Generate a bitmask for vgbm instruction.
     'x': print integer X as if it's an unsigned halfword.
     'v': print register number as vector register (v1 instead of f1).
+    'V': print the second word of a TFmode operand as vector register.
 */
 
 void
@@ -8071,13 +8089,13 @@ print_operand (FILE *file, rtx x, int code)
     case REG:
       /* Print FP regs as fx instead of vx when they are accessed
 	 through non-vector mode.  */
-      if (code == 'v'
+      if ((code == 'v' || code == 'V')
 	  || VECTOR_NOFP_REG_P (x)
 	  || (FP_REG_P (x) && VECTOR_MODE_P (GET_MODE (x)))
 	  || (VECTOR_REG_P (x)
 	      && (GET_MODE_SIZE (GET_MODE (x)) /
 		  s390_class_max_nregs (FP_REGS, GET_MODE (x))) > 8))
-	fprintf (file, "%%v%s", reg_names[REGNO (x)] + 2);
+	fprintf (file, "%%v%s", reg_names[REGNO (x) + (code == 'V')] + 2);
       else
 	fprintf (file, "%s", reg_names[REGNO (x)]);
       break;
@@ -8623,7 +8641,7 @@ replace_constant_pool_ref (rtx_insn *insn, rtx ref, rtx offset)
 
 static machine_mode constant_modes[] =
 {
-  TFmode, TImode, TDmode,
+  TFmode, FPRX2mode, TImode, TDmode,
   V16QImode, V8HImode, V4SImode, V2DImode, V1TImode,
   V4SFmode, V2DFmode, V1TFmode,
   DFmode, DImode, DDmode,
@@ -10418,7 +10436,8 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
 	 full VRs.  */
       if (TARGET_VX
 	  && SCALAR_FLOAT_MODE_P (mode)
-	  && GET_MODE_SIZE (mode) >= 16)
+	  && GET_MODE_SIZE (mode) >= 16
+	  && !(TARGET_VXE && mode == TFmode))
 	reg_pair_required_p = true;
 
       /* Even if complex types would fit into a single FPR/VR we force
@@ -10441,6 +10460,24 @@ s390_class_max_nregs (enum reg_class rclass, machine_mode mode)
   return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size;
 }
 
+/* Return nonzero if mode M describes a 128-bit float in a floating point
+   register pair.  */
+
+static bool
+s390_is_fpr128 (machine_mode m)
+{
+  return m == FPRX2mode || (!TARGET_VXE && m == TFmode);
+}
+
+/* Return nonzero if mode M describes a 128-bit float in a vector
+   register.  */
+
+static bool
+s390_is_vr128 (machine_mode m)
+{
+  return m == V1TFmode || (TARGET_VXE && m == TFmode);
+}
+
 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
 static bool
@@ -10451,11 +10488,11 @@ s390_can_change_mode_class (machine_mode from_mode,
   machine_mode small_mode;
   machine_mode big_mode;
 
-  /* V1TF and TF have different representations in vector
-     registers.  */
+  /* 128-bit values have different representations in floating point and
+     vector registers.  */
   if (reg_classes_intersect_p (VEC_REGS, rclass)
-      && ((from_mode == V1TFmode && to_mode == TFmode)
-	  || (from_mode == TFmode && to_mode == V1TFmode)))
+      && ((s390_is_fpr128 (from_mode) && s390_is_vr128 (to_mode))
+	  || (s390_is_vr128 (from_mode) && s390_is_fpr128 (to_mode))))
     return false;
 
   if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode))
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index ec5128c0af2..434a8449c9b 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1186,5 +1186,33 @@ struct GTY(()) machine_function
 
 #define TARGET_INDIRECT_BRANCH_TABLE s390_indirect_branch_table
 
+/* Dispatcher for movtf.  */
+#define EXPAND_MOVTF(icode)                                                   \
+  do                                                                          \
+    {                                                                         \
+      if (TARGET_VXE)                                                         \
+	emit_insn (gen_##icode##_vr (operands[0], operands[1]));              \
+      else                                                                    \
+	emit_insn (gen_##icode##_fpr (operands[0], operands[1]));             \
+      DONE;                                                                   \
+    }                                                                         \
+  while (false)
+
+/* Like EXPAND_MOVTF, but also legitimizes operands.  */
+#define EXPAND_TF(icode, nops)                                                \
+  do                                                                          \
+    {                                                                         \
+      const size_t __nops = (nops);                                           \
+      expand_operand ops[__nops];                                             \
+      create_output_operand (&ops[0], operands[0], GET_MODE (operands[0]));   \
+      for (size_t i = 1; i < __nops; i++)                                     \
+	create_input_operand (&ops[i], operands[i], GET_MODE (operands[i]));  \
+      if (TARGET_VXE)                                                         \
+	expand_insn (CODE_FOR_##icode##_vr, __nops, ops);                     \
+      else                                                                    \
+	expand_insn (CODE_FOR_##icode##_fpr, __nops, ops);                    \
+      DONE;                                                                   \
+    }                                                                         \
+  while (false)
 
 #endif /* S390_H */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 050374980ae..fd2a0c6e68a 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -405,6 +405,7 @@ (define_constants
    (PFPO_OP_TYPE_SF             0x5)
    (PFPO_OP_TYPE_DF             0x6)
    (PFPO_OP_TYPE_TF             0x7)
+   (PFPO_OP_TYPE_FPRX2          0x7)
    (PFPO_OP_TYPE_SD             0x8)
    (PFPO_OP_TYPE_DD             0x9)
    (PFPO_OP_TYPE_TD             0xa)
@@ -627,20 +628,29 @@ (define_attr "relative_long" "no,yes" (const_string "no"))
 
 ;; Iterators
 
-(define_mode_iterator ALL [TI DI SI HI QI TF DF SF TD DD SD V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF V2SF V4SF V1TI V1DF V2DF V1TF])
+(define_mode_iterator ALL [TI DI SI HI QI TF FPRX2 DF SF TD DD SD V1QI V2QI
+			   V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI
+			   V1DI V2DI V1SF V2SF V4SF V1TI V1DF V2DF V1TF])
 
 ;; These mode iterators allow floating point patterns to be generated from the
 ;; same template.
-(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
+(define_mode_iterator FP_ALL [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF
+			      (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
                               (SD "TARGET_HARD_DFP")])
-(define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
-(define_mode_iterator BFP [TF DF SF])
+(define_mode_iterator FP [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF
+			  (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
+;; Like FP, but without a condition on TF. Useful for expanders that must be
+;; the same for FP and VR variants of TF.
+(define_mode_iterator FP_ANYTF [TF (FPRX2 "TARGET_VXE") DF SF
+				(TD "TARGET_HARD_DFP")
+				(DD "TARGET_HARD_DFP")])
+(define_mode_iterator BFP [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") DF SF])
 (define_mode_iterator DFP [TD DD])
 (define_mode_iterator DFP_ALL [TD DD SD])
 (define_mode_iterator DSF [DF SF])
 (define_mode_iterator SD_SF [SF SD])
 (define_mode_iterator DD_DF [DF DD])
-(define_mode_iterator TD_TF [TF TD])
+(define_mode_iterator TD_TF [(TF "!TARGET_VXE") (FPRX2 "TARGET_VXE") TD])
 
 ; 32 bit int<->fp conversion instructions are available since VXE2 (z15).
 (define_mode_iterator VX_CONV_BFP [DF (SF "TARGET_VXE2")])
@@ -714,7 +724,8 @@ (define_code_attr noxa [(and "n") (ior "o") (xor "x") (plus "a")])
 
 ;; In FP templates, a string like "lt<de>br" will expand to "ltxbr" in
 ;; TF/TDmode, "ltdbr" in DF/DDmode, and "ltebr" in SF/SDmode.
-(define_mode_attr xde [(TF "x") (DF "d") (SF "e") (TD "x") (DD "d") (SD "e") (V4SF "e") (V2DF "d")])
+(define_mode_attr xde [(TF "x") (FPRX2 "x") (DF "d") (SF "e") (TD "x")
+		       (DD "d") (SD "e") (V4SF "e") (V2DF "d")])
 
 ;; In FP templates, a <dee> in "m<dee><bt>r" will expand to "mx<bt>r" in
 ;; TF/TDmode, "md<bt>r" in DF/DDmode, "mee<bt>r" in SFmode and "me<bt>r in
@@ -727,19 +738,22 @@ (define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")])
 
 ;; These mode attributes are supposed to be used in the `enabled' insn
 ;; attribute to disable certain alternatives for certain modes.
-(define_mode_attr nBFP [(TF "0") (DF "0") (SF "0") (TD "*") (DD "*") (DD "*")])
-(define_mode_attr nDFP [(TF "*") (DF "*") (SF "*") (TD "0") (DD "0") (DD "0")])
-(define_mode_attr DSF [(TF "0") (DF "*") (SF "*") (TD "0") (DD "0") (SD "0")])
-(define_mode_attr DFDI [(TF "0") (DF "*") (SF "0")
+(define_mode_attr nBFP [(TF "0") (FPRX2 "0") (DF "0") (SF "0") (TD "*")
+			(DD "*") (DD "*")])
+(define_mode_attr nDFP [(TF "*") (FPRX2 "*") (DF "*") (SF "*") (TD "0")
+			(DD "0") (DD "0")])
+(define_mode_attr DSF [(TF "0") (FPRX2 "0") (DF "*") (SF "*") (TD "0")
+		       (DD "0") (SD "0")])
+(define_mode_attr DFDI [(TF "0") (FPRX2 "0") (DF "*") (SF "0")
 			(TD "0") (DD "0") (DD "0")
 			(TI "0") (DI "*") (SI "0")])
-(define_mode_attr SFSI [(TF "0") (DF "0") (SF "*")
+(define_mode_attr SFSI [(TF "0") (FPRX2 "0") (DF "0") (SF "*")
 			(TD "0") (DD "0") (DD "0")
 			(TI "0") (DI "0") (SI "*")])
-(define_mode_attr DF [(TF "0") (DF "*") (SF "0")
+(define_mode_attr DF [(TF "0") (FPRX2 "0") (DF "*") (SF "0")
 		      (TD "0") (DD "0") (DD "0")
 		      (TI "0") (DI "0") (SI "0")])
-(define_mode_attr SF [(TF "0") (DF "0") (SF "*")
+(define_mode_attr SF [(TF "0") (FPRX2 "0") (DF "0") (SF "*")
 		      (TD "0") (DD "0") (DD "0")
 		      (TI "0") (DI "0") (SI "0")])
 
@@ -749,15 +763,17 @@ (define_mode_attr SF [(TF "0") (DF "0") (SF "*")
 ;; sign bit instructions only handle single source and target fp registers
 ;; these instructions can only be used for TFmode values if the source and
 ;; target operand uses the same fp register.
-(define_mode_attr fT0 [(TF "0") (DF "f") (SF "f")])
+(define_mode_attr fT0 [(TF "0") (FPRX2 "0") (DF "f") (SF "f")])
 
 ;; This attribute adds b for bfp instructions and t for dfp instructions and is used
 ;; within instruction mnemonics.
-(define_mode_attr bt [(TF "b") (DF "b") (SF "b") (TD "t") (DD "t") (SD "t")])
+(define_mode_attr bt [(TF "b") (FPRX2 "b") (DF "b") (SF "b") (TD "t") (DD "t")
+		      (SD "t")])
 
 ;; This attribute is used within instruction mnemonics.  It evaluates to d for dfp
 ;; modes and to an empty string for bfp modes.
-(define_mode_attr _d [(TF "") (DF "") (SF "") (TD "d") (DD "d") (SD "d")])
+(define_mode_attr _d [(TF "") (FPRX2 "") (DF "") (SF "") (TD "d") (DD "d")
+		      (SD "d")])
 
 ;; In GPR and P templates, a constraint like "<d0>" will expand to "d" in DImode
 ;; and "0" in SImode. This allows to combine instructions of which the 31bit
@@ -829,7 +845,7 @@ (define_mode_attr DBL [(DI "TI") (SI "DI")])
 
 ;; This attribute expands to DF for TFmode and to DD for TDmode .  It is
 ;; used for Txmode splitters splitting a Txmode copy into 2 Dxmode copies.
-(define_mode_attr HALF_TMODE [(TF "DF") (TD "DD")])
+(define_mode_attr HALF_TMODE [(TF "DF") (FPRX2 "DF") (TD "DD")])
 
 ;; Maximum unsigned integer that fits in MODE.
 (define_mode_attr max_uint [(HI "65535") (QI "255")])
@@ -850,6 +866,13 @@ (define_mode_attr modesize [(DI "8") (SI "4")])
 ;; Allow return and simple_return to be defined from a single template.
 (define_code_iterator ANY_RETURN [return simple_return])
 
+;; Facilitate dispatching TFmode expanders on z14+.
+(define_mode_attr tf_fpr [(TF "_fpr") (FPRX2 "") (DF "") (SF "") (TD "")
+			  (DD "") (SD "")])
+
+;; Mode names as seen in type mode_attr values.
+(define_mode_attr type [(TF "tf") (FPRX2 "tf") (DF "df") (SF "sf") (TD "td")
+			(DD "dd") (SD "sd")])
 
 
 ; Condition code modes generated by vector fp comparisons.  These will
@@ -1421,7 +1444,7 @@ (define_insn "*cmp<mode>_ccz_0"
   "TARGET_HARD_FLOAT"
   "lt<xde><bt>r\t%0,%0"
    [(set_attr "op_type" "RRE")
-    (set_attr "type"  "fsimp<mode>")])
+    (set_attr "type" "fsimp<type>")])
 
 (define_insn "*cmp<mode>_ccs_0_fastmath"
   [(set (reg CC_REGNUM)
@@ -1433,7 +1456,7 @@ (define_insn "*cmp<mode>_ccs_0_fastmath"
    && !flag_signaling_nans"
   "lt<xde><bt>r\t%0,%0"
   [(set_attr "op_type" "RRE")
-   (set_attr "type" "fsimp<mode>")])
+   (set_attr "type" "fsimp<type>")])
 
 ; VX: TFmode in FPR pairs: use cxbr instead of wfcxb
 ; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcsb, wfcdb
@@ -1451,6 +1474,18 @@ (define_insn "*cmp<mode>_ccs"
    (set_attr "cpu_facility" "*,*,vx,vxe")
    (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
 
+; VX: TFmode in VR: use wfcxb
+(define_insn "*cmptf_ccs"
+  [(set (reg CC_REGNUM)
+	(compare (match_operand:TF 0 "register_operand" "v")
+		 (match_operand:TF 1 "general_operand"  "v")))]
+  "s390_match_ccmode(insn, CCSmode) && TARGET_VXE"
+  "wfcxb\t%0,%1"
+  [(set_attr "op_type" "VRR")
+   (set_attr "cpu_facility" "vxe")])
+
+; VX: TFmode in FPR pairs: use kxbr instead of wfkxb
+; kxtr, kdtr, kxbr, kdbr, kebr, kdb, keb, wfksb, wfkdb
 (define_insn "*cmp<mode>_ccsfps"
   [(set (reg CC_REGNUM)
 	(compare (match_operand:FP 0 "register_operand" "f,f,v,v")
@@ -1465,6 +1500,16 @@ (define_insn "*cmp<mode>_ccsfps"
    (set_attr "cpu_facility" "*,*,vx,vxe")
    (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
 
+; VX: TFmode in VR: use wfkxb
+(define_insn "*cmptf_ccsfps"
+  [(set (reg CC_REGNUM)
+	(compare (match_operand:TF 0 "register_operand" "v")
+		 (match_operand:TF 1 "general_operand"  "v")))]
+  "s390_match_ccmode (insn, CCSFPSmode) && TARGET_VXE"
+  "wfkxb\t%0,%1"
+  [(set_attr "op_type" "VRR")
+   (set_attr "cpu_facility" "vxe")])
+
 ; Compare and Branch instructions
 
 ; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
@@ -2489,7 +2534,7 @@ (define_insn "movstrictsi"
 ; mov(tf|td) instruction pattern(s).
 ;
 
-(define_expand "mov<mode>"
+(define_expand "mov<mode><tf_fpr>"
   [(set (match_operand:TD_TF 0 "nonimmediate_operand" "")
         (match_operand:TD_TF 1 "general_operand"      ""))]
   ""
@@ -3418,7 +3463,7 @@ (define_insn "*cpymem_long_31z"
 ; Test data class.
 ;
 
-(define_expand "signbit<mode>2"
+(define_expand "signbit<mode>2<tf_fpr>"
   [(set (reg:CCZ CC_REGNUM)
         (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
                      (match_dup 2)]
@@ -3430,7 +3475,7 @@ (define_expand "signbit<mode>2"
   operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
 })
 
-(define_expand "isinf<mode>2"
+(define_expand "isinf<mode>2<tf_fpr>"
   [(set (reg:CCZ CC_REGNUM)
         (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
                      (match_dup 2)]
@@ -3468,7 +3513,7 @@ (define_insn "*TDC_insn_<mode>"
   "TARGET_HARD_FLOAT"
   "t<_d>c<xde><bt>\t%0,%1"
    [(set_attr "op_type" "RXE")
-    (set_attr "type"  "fsimp<mode>")])
+    (set_attr "type"    "fsimp<type>")])
 
 
 
@@ -4984,7 +5029,7 @@ (define_insn_and_split "*zero_extendqihi2_31"
 ; This is the only entry point for fixuns_trunc.  It multiplexes the
 ; expansion to either the *_emu expanders below for pre z196 machines
 ; or emits the default pattern otherwise.
-(define_expand "fixuns_trunc<FP:mode><GPR:mode>2"
+(define_expand "fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>"
   [(parallel
     [(set (match_operand:GPR 0 "register_operand" "")
 	  (unsigned_fix:GPR (match_operand:FP 1 "register_operand" "")))
@@ -5247,12 +5292,12 @@ (define_insn "fix_trunc<DFP:mode>di2_dfp"
 ; fix_trunctf(si|di)2 instruction pattern(s).
 ;
 
-(define_expand "fix_trunctf<mode>2"
+(define_expand "fix_trunctf<mode>2_fpr"
   [(parallel [(set (match_operand:GPR 0 "register_operand" "")
 		   (fix:GPR (match_operand:TF 1 "register_operand" "")))
 	      (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
 	      (clobber (reg:CC CC_REGNUM))])]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && !TARGET_VXE"
   "")
 
 
@@ -5261,7 +5306,7 @@ (define_expand "fix_trunctf<mode>2"
 ;
 
 ; cxgbr, cdgbr, cegbr, cxgtr, cdgtr
-(define_insn "floatdi<mode>2"
+(define_insn "floatdi<mode>2<tf_fpr>"
   [(set (match_operand:FP           0 "register_operand" "=f,v")
         (float:FP (match_operand:DI 1 "register_operand"  "d,v")))]
   "TARGET_ZARCH && TARGET_HARD_FLOAT"
@@ -5269,12 +5314,12 @@ (define_insn "floatdi<mode>2"
    c<xde>g<bt>r\t%0,%1
    wcdgb\t%v0,%v1,0,0"
   [(set_attr "op_type"      "RRE,VRR")
-   (set_attr "type"         "itof<mode>" )
+   (set_attr "type"         "itof<type>" )
    (set_attr "cpu_facility" "*,vx")
    (set_attr "enabled"      "*,<DFDI>")])
 
 ; cxfbr, cdfbr, cefbr, wcefb
-(define_insn "floatsi<mode>2"
+(define_insn "floatsi<mode>2<tf_fpr>"
   [(set (match_operand:BFP           0 "register_operand" "=f,v")
         (float:BFP (match_operand:SI 1 "register_operand"  "d,v")))]
   "TARGET_HARD_FLOAT"
@@ -5282,7 +5327,7 @@ (define_insn "floatsi<mode>2"
    c<xde>fbr\t%0,%1
    wcefb\t%v0,%v1,0,0"
   [(set_attr "op_type"      "RRE,VRR")
-   (set_attr "type"         "itof<mode>" )
+   (set_attr "type"         "itof<type>" )
    (set_attr "cpu_facility" "*,vxe2")
    (set_attr "enabled"      "*,<SFSI>")])
 
@@ -5293,7 +5338,7 @@ (define_insn "floatsi<mode>2"
   "TARGET_Z196 && TARGET_HARD_FLOAT"
   "c<xde>ftr\t%0,0,%1,0"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"   "itof<mode>" )])
+   (set_attr "type"    "itof<type>")])
 
 ;
 ; floatuns(si|di)(tf|df|sf|td|dd)2 instruction pattern(s).
@@ -5319,9 +5364,9 @@ (define_insn "*floatuns<GPR:mode><FP:mode>2"
    && (!TARGET_VX || <FP:MODE>mode != DFmode || <GPR:MODE>mode != DImode)"
   "c<FP:xde>l<GPR:gf><FP:bt>r\t%0,0,%1,0"
   [(set_attr "op_type" "RRE")
-   (set_attr "type"    "itof<FP:mode>")])
+   (set_attr "type"    "itof<FP:type>")])
 
-(define_expand "floatuns<GPR:mode><FP:mode>2"
+(define_expand "floatuns<GPR:mode><FP:mode>2<tf_fpr>"
   [(set (match_operand:FP                     0 "register_operand" "")
         (unsigned_float:FP (match_operand:GPR 1 "register_operand" "")))]
   "TARGET_Z196 && TARGET_HARD_FLOAT")
@@ -5347,7 +5392,7 @@ (define_insn "truncdfsf2"
 ;
 
 ; ldxbr, lexbr
-(define_insn "trunctf<mode>2"
+(define_insn "trunctf<mode>2_fpr"
   [(set (match_operand:DSF 0 "register_operand" "=f")
         (float_truncate:DSF (match_operand:TF 1 "register_operand" "f")))
    (clobber (match_scratch:TF 2 "=f"))]
@@ -5427,9 +5472,9 @@ (define_insn "*extend<DSF:mode><BFP:mode>2"
    l<BFP:xde><DSF:xde>br\t%0,%1
    l<BFP:xde><DSF:xde>b\t%0,%1"
   [(set_attr "op_type" "RRE,RXE")
-   (set_attr "type"    "fsimp<BFP:mode>, fload<BFP:mode>")])
+   (set_attr "type"    "fsimp<BFP:type>, fload<BFP:type>")])
 
-(define_expand "extend<DSF:mode><BFP:mode>2"
+(define_expand "extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>"
   [(set (match_operand:BFP                   0 "register_operand"     "")
         (float_extend:BFP (match_operand:DSF 1 "nonimmediate_operand" "")))]
   "TARGET_HARD_FLOAT
@@ -5471,27 +5516,27 @@ (define_expand "extendsdtd2"
 ; For all of them the inexact exceptions are suppressed.
 
 ; fiebra, fidbra, fixbra
-(define_insn "<FPINT:fpint_name><BFP:mode>2"
+(define_insn "<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>"
   [(set (match_operand:BFP 0 "register_operand" "=f")
 	(unspec:BFP [(match_operand:BFP 1 "register_operand" "f")]
 		    FPINT))]
   "TARGET_Z196"
   "fi<BFP:xde>bra\t%0,<FPINT:fpint_roundingmode>,%1,4"
   [(set_attr "op_type"   "RRF")
-   (set_attr "type"      "fsimp<BFP:mode>")])
+   (set_attr "type"      "fsimp<BFP:type>")])
 
 ; rint is supposed to raise an inexact exception so we can use the
 ; older instructions.
 
 ; fiebr, fidbr, fixbr
-(define_insn "rint<BFP:mode>2"
+(define_insn "rint<BFP:mode>2<BFP:tf_fpr>"
   [(set (match_operand:BFP 0 "register_operand" "=f")
 	(unspec:BFP [(match_operand:BFP 1 "register_operand" "f")]
 		    UNSPEC_FPINT_RINT))]
   ""
   "fi<BFP:xde>br\t%0,0,%1"
   [(set_attr "op_type"   "RRF")
-   (set_attr "type"      "fsimp<BFP:mode>")])
+   (set_attr "type"      "fsimp<BFP:type>")])
 
 
 ; Decimal Floating Point - load fp integer
@@ -5504,7 +5549,7 @@ (define_insn "<FPINT:fpint_name><DFP:mode>2"
   "TARGET_HARD_DFP"
   "fi<DFP:xde>tr\t%0,<FPINT:fpint_roundingmode>,%1,4"
   [(set_attr "op_type"   "RRF")
-   (set_attr "type"      "fsimp<DFP:mode>")])
+   (set_attr "type"      "fsimp<DFP:type>")])
 
 ; fidtr, fixtr
 (define_insn "rint<DFP:mode>2"
@@ -5514,7 +5559,7 @@ (define_insn "rint<DFP:mode>2"
   "TARGET_HARD_DFP"
   "fi<DFP:xde>tr\t%0,0,%1,0"
   [(set_attr "op_type"   "RRF")
-   (set_attr "type"      "fsimp<DFP:mode>")])
+   (set_attr "type"      "fsimp<DFP:type>")])
 
 ;
 ; Binary <-> Decimal floating point trunc patterns
@@ -5538,7 +5583,7 @@ (define_insn "*trunc<DFP_ALL:mode><BFP:mode>2"
   "TARGET_HARD_DFP"
   "pfpo")
 
-(define_expand "trunc<BFP:mode><DFP_ALL:mode>2"
+(define_expand "trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>"
   [(set (reg:BFP FPR4_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
    (set (reg:SI GPR0_REGNUM) (match_dup 2))
    (parallel
@@ -5565,7 +5610,7 @@ (define_expand "trunc<BFP:mode><DFP_ALL:mode>2"
   operands[2] = GEN_INT (flags);
 })
 
-(define_expand "trunc<DFP_ALL:mode><BFP:mode>2"
+(define_expand "trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>"
   [(set (reg:DFP_ALL FPR4_REGNUM)
         (match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
    (set (reg:SI GPR0_REGNUM) (match_dup 2))
@@ -5611,7 +5656,7 @@ (define_insn "*extend<DFP_ALL:mode><BFP:mode>2"
   "TARGET_HARD_DFP"
   "pfpo")
 
-(define_expand "extend<BFP:mode><DFP_ALL:mode>2"
+(define_expand "extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>"
   [(set (reg:BFP FPR4_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
    (set (reg:SI GPR0_REGNUM) (match_dup 2))
    (parallel
@@ -5638,7 +5683,7 @@ (define_expand "extend<BFP:mode><DFP_ALL:mode>2"
   operands[2] = GEN_INT (flags);
 })
 
-(define_expand "extend<DFP_ALL:mode><BFP:mode>2"
+(define_expand "extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>"
   [(set (reg:DFP_ALL FPR4_REGNUM)
         (match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
    (set (reg:SI GPR0_REGNUM) (match_dup 2))
@@ -6117,7 +6162,7 @@ (define_insn "*addv<mode>3_ccoverflow_const"
 
 ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
 ; FIXME: wfadb does not clobber cc
-(define_insn "add<mode>3"
+(define_insn "add<mode>3<tf_fpr>"
   [(set (match_operand:FP          0 "register_operand"     "=f,f,f,v,v")
         (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v,v")
 		 (match_operand:FP 2 "general_operand"       "f,f,R,v,v")))
@@ -6130,7 +6175,7 @@ (define_insn "add<mode>3"
    wfadb\t%v0,%v1,%v2
    wfasb\t%v0,%v1,%v2"
   [(set_attr "op_type"      "RRF,RRE,RXE,VRR,VRR")
-   (set_attr "type"         "fsimp<mode>")
+   (set_attr "type"         "fsimp<type>")
    (set_attr "cpu_facility" "*,*,*,vx,vxe")
    (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
@@ -6148,7 +6193,7 @@ (define_insn "*add<mode>3_cc"
    a<xde>br\t%0,%2
    a<xde>b\t%0,%2"
   [(set_attr "op_type"  "RRF,RRE,RXE")
-   (set_attr "type"     "fsimp<mode>")
+   (set_attr "type"     "fsimp<type>")
    (set_attr "enabled"  "<nBFP>,<nDFP>,<DSF>")])
 
 ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
@@ -6164,7 +6209,7 @@ (define_insn "*add<mode>3_cconly"
    a<xde>br\t%0,%2
    a<xde>b\t%0,%2"
   [(set_attr "op_type"  "RRF,RRE,RXE")
-   (set_attr "type"     "fsimp<mode>")
+   (set_attr "type"     "fsimp<type>")
    (set_attr "enabled"  "<nBFP>,<nDFP>,<DSF>")])
 
 ;
@@ -6562,7 +6607,7 @@ (define_insn "*subv<mode>3_ccoverflow"
 
 ; FIXME: (clobber (match_scratch:CC 3 "=c,c,c,X,X")) does not work - why?
 ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
-(define_insn "sub<mode>3"
+(define_insn "sub<mode>3<tf_fpr>"
   [(set (match_operand:FP           0 "register_operand" "=f,f,f,v,v")
         (minus:FP (match_operand:FP 1 "register_operand"  "f,0,0,v,v")
 		  (match_operand:FP 2 "general_operand"   "f,f,R,v,v")))
@@ -6575,7 +6620,7 @@ (define_insn "sub<mode>3"
    wfsdb\t%v0,%v1,%v2
    wfssb\t%v0,%v1,%v2"
   [(set_attr "op_type"      "RRF,RRE,RXE,VRR,VRR")
-   (set_attr "type"         "fsimp<mode>")
+   (set_attr "type"         "fsimp<type>")
    (set_attr "cpu_facility" "*,*,*,vx,vxe")
    (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
@@ -6593,7 +6638,7 @@ (define_insn "*sub<mode>3_cc"
    s<xde>br\t%0,%2
    s<xde>b\t%0,%2"
   [(set_attr "op_type"  "RRF,RRE,RXE")
-   (set_attr "type"     "fsimp<mode>")
+   (set_attr "type"     "fsimp<type>")
    (set_attr "enabled"  "<nBFP>,<nDFP>,<DSF>")])
 
 ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
@@ -6609,7 +6654,7 @@ (define_insn "*sub<mode>3_cconly"
    s<xde>br\t%0,%2
    s<xde>b\t%0,%2"
   [(set_attr "op_type"  "RRF,RRE,RXE")
-   (set_attr "type"     "fsimp<mode>")
+   (set_attr "type"     "fsimp<type>")
    (set_attr "enabled"  "<nBFP>,<nDFP>,<DSF>")])
 
 
@@ -7143,7 +7188,7 @@ (define_insn "umul<dwh><mode>3"
 ;
 
 ; mxbr, mdbr, meebr, mxb, mxb, meeb, mdtr, mxtr
-(define_insn "mul<mode>3"
+(define_insn "mul<mode>3<tf_fpr>"
   [(set (match_operand:FP          0 "register_operand"     "=f,f,f,v,v")
         (mult:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v,v")
 		 (match_operand:FP 2 "general_operand"       "f,f,R,v,v")))]
@@ -7155,7 +7200,7 @@ (define_insn "mul<mode>3"
    wfmdb\t%v0,%v1,%v2
    wfmsb\t%v0,%v1,%v2"
   [(set_attr "op_type"      "RRF,RRE,RXE,VRR,VRR")
-   (set_attr "type"         "fmul<mode>")
+   (set_attr "type"         "fmul<type>")
    (set_attr "cpu_facility" "*,*,*,vx,vxe")
    (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
@@ -7165,7 +7210,7 @@ (define_insn "fma<mode>4"
 	(fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,v,v")
 		 (match_operand:DSF 2 "nonimmediate_operand"  "f,R,v,v")
 		 (match_operand:DSF 3 "register_operand"      "0,0,v,v")))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && s390_fma_allowed_p (<MODE>mode)"
   "@
    ma<xde>br\t%0,%1,%2
    ma<xde>b\t%0,%1,%2
@@ -7182,7 +7227,7 @@ (define_insn "fms<mode>4"
 	(fma:DSF (match_operand:DSF          1 "nonimmediate_operand" "%f,f,v,v")
 		 (match_operand:DSF          2 "nonimmediate_operand"  "f,R,v,v")
 		 (neg:DSF (match_operand:DSF 3 "register_operand"      "0,0,v,v"))))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_HARD_FLOAT && s390_fma_allowed_p (<MODE>mode)"
   "@
    ms<xde>br\t%0,%1,%2
    ms<xde>b\t%0,%1,%2
@@ -7448,7 +7493,7 @@ (define_insn "udivmoddisi3"
 ;
 
 ; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr
-(define_insn "div<mode>3"
+(define_insn "div<mode>3<tf_fpr>"
   [(set (match_operand:FP         0 "register_operand" "=f,f,f,v,v")
         (div:FP (match_operand:FP 1 "register_operand"  "f,0,0,v,v")
 		(match_operand:FP 2 "general_operand"   "f,f,R,v,v")))]
@@ -7460,7 +7505,7 @@ (define_insn "div<mode>3"
    wfddb\t%v0,%v1,%v2
    wfdsb\t%v0,%v1,%v2"
   [(set_attr "op_type"      "RRF,RRE,RXE,VRR,VRR")
-   (set_attr "type"         "fdiv<mode>")
+   (set_attr "type"         "fdiv<type>")
    (set_attr "cpu_facility" "*,*,*,vx,vxe")
    (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
@@ -8777,10 +8822,10 @@ (define_split
    operands[6] = gen_label_rtx ();")
 
 ;
-; neg(df|sf)2 instruction pattern(s).
+; neg(tf|df|sf)2 instruction pattern(s).
 ;
 
-(define_expand "neg<mode>2"
+(define_expand "neg<mode>2<tf_fpr>"
   [(parallel
     [(set (match_operand:BFP          0 "register_operand")
           (neg:BFP (match_operand:BFP 1 "register_operand")))
@@ -8797,7 +8842,7 @@ (define_insn "*neg<mode>2_cc"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "lc<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lcxbr, lcdbr, lcebr
 (define_insn "*neg<mode>2_cconly"
@@ -8808,7 +8853,7 @@ (define_insn "*neg<mode>2_cconly"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "lc<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lcdfr
 (define_insn "*neg<mode>2_nocc"
@@ -8817,7 +8862,7 @@ (define_insn "*neg<mode>2_nocc"
   "TARGET_DFP"
   "lcdfr\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lcxbr, lcdbr, lcebr
 ; FIXME: wflcdb does not clobber cc
@@ -8833,7 +8878,7 @@ (define_insn "*neg<mode>2"
    wflcsb\t%0,%1"
   [(set_attr "op_type"      "RRE,VRR,VRR")
    (set_attr "cpu_facility" "*,vx,vxe")
-   (set_attr "type"         "fsimp<mode>,*,*")
+   (set_attr "type"         "fsimp<type>,*,*")
    (set_attr "enabled"      "*,<DF>,<SF>")])
 
 
@@ -8901,10 +8946,10 @@ (define_insn "abs<mode>2"
    (set_attr "z10prop" "z10_c")])
 
 ;
-; abs(df|sf)2 instruction pattern(s).
+; abs(tf|df|sf)2 instruction pattern(s).
 ;
 
-(define_expand "abs<mode>2"
+(define_expand "abs<mode>2<tf_fpr>"
   [(parallel
     [(set (match_operand:BFP 0 "register_operand" "=f")
           (abs:BFP (match_operand:BFP 1 "register_operand" "f")))
@@ -8922,7 +8967,7 @@ (define_insn "*abs<mode>2_cc"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "lp<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lpxbr, lpdbr, lpebr
 (define_insn "*abs<mode>2_cconly"
@@ -8933,7 +8978,7 @@ (define_insn "*abs<mode>2_cconly"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "lp<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lpdfr
 (define_insn "*abs<mode>2_nocc"
@@ -8942,7 +8987,7 @@ (define_insn "*abs<mode>2_nocc"
   "TARGET_DFP"
   "lpdfr\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lpxbr, lpdbr, lpebr
 ; FIXME: wflpdb does not clobber cc
@@ -8956,7 +9001,7 @@ (define_insn "*abs<mode>2"
     wflpdb\t%0,%1"
   [(set_attr "op_type"      "RRE,VRR")
    (set_attr "cpu_facility" "*,vx")
-   (set_attr "type"         "fsimp<mode>,*")
+   (set_attr "type"         "fsimp<type>,*")
    (set_attr "enabled"      "*,<DFDI>")])
 
 
@@ -9038,7 +9083,7 @@ (define_insn "*negabs<mode>2_cc"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "ln<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lnxbr, lndbr, lnebr
 (define_insn "*negabs<mode>2_cconly"
@@ -9049,7 +9094,7 @@ (define_insn "*negabs<mode>2_cconly"
   "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
   "ln<xde>br\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lndfr
 (define_insn "*negabs<mode>2_nocc"
@@ -9058,7 +9103,7 @@ (define_insn "*negabs<mode>2_nocc"
   "TARGET_DFP"
   "lndfr\t%0,%1"
   [(set_attr "op_type"  "RRE")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 ; lnxbr, lndbr, lnebr
 ; FIXME: wflndb does not clobber cc
@@ -9072,7 +9117,7 @@ (define_insn "*negabs<mode>2"
    wflndb\t%0,%1"
   [(set_attr "op_type"      "RRE,VRR")
    (set_attr "cpu_facility" "*,vx")
-   (set_attr "type"         "fsimp<mode>,*")
+   (set_attr "type"         "fsimp<type>,*")
    (set_attr "enabled"      "*,<DFDI>")])
 
 ;;
@@ -9084,7 +9129,7 @@ (define_insn "*negabs<mode>2"
 ;
 
 ; sqxbr, sqdbr, sqebr, sqdb, sqeb
-(define_insn "sqrt<mode>2"
+(define_insn "sqrt<mode>2<tf_fpr>"
   [(set (match_operand:BFP           0 "register_operand" "=f,f,v")
 	(sqrt:BFP (match_operand:BFP 1 "general_operand"   "f,R,v")))]
   "TARGET_HARD_FLOAT"
@@ -9093,7 +9138,7 @@ (define_insn "sqrt<mode>2"
    sq<xde>b\t%0,%1
    wfsqdb\t%v0,%v1"
   [(set_attr "op_type"      "RRE,RXE,VRR")
-   (set_attr "type"         "fsqrt<mode>")
+   (set_attr "type"         "fsqrt<type>")
    (set_attr "cpu_facility" "*,*,vx")
    (set_attr "enabled"      "*,<DSF>,<DFDI>")])
 
@@ -9294,8 +9339,8 @@ (define_expand "cbranch<mode>4"
 (define_expand "cbranch<mode>4"
   [(set (pc)
         (if_then_else (match_operator 0 "comparison_operator"
-        	       [(match_operand:FP 1 "register_operand" "")
-                        (match_operand:FP 2 "general_operand" "")])
+		       [(match_operand:FP_ANYTF 1 "register_operand" "")
+			(match_operand:FP_ANYTF 2 "general_operand" "")])
 		      (label_ref (match_operand 3 "" ""))
                       (pc)))]
   "TARGET_HARD_FLOAT"
@@ -11790,7 +11835,7 @@ (define_expand "popcountqi2"
 ;;- Copy sign instructions
 ;;
 
-(define_insn "copysign<mode>3"
+(define_insn "copysign<mode>3<tf_fpr>"
   [(set (match_operand:FP 0 "register_operand" "=f")
       (unspec:FP [(match_operand:FP 1 "register_operand" "<fT0>")
                   (match_operand:FP 2 "register_operand" "f")]
@@ -11798,7 +11843,7 @@ (define_insn "copysign<mode>3"
   "TARGET_Z196"
   "cpsdr\t%0,%2,%1"
   [(set_attr "op_type"  "RRF")
-   (set_attr "type"     "fsimp<mode>")])
+   (set_attr "type"     "fsimp<type>")])
 
 
 ;;
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index 300309cddda..0afcea3c3fe 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -304,3 +304,14 @@ mnop-mcount
 Target Report Var(flag_nop_mcount)
 Generate mcount/__fentry__ calls as nops. To activate they need to be
 patched in.
+
+mvx-long-double-fma
+Target Report Undocumented Var(flag_vx_long_double_fma)
+Emit fused multiply-add instructions for long doubles in vector registers
+(wfmaxb, wfmsxb, wfnmaxb, wfnmsxb).  Reassociation pass does not handle
+fused multiply-adds, therefore code generated by the middle-end is prone to
+having long fused multiply-add chains.  This is not pipeline-friendly,
+and the default behavior is to emit separate multiplication and addition
+instructions for long doubles in vector registers, because measurements show
+that this improves performance.  This option allows overriding it for testing
+purposes.
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 3e621daf7b1..03c04f1c93a 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -27,10 +27,14 @@ (define_mode_iterator VT
    V2SF V4SF V1DF V2DF V1TF V1TI TI])
 
 ; All modes directly supported by the hardware having full vector reg size
-; V_HW2 is duplicate of V_HW for having two iterators expanding
-; independently e.g. vcond
-(define_mode_iterator V_HW  [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
-(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
+; V_HW2 is for having two iterators expanding independently e.g. vcond.
+; It's similar to V_HW, but not fully identical: V1TI is not included, because
+; there are no 128-bit compares.
+(define_mode_iterator V_HW  [V16QI V8HI V4SI V2DI (V1TI "TARGET_VXE") V2DF
+			     (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")
+			     (TF "TARGET_VXE")])
+(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE")
+			     (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
 
 (define_mode_iterator V_HW_64 [V2DI V2DF])
 (define_mode_iterator VT_HW_HSDT [V8HI V4SI V4SF V2DI V2DF V1TI V1TF TI TF])
@@ -55,19 +59,20 @@ (define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI
 
 (define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
 			   V1DF V2DF
-			   (V1TF "TARGET_VXE")])
+			   (V1TF "TARGET_VXE") (TF "TARGET_VXE")])
 
 ; FP vector modes directly supported by the HW.  This does not include
 ; vector modes using only part of a vector register and should be used
 ; for instructions which might trigger IEEE exceptions.
-(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")])
+(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")
+			     (TF "TARGET_VXE")])
 
 (define_mode_iterator V_8   [V1QI])
 (define_mode_iterator V_16  [V2QI  V1HI])
 (define_mode_iterator V_32  [V4QI  V2HI V1SI V1SF])
 (define_mode_iterator V_64  [V8QI  V4HI V2SI V2SF V1DI V1DF])
-(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF])
-
+(define_mode_iterator V_128 [V16QI V8HI V4SI V4SF V2DI V2DF V1TI V1TF
+			     (TF "TARGET_VXE")])
 (define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
 
 ; 32 bit int<->fp vector conversion instructions are available since VXE2 (z15).
@@ -86,6 +91,11 @@ (define_mode_attr ti* [(V1QI "")  (V2QI "") (V4QI "") (V8QI "") (V16QI "")
 		       (V1DF "")  (V2DF "")
 		       (V1TF "")  (TF "")])
 
+;; Facilitate dispatching TFmode expanders on z14+.
+(define_mode_attr tf_vr [(TF "_vr") (V4SF "") (V2DF "") (V1TF "") (V1SF "")
+			 (V2SF "") (V1DF "") (V16QI "") (V8HI "") (V4SI "")
+			 (V2DI "") (V1TI "")])
+
 ; The element type of the vector.
 (define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI")
 			  (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI")
@@ -134,7 +144,7 @@ (define_mode_attr tointvec [(V1QI "V1QI") (V2QI "V2QI") (V4QI "V4QI") (V8QI "V8Q
 			    (V1TI "V1TI")
 			    (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
 			    (V1DF "V1DI") (V2DF "V2DI")
-			    (V1TF "V1TI")])
+			    (V1TF "V1TI") (TF "V1TI")])
 (define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
 		      (DF "w") (V1DF "w") (V2DF "v")
 		      (TF "w") (V1TF "w")])
@@ -194,7 +204,7 @@ (define_constants
 ; for TImode (use double-int for the calculations)
 
 ; vgmb, vgmh, vgmf, vgmg, vrepib, vrepih, vrepif, vrepig
-(define_insn "mov<mode>"
+(define_insn "mov<mode><tf_vr>"
   [(set (match_operand:V_128 0 "nonimmediate_operand" "=v,v,R,  v,  v,  v,  v,  v,v,*d,*d,?o")
 	(match_operand:V_128 1 "general_operand"      " v,R,v,j00,jm1,jyy,jxx,jKK,d, v,dT,*d"))]
   ""
@@ -214,6 +224,12 @@ (define_insn "mov<mode>"
   [(set_attr "cpu_facility" "vx,vx,vx,vx,vx,vx,vx,vx,vx,vx,*,*")
    (set_attr "op_type"      "VRR,VRX,VRX,VRI,VRI,VRI,VRI,VRI,VRR,*,*,*")])
 
+(define_expand "movtf"
+  [(match_operand:TF 0 "nonimmediate_operand" "")
+   (match_operand:TF 1 "general_operand"      "")]
+  ""
+  { EXPAND_MOVTF(movtf); })
+
 ; VR -> GPR, no instruction so split it into 64 element sets.
 (define_split
   [(set (match_operand:V_128 0 "register_operand" "")
@@ -565,10 +581,10 @@ (define_insn "*vec_splats_bswap_elem<mode>"
 
 ; A TFmode operand resides in FPR register pairs while V1TF is in a
 ; single vector register.
-(define_insn "*vec_tf_to_v1tf"
+(define_insn "*vec_tf_to_v1tf_fpr"
   [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
 	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "f,R,f,G,d")))]
-  "TARGET_VX"
+  "TARGET_VX && !TARGET_VXE"
   "@
    vmrhg\t%v0,%1,%N1
    vl\t%v0,%1%A1
@@ -577,6 +593,26 @@ (define_insn "*vec_tf_to_v1tf"
    vlvgp\t%v0,%1,%N1"
   [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
 
+; Both TFmode and V1TFmode operands reside in vector registers.
+(define_insn "*vec_tf_to_v1tf_vr"
+  [(set (match_operand:V1TF                   0 "nonimmediate_operand" "=v,v,R,v,v")
+	(vec_duplicate:V1TF (match_operand:TF 1 "general_operand"       "v,R,v,G,d")))]
+  "TARGET_VXE"
+  "@
+   vlr\t%v0,%1
+   vl\t%v0,%1%A1
+   vst\t%v1,%0%A0
+   vzero\t%v0
+   vlvgp\t%v0,%1,%N1"
+  [(set_attr "op_type" "VRR,VRX,VRX,VRI,VRR")])
+
+(define_insn "*fprx2_to_tf"
+  [(set (match_operand:TF               0 "nonimmediate_operand" "=v")
+	(subreg:TF (match_operand:FPRX2 1 "general_operand"       "f") 0))]
+  "TARGET_VXE"
+  "vmrhg\t%v0,%1,%N1"
+  [(set_attr "op_type" "VRR")])
+
 (define_insn "*vec_ti_to_v1ti"
   [(set (match_operand:V1TI                   0 "nonimmediate_operand" "=v,v,R,  v,  v,v")
 	(vec_duplicate:V1TI (match_operand:TI 1 "general_operand"       "v,R,v,j00,jm1,d")))]
@@ -691,6 +727,21 @@ (define_insn "*vec_perm<mode>"
   "vperm\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
+(define_insn "*mov_tf_to_fprx2_0"
+  [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "=f") 0)
+	(subreg:DF (match_operand:TF    1 "general_operand"       "v") 0))]
+  "TARGET_VXE"
+  ; M4 == 1 corresponds to %v0[0] = %v1[0]; %v0[1] = %v0[1];
+  "vpdi\t%v0,%v1,%v0,1"
+  [(set_attr "op_type" "VRR")])
+
+(define_insn "*mov_tf_to_fprx2_1"
+  [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "=f") 8)
+	(subreg:DF (match_operand:TF    1 "general_operand"       "v") 8))]
+  "TARGET_VXE"
+  ; M4 == 5 corresponds to %V0[0] = %v1[1]; %V0[1] = %V0[1];
+  "vpdi\t%V0,%v1,%V0,5"
+  [(set_attr "op_type" "VRR")])
 
 ; vec_perm_const for V2DI using vpdi?
 
@@ -1253,7 +1304,7 @@ (define_expand "vec_widen_smult_hi_<mode>"
 ;;
 
 ; vfasb, vfadb, wfasb, wfadb, wfaxb
-(define_insn "add<mode>3"
+(define_insn "add<mode>3<tf_vr>"
   [(set (match_operand:VF_HW             0 "register_operand" "=v")
 	(plus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		    (match_operand:VF_HW 2 "register_operand"  "v")))]
@@ -1261,8 +1312,15 @@ (define_insn "add<mode>3"
   "<vw>fa<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "addtf3"
+  [(match_operand:TF 0 "register_operand"     "")
+   (match_operand:TF 1 "nonimmediate_operand" "")
+   (match_operand:TF 2 "general_operand"      "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(addtf3, 3); })
+
 ; vfssb, vfsdb, wfssb, wfsdb, wfsxb
-(define_insn "sub<mode>3"
+(define_insn "sub<mode>3<tf_vr>"
   [(set (match_operand:VF_HW              0 "register_operand" "=v")
 	(minus:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		     (match_operand:VF_HW 2 "register_operand"  "v")))]
@@ -1270,8 +1328,15 @@ (define_insn "sub<mode>3"
   "<vw>fs<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "subtf3"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")
+   (match_operand:TF 2 "general_operand"  "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(subtf3, 3); })
+
 ; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
-(define_insn "mul<mode>3"
+(define_insn "mul<mode>3<tf_vr>"
   [(set (match_operand:VF_HW             0 "register_operand" "=v")
 	(mult:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		    (match_operand:VF_HW 2 "register_operand"  "v")))]
@@ -1279,8 +1344,15 @@ (define_insn "mul<mode>3"
   "<vw>fm<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "multf3"
+  [(match_operand:TF 0 "register_operand"     "")
+   (match_operand:TF 1 "nonimmediate_operand" "")
+   (match_operand:TF 2 "general_operand"      "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(multf3, 3); })
+
 ; vfdsb, vfddb, wfdsb, wfddb, wfdxb
-(define_insn "div<mode>3"
+(define_insn "div<mode>3<tf_vr>"
   [(set (match_operand:VF_HW            0 "register_operand" "=v")
 	(div:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		   (match_operand:VF_HW 2 "register_operand"  "v")))]
@@ -1288,21 +1360,34 @@ (define_insn "div<mode>3"
   "<vw>fd<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "divtf3"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")
+   (match_operand:TF 2 "general_operand"  "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(divtf3, 3); })
+
 ; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
-(define_insn "sqrt<mode>2"
-  [(set (match_operand:VF_HW           0 "register_operand" "=v")
+(define_insn "sqrt<mode>2<tf_vr>"
+  [(set (match_operand:VF_HW             0 "register_operand" "=v")
 	(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")))]
   "TARGET_VX"
   "<vw>fsq<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "sqrttf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "general_operand"  "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(sqrttf2, 2); })
+
 ; vfmasb, vfmadb, wfmasb, wfmadb, wfmaxb
 (define_insn "fma<mode>4"
   [(set (match_operand:VF_HW            0 "register_operand" "=v")
 	(fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		   (match_operand:VF_HW 2 "register_operand"  "v")
 		   (match_operand:VF_HW 3 "register_operand"  "v")))]
-  "TARGET_VX"
+  "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
   "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
@@ -1312,7 +1397,7 @@ (define_insn "fms<mode>4"
 	(fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
 		   (match_operand:VF_HW          2 "register_operand"  "v")
 		 (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v"))))]
-  "TARGET_VX"
+  "TARGET_VX && s390_fma_allowed_p (<MODE>mode)"
   "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
@@ -1323,7 +1408,7 @@ (define_insn "neg_fma<mode>4"
 	 (fma:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")
 		    (match_operand:VF_HW 2 "register_operand"  "v")
 		    (match_operand:VF_HW 3 "register_operand"  "v"))))]
-  "TARGET_VXE"
+  "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
   "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
@@ -1334,26 +1419,38 @@ (define_insn "neg_fms<mode>4"
 	 (fma:VF_HW (match_operand:VF_HW          1 "register_operand"  "v")
 		    (match_operand:VF_HW          2 "register_operand"  "v")
 		  (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v")))))]
-  "TARGET_VXE"
+  "TARGET_VXE && s390_fma_allowed_p (<MODE>mode)"
   "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
 ; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
-(define_insn "neg<mode>2"
+(define_insn "neg<mode>2<tf_vr>"
   [(set (match_operand:VFT          0 "register_operand" "=v")
 	(neg:VFT (match_operand:VFT 1 "register_operand"  "v")))]
   "TARGET_VX"
   "<vw>flc<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "negtf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(negtf2, 2); })
+
 ; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
-(define_insn "abs<mode>2"
+(define_insn "abs<mode>2<tf_vr>"
   [(set (match_operand:VFT          0 "register_operand" "=v")
 	(abs:VFT (match_operand:VFT 1 "register_operand"  "v")))]
   "TARGET_VX"
   "<vw>flp<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
+(define_expand "abstf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(abstf2, 2); })
+
 ; vflnsb, vflndb, wflnsb, wflndb, wflnxb
 (define_insn "negabs<mode>2"
   [(set (match_operand:VFT                   0 "register_operand" "=v")
@@ -2152,6 +2249,24 @@ (define_insn "float<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
   "vc<VX_VEC_CONV_BFP:xde><VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
   [(set_attr "op_type" "VRR")])
 
+; There is no instruction for loading a signed integer into an extended BFP
+; operand in a VR, therefore we need to load it into a FPR pair first.
+(define_expand "float<mode>tf2_vr"
+  [(set (match_dup 2)
+	(float:FPRX2 (match_operand:DSI 1 "register_operand" "")))
+   (set (match_operand:TF               0 "register_operand" "")
+	(subreg:TF (match_dup 2) 0))]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "float<mode>tf2"
+  [(match_operand:TF  0 "register_operand" "")
+   (match_operand:DSI 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(float<mode>tf2, 2); })
+
 ; unsigned integer to floating point
 
 ; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2165,6 +2280,24 @@ (define_insn "floatuns<VX_VEC_CONV_INT:mode><VX_VEC_CONV_BFP:mode>2"
   "vc<VX_VEC_CONV_BFP:xde>l<VX_VEC_CONV_INT:bhfgq>b\t%v0,%v1,0,0"
   [(set_attr "op_type" "VRR")])
 
+; There is no instruction for loading an unsigned integer into an extended BFP
+; operand in a VR, therefore load it into a FPR pair first.
+(define_expand "floatuns<mode>tf2_vr"
+  [(set (match_dup 2)
+	(unsigned_float:FPRX2 (match_operand:GPR 1 "register_operand" "")))
+   (set (match_operand:TF                        0 "register_operand" "")
+	(subreg:TF (match_dup 2) 0))]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "floatuns<mode>tf2"
+  [(match_operand:TF  0 "register_operand" "")
+   (match_operand:GPR 1 "register_operand" "")]
+  "(TARGET_Z196 && TARGET_HARD_FLOAT) || TARGET_VXE"
+  { EXPAND_TF(floatuns<mode>tf2, 2); })
+
 ; floating point to signed integer
 
 ; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2178,6 +2311,27 @@ (define_insn "fix_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
   "vc<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
   [(set_attr "op_type" "VRR")])
 
+; There is no instruction for rounding an extended BFP operand in a VR into
+; a signed integer, therefore copy it into a FPR pair first.
+(define_expand "fix_trunctf<mode>2_vr"
+  [(set (subreg:DF (match_dup 2) 0)
+	(subreg:DF (match_operand:TF 1 "register_operand" "") 0))
+   (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+   (parallel [(set (match_operand:GPR 0 "register_operand" "")
+		   (fix:GPR (match_dup 2)))
+	      (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
+	      (clobber (reg:CC CC_REGNUM))])]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "fix_trunctf<mode>2"
+  [(match_operand:GPR 0 "register_operand" "")
+   (match_operand:TF  1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(fix_trunctf<mode>2, 2); })
+
 ; floating point to unsigned integer
 
 ; op2: inexact exception not suppressed (IEEE 754 2008)
@@ -2191,6 +2345,186 @@ (define_insn "fixuns_trunc<VX_VEC_CONV_BFP:mode><VX_VEC_CONV_INT:mode>2"
   "vcl<VX_VEC_CONV_INT:bhfgq><VX_VEC_CONV_BFP:xde>b\t%v0,%v1,0,5"
   [(set_attr "op_type" "VRR")])
 
+; There is no instruction for rounding an extended BFP operand in a VR into
+; an unsigned integer, therefore copy it into a FPR pair first.
+(define_expand "fixuns_trunctf<mode>2_vr"
+  [(set (subreg:DF (match_dup 2) 0)
+	(subreg:DF (match_operand:TF 1 "register_operand" "") 0))
+   (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+   (parallel [(set (match_operand:GPR 0 "register_operand" "")
+		   (unsigned_fix:GPR (match_dup 2)))
+	      (unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
+	      (clobber (reg:CC CC_REGNUM))])]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx (FPRX2mode);
+})
+
+(define_expand "fixuns_trunctf<mode>2"
+  [(match_operand:GPR 0 "register_operand" "")
+   (match_operand:TF  1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(fixuns_trunctf<mode>2, 2); })
+
+; load fp integer
+
+; vfisb, wfisb, vfidb, wfidb, wfixb; suppress inexact exceptions
+(define_insn "<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>"
+  [(set (match_operand:VF_HW                0 "register_operand" "=v")
+	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"  "v")]
+		      FPINT))]
+  "TARGET_VX"
+  "<vw>fi<VF_HW:sdx>b\t%v0,%v1,4,<FPINT:fpint_roundingmode>"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "<FPINT:fpint_name>tf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")
+   ; recognize FPINT as an iterator
+   (unspec:TF [(match_dup 1)] FPINT)]
+  "TARGET_Z196 || TARGET_VXE"
+  { EXPAND_TF(<FPINT:fpint_name>tf2, 2); })
+
+; vfisb, wfisb, vfidb, wfidb, wfixb; raise inexact exceptions
+(define_insn "rint<mode>2<tf_vr>"
+  [(set (match_operand:VF_HW                0 "register_operand" "=v")
+	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"  "v")]
+		      UNSPEC_FPINT_RINT))]
+  "TARGET_VX"
+  "<vw>fi<sdx>b\t%v0,%v1,0,0"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "rinttf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  ""
+  { EXPAND_TF(rinttf2, 2); })
+
+; load rounded
+
+; wflrx
+(define_insn "*trunctfdf2_vr"
+  [(set (match_operand:DF                    0 "register_operand" "=f")
+	(float_truncate:DF (match_operand:TF 1 "register_operand"  "v")))
+   (unspec:DF [(match_operand                2 "const_int_operand" "")]
+	       UNSPEC_ROUND)]
+  "TARGET_VXE"
+  "wflrx\t%v0,%v1,0,%2"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "trunctfdf2_vr"
+  [(parallel [
+     (set (match_operand:DF                    0 "register_operand" "")
+	  (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
+     (unspec:DF [(const_int BFP_RND_CURRENT)] UNSPEC_ROUND)])]
+  "TARGET_VXE")
+
+(define_expand "trunctfdf2"
+  [(match_operand:DF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(trunctfdf2, 2); })
+
+; wflrx + (ledbr|wledb)
+(define_expand "trunctfsf2_vr"
+  [(parallel [
+     (set (match_dup 2)
+	  (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
+     (unspec:DF [(const_int BFP_RND_PREP_FOR_SHORT_PREC)] UNSPEC_ROUND)])
+   (set (match_operand:SF                    0 "register_operand" "")
+	(float_truncate:SF (match_dup 2)))]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx(DFmode);
+})
+
+(define_expand "trunctfsf2"
+  [(match_operand:SF 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(trunctfsf2, 2); })
+
+; load lengthened
+
+(define_insn "extenddftf2_vr"
+  [(set (match_operand:TF                  0 "register_operand" "=v")
+	(float_extend:TF (match_operand:DF 1 "register_operand"  "f")))]
+  "TARGET_VXE"
+  "wflld\t%v0,%v1"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "extenddftf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:DF 1 "nonimmediate_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(extenddftf2, 2); })
+
+(define_expand "extendsftf2_vr"
+  [(set (match_dup 2)
+	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
+   (set (match_operand:TF                  0 "register_operand"     "")
+	(float_extend:TF (match_dup 2)))]
+  "TARGET_VXE"
+{
+  operands[2] = gen_reg_rtx(DFmode);
+})
+
+(define_expand "extendsftf2"
+  [(match_operand:TF 0 "register_operand" "")
+   (match_operand:SF 1 "nonimmediate_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(extendsftf2, 2); })
+
+; test data class
+
+(define_expand "signbittf2_vr"
+  [(parallel
+    [(set (reg:CCRAW CC_REGNUM)
+	  (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
+			 (match_dup        2)]
+			UNSPEC_VEC_VFTCICC))
+     (clobber (scratch:V1TI))])
+   (set (match_operand:SI                  0 "register_operand" "")
+	(const_int 0))
+   (set (match_dup                         0)
+	(if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
+			 (const_int 1)
+			 (match_dup        0)))]
+  "TARGET_VXE"
+{
+  operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
+})
+
+(define_expand "signbittf2"
+  [(match_operand:SI 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(signbittf2, 2); })
+
+(define_expand "isinftf2_vr"
+  [(parallel
+    [(set (reg:CCRAW CC_REGNUM)
+	  (unspec:CCRAW [(match_operand:TF 1 "register_operand" "")
+			 (match_dup        2)]
+			UNSPEC_VEC_VFTCICC))
+     (clobber (scratch:V1TI))])
+   (set (match_operand:SI                  0 "register_operand" "")
+	(const_int 0))
+   (set (match_dup                         0)
+	(if_then_else:SI (eq (reg:CCRAW CC_REGNUM) (const_int 8))
+			 (const_int 1)
+			 (match_dup        0)))]
+  "TARGET_VXE"
+{
+  operands[2] = GEN_INT (S390_TDC_INFINITY);
+})
+
+(define_expand "isinftf2"
+  [(match_operand:SI 0 "register_operand" "")
+   (match_operand:TF 1 "register_operand" "")]
+  "TARGET_HARD_FLOAT"
+  { EXPAND_TF(isinftf2, 2); })
+
 ;
 ; Vector byte swap patterns
 ;
diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md
index 6f1add02d0b..010db4d1115 100644
--- a/gcc/config/s390/vx-builtins.md
+++ b/gcc/config/s390/vx-builtins.md
@@ -1940,22 +1940,22 @@ (define_expand "vec_st2f"
 ; These ignore the vector result and only want CC stored to an int
 ; pointer.
 
-; vftcisb, vftcidb
+; vftcisb, vftcidb, wftcixb
 (define_insn "*vftci<mode>_cconly"
   [(set (reg:CCRAW CC_REGNUM)
-	(unspec:CCRAW [(match_operand:VECF_HW 1 "register_operand")
-		       (match_operand:HI      2 "const_int_operand")]
+	(unspec:CCRAW [(match_operand:VF_HW 1 "register_operand"  "v")
+		       (match_operand:HI    2 "const_int_operand" "J")]
 		      UNSPEC_VEC_VFTCICC))
-   (clobber (match_scratch:<tointvec> 0))]
+   (clobber (match_scratch:<tointvec> 0 "=v"))]
   "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
-  "vftci<sdx>b\t%v0,%v1,%x2"
+  "<vw>ftci<sdx>b\t%v0,%v1,%x2"
   [(set_attr "op_type" "VRR")])
 
 (define_expand "vftci<mode>_intcconly"
   [(parallel
     [(set (reg:CCRAW CC_REGNUM)
-	  (unspec:CCRAW [(match_operand:VECF_HW 0 "register_operand")
-			 (match_operand:HI      1 "const_int_operand")]
+	  (unspec:CCRAW [(match_operand:VF_HW 0 "register_operand")
+			 (match_operand:HI    1 "const_int_operand")]
 			UNSPEC_VEC_VFTCICC))
      (clobber (scratch:<tointvec>))])
    (set (match_operand:SI 2 "register_operand" "")
@@ -1965,27 +1965,27 @@ (define_expand "vftci<mode>_intcconly"
 ; vec_fp_test_data_class wants the result vector and the CC stored to
 ; an int pointer.
 
-; vftcisb, vftcidb
-(define_insn "*vftci<mode>"
-  [(set (match_operand:VECF_HW                  0 "register_operand"  "=v")
-	(unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand"   "v")
-			 (match_operand:HI      2 "const_int_operand"  "J")]
-			UNSPEC_VEC_VFTCI))
+; vftcisb, vftcidb, wftcixb
+(define_insn "vftci<mode>"
+  [(set (match_operand:VF_HW                0 "register_operand"  "=v")
+	(unspec:VF_HW [(match_operand:VF_HW 1 "register_operand"   "v")
+		       (match_operand:HI    2 "const_int_operand"  "J")]
+		      UNSPEC_VEC_VFTCI))
    (set (reg:CCRAW CC_REGNUM)
 	(unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))]
   "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")"
-  "vftci<sdx>b\t%v0,%v1,%x2"
+  "<vw>ftci<sdx>b\t%v0,%v1,%x2"
   [(set_attr "op_type" "VRR")])
 
 (define_expand "vftci<mode>_intcc"
   [(parallel
-    [(set (match_operand:VECF_HW                  0 "register_operand")
-	  (unspec:VECF_HW [(match_operand:VECF_HW 1 "register_operand")
-			   (match_operand:HI      2 "const_int_operand")]
-			  UNSPEC_VEC_VFTCI))
+    [(set (match_operand:VF_HW                0 "register_operand")
+	  (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand")
+			 (match_operand:HI    2 "const_int_operand")]
+			UNSPEC_VEC_VFTCI))
      (set (reg:CCRAW CC_REGNUM)
 	  (unspec:CCRAW [(match_dup 1) (match_dup 2)] UNSPEC_VEC_VFTCICC))])
-   (set (match_operand:SI 3 "memory_operand" "")
+   (set (match_operand:SI                     3 "nonimmediate_operand")
 	(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
   "TARGET_VX && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'J', \"J\")")
 
-- 
2.25.4


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

* [PATCH 4/4] IBM Z: Test long doubles in vector registers
  2020-11-03 21:36 [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
                   ` (2 preceding siblings ...)
  2020-11-03 21:45 ` [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
@ 2020-11-03 21:46 ` Ilya Leoshkevich
  2020-11-04 17:28   ` Andreas Krebbel
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-03 21:46 UTC (permalink / raw)
  To: krebbel; +Cc: gcc-patches, Ilya Leoshkevich

gcc/testsuite/ChangeLog:

2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>

	* gcc.target/s390/zvector/long-double-callee-abi-scan.c: New test.
	* gcc.target/s390/zvector/long-double-caller-abi-run.c: New test.
	* gcc.target/s390/zvector/long-double-caller-abi-scan.c: New test.
	* gcc.target/s390/zvector/long-double-copysign-run.c: New test.
	* gcc.target/s390/zvector/long-double-copysign-scan.c: New test.
	* gcc.target/s390/zvector/long-double-fprx2-constant.c: New test.
	* gcc.target/s390/zvector/long-double-from-double-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-double-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-float-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-float-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-i16-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-i16-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-i32-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-i32-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-i64-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-i64-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-i8-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-i8-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-u16-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-u16-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-u32-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-u32-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-u64-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-u64-scan.c: New test.
	* gcc.target/s390/zvector/long-double-from-u8-run.c: New test.
	* gcc.target/s390/zvector/long-double-from-u8-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-double-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-double-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-float-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-float-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-i16-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-i16-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-i32-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-i32-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-i64-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-i64-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-i8-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-i8-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-u16-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-u16-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-u32-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-u32-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-u64-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-u64-scan.c: New test.
	* gcc.target/s390/zvector/long-double-to-u8-run.c: New test.
	* gcc.target/s390/zvector/long-double-to-u8-scan.c: New test.
	* gcc.target/s390/zvector/long-double-vec-duplicate.c: New test.
	* gcc.target/s390/zvector/long-double-wf.h: New test.
	* gcc.target/s390/zvector/long-double-wfaxb-run.c: New test.
	* gcc.target/s390/zvector/long-double-wfaxb-scan.c: New test.
	* gcc.target/s390/zvector/long-double-wfaxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfcxb-0001.c: New test.
	* gcc.target/s390/zvector/long-double-wfcxb-0111.c: New test.
	* gcc.target/s390/zvector/long-double-wfcxb-1011.c: New test.
	* gcc.target/s390/zvector/long-double-wfcxb-1101.c: New test.
	* gcc.target/s390/zvector/long-double-wfdxb-run.c: New test.
	* gcc.target/s390/zvector/long-double-wfdxb-scan.c: New test.
	* gcc.target/s390/zvector/long-double-wfdxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfixb.c: New test.
	* gcc.target/s390/zvector/long-double-wfkxb-0111.c: New test.
	* gcc.target/s390/zvector/long-double-wfkxb-1011.c: New test.
	* gcc.target/s390/zvector/long-double-wfkxb-1101.c: New test.
	* gcc.target/s390/zvector/long-double-wflcxb.c: New test.
	* gcc.target/s390/zvector/long-double-wflpxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfmaxb-2.c: New test.
	* gcc.target/s390/zvector/long-double-wfmaxb-3.c: New test.
	* gcc.target/s390/zvector/long-double-wfmaxb-disabled.c: New test.
	* gcc.target/s390/zvector/long-double-wfmaxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfmsxb-disabled.c: New test.
	* gcc.target/s390/zvector/long-double-wfmsxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfmxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c: New test.
	* gcc.target/s390/zvector/long-double-wfnmaxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c: New test.
	* gcc.target/s390/zvector/long-double-wfnmsxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfsqxb.c: New test.
	* gcc.target/s390/zvector/long-double-wfsxb-1.c: New test.
	* gcc.target/s390/zvector/long-double-wfsxb.c: New test.
	* gcc.target/s390/zvector/long-double-wftcixb-1.c: New test.
	* gcc.target/s390/zvector/long-double-wftcixb.c: New test.
---
 .../zvector/long-double-callee-abi-scan.c     | 20 +++++++
 .../s390/zvector/long-double-caller-abi-run.c |  4 ++
 .../zvector/long-double-caller-abi-scan.c     | 13 ++++
 .../s390/zvector/long-double-copysign-run.c   | 14 +++++
 .../s390/zvector/long-double-copysign-scan.c  | 11 ++++
 .../s390/zvector/long-double-fprx2-constant.c | 11 ++++
 .../zvector/long-double-from-double-run.c     | 12 ++++
 .../zvector/long-double-from-double-scan.c    |  9 +++
 .../s390/zvector/long-double-from-float-run.c | 12 ++++
 .../zvector/long-double-from-float-scan.c     | 10 ++++
 .../s390/zvector/long-double-from-i16-run.c   | 12 ++++
 .../s390/zvector/long-double-from-i16-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-i32-run.c   | 12 ++++
 .../s390/zvector/long-double-from-i32-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-i64-run.c   | 12 ++++
 .../s390/zvector/long-double-from-i64-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-i8-run.c    | 12 ++++
 .../s390/zvector/long-double-from-i8-scan.c   | 11 ++++
 .../s390/zvector/long-double-from-u16-run.c   | 12 ++++
 .../s390/zvector/long-double-from-u16-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-u32-run.c   | 12 ++++
 .../s390/zvector/long-double-from-u32-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-u64-run.c   | 12 ++++
 .../s390/zvector/long-double-from-u64-scan.c  | 11 ++++
 .../s390/zvector/long-double-from-u8-run.c    | 12 ++++
 .../s390/zvector/long-double-from-u8-scan.c   | 11 ++++
 .../s390/zvector/long-double-to-double-run.c  | 12 ++++
 .../s390/zvector/long-double-to-double-scan.c |  9 +++
 .../s390/zvector/long-double-to-float-run.c   | 12 ++++
 .../s390/zvector/long-double-to-float-scan.c  | 10 ++++
 .../s390/zvector/long-double-to-i16-run.c     | 12 ++++
 .../s390/zvector/long-double-to-i16-scan.c    | 11 ++++
 .../s390/zvector/long-double-to-i32-run.c     | 12 ++++
 .../s390/zvector/long-double-to-i32-scan.c    | 11 ++++
 .../s390/zvector/long-double-to-i64-run.c     | 12 ++++
 .../s390/zvector/long-double-to-i64-scan.c    | 13 ++++
 .../s390/zvector/long-double-to-i8-run.c      | 12 ++++
 .../s390/zvector/long-double-to-i8-scan.c     | 11 ++++
 .../s390/zvector/long-double-to-u16-run.c     | 13 ++++
 .../s390/zvector/long-double-to-u16-scan.c    | 11 ++++
 .../s390/zvector/long-double-to-u32-run.c     | 13 ++++
 .../s390/zvector/long-double-to-u32-scan.c    | 11 ++++
 .../s390/zvector/long-double-to-u64-run.c     | 13 ++++
 .../s390/zvector/long-double-to-u64-scan.c    | 11 ++++
 .../s390/zvector/long-double-to-u8-run.c      | 13 ++++
 .../s390/zvector/long-double-to-u8-scan.c     | 11 ++++
 .../s390/zvector/long-double-vec-duplicate.c  | 13 ++++
 .../gcc.target/s390/zvector/long-double-wf.h  | 60 +++++++++++++++++++
 .../s390/zvector/long-double-wfaxb-run.c      | 11 ++++
 .../s390/zvector/long-double-wfaxb-scan.c     | 10 ++++
 .../s390/zvector/long-double-wfaxb.c          |  8 +++
 .../s390/zvector/long-double-wfcxb-0001.c     | 10 ++++
 .../s390/zvector/long-double-wfcxb-0111.c     | 10 ++++
 .../s390/zvector/long-double-wfcxb-1011.c     | 10 ++++
 .../s390/zvector/long-double-wfcxb-1101.c     | 10 ++++
 .../s390/zvector/long-double-wfdxb-run.c      | 11 ++++
 .../s390/zvector/long-double-wfdxb-scan.c     | 10 ++++
 .../s390/zvector/long-double-wfdxb.c          |  8 +++
 .../s390/zvector/long-double-wfixb.c          |  8 +++
 .../s390/zvector/long-double-wfkxb-0111.c     | 10 ++++
 .../s390/zvector/long-double-wfkxb-1011.c     | 10 ++++
 .../s390/zvector/long-double-wfkxb-1101.c     | 10 ++++
 .../s390/zvector/long-double-wflcxb.c         |  8 +++
 .../s390/zvector/long-double-wflpxb.c         |  8 +++
 .../s390/zvector/long-double-wfmaxb-2.c       | 24 ++++++++
 .../s390/zvector/long-double-wfmaxb-3.c       | 14 +++++
 .../zvector/long-double-wfmaxb-disabled.c     |  9 +++
 .../s390/zvector/long-double-wfmaxb.c         |  8 +++
 .../zvector/long-double-wfmsxb-disabled.c     |  9 +++
 .../s390/zvector/long-double-wfmsxb.c         |  8 +++
 .../s390/zvector/long-double-wfmxb.c          |  8 +++
 .../zvector/long-double-wfnmaxb-disabled.c    | 10 ++++
 .../s390/zvector/long-double-wfnmaxb.c        |  8 +++
 .../zvector/long-double-wfnmsxb-disabled.c    | 10 ++++
 .../s390/zvector/long-double-wfnmsxb.c        |  8 +++
 .../s390/zvector/long-double-wfsqxb.c         |  8 +++
 .../s390/zvector/long-double-wfsxb-1.c        | 21 +++++++
 .../s390/zvector/long-double-wfsxb.c          |  8 +++
 .../s390/zvector/long-double-wftcixb-1.c      | 15 +++++
 .../s390/zvector/long-double-wftcixb.c        |  8 +++
 80 files changed, 934 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c

diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
new file mode 100644
index 00000000000..005bfa9977a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-loops" } */
+#include <stdarg.h>
+
+__attribute__ ((noipa, used)) long double
+long_double_callee (long double x, int n, ...)
+{
+  long double sum = x;
+  va_list vl;
+  int i;
+
+  va_start (vl, n);
+  for (i = 0; i < n; i++)
+    sum += va_arg (vl, long double);
+  va_end (vl);
+
+  return sum;
+}
+
+/* { dg-final { scan-assembler-times {\n\tvl\t} 3 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
new file mode 100644
index 00000000000..d1756f5d34c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include "long-double-callee-abi-scan.c"
+#include "long-double-caller-abi-scan.c"
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
new file mode 100644
index 00000000000..ef690733fbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+long double long_double_callee (long double x, int n, ...);
+
+int
+main ()
+{
+  assert (long_double_callee (1.L, 2, 2.L, 3.L) == 6.L);
+}
+
+/* { dg-final { scan-assembler-times {\n\tvst\t} 3 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
new file mode 100644
index 00000000000..c874b64d78e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-copysign-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_copysign (1.1L, 2.2L) == 1.1L);
+  assert (long_double_copysign (1.1L, -2.2L) == -1.1L);
+  assert (long_double_copysign (-1.1L, 2.2L) == 1.1L);
+  assert (long_double_copysign (-1.1L, -2.2L) == -1.1L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
new file mode 100644
index 00000000000..6a44c0eff61
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_copysign (long double x, long double y)
+{
+  return __builtin_copysignl (x, y);
+}
+
+/* { dg-final { scan-assembler-times {\n\tvsel\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
new file mode 100644
index 00000000000..02a6a1f69c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mtune=z14 -funroll-loops" } */
+
+long double a;
+int d;
+void
+b ()
+{
+  for (int c = 0; c < d; ++c)
+    a = (a - c) / (c + 1);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
new file mode 100644
index 00000000000..7a960ad119d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-double-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_double (42.) == 42.L);
+  assert (long_double_from_double (-42.) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
new file mode 100644
index 00000000000..db9ba4534c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+__attribute__ ((noipa, used)) static long double
+long_double_from_double (double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
new file mode 100644
index 00000000000..41256b39abc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-float-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_float (42.F) == 42.L);
+  assert (long_double_from_float (-42.F) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
new file mode 100644
index 00000000000..4b9b570fcfb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+__attribute__ ((noipa, used)) static long double
+long_double_from_float (float x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tldebr\t} 1 } } */
+/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
new file mode 100644
index 00000000000..6c0fac93da5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-i16-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_i16 (42) == 42.L);
+  assert (long_double_from_i16 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
new file mode 100644
index 00000000000..18af4d82f57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_i16 (int16_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
new file mode 100644
index 00000000000..2baa6e156f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-i32-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_i32 (42) == 42.L);
+  assert (long_double_from_i32 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
new file mode 100644
index 00000000000..433b6bbffe5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_i32 (int32_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
new file mode 100644
index 00000000000..c6f460064e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-i64-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_i64 (42) == 42.L);
+  assert (long_double_from_i64 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
new file mode 100644
index 00000000000..f418dffd8b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_i64 (int64_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
new file mode 100644
index 00000000000..15c46d8a909
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-i8-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_i8 (42) == 42.L);
+  assert (long_double_from_i8 (-42) == -42.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
new file mode 100644
index 00000000000..7a8b3fdaad0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_i8 (int8_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
new file mode 100644
index 00000000000..495b3f9f18d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-u16-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_u16 (42) == 42.L);
+  assert (long_double_from_u16 (-42) == 65494.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
new file mode 100644
index 00000000000..b65e10269df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_u16 (uint16_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
new file mode 100644
index 00000000000..072ae99ef24
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-u32-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_u32 (42) == 42.L);
+  assert (long_double_from_u32 (-42) == 4294967254.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
new file mode 100644
index 00000000000..408e3d1b570
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_u32 (uint32_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
new file mode 100644
index 00000000000..6146c322611
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-u64-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_u64 (42) == 42.L);
+  assert (long_double_from_u64 (-42) == 18446744073709551574.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
new file mode 100644
index 00000000000..856912d5689
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_u64 (uint64_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlgbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
new file mode 100644
index 00000000000..d769d006499
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-from-u8-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_from_u8 (42) == 42.L);
+  assert (long_double_from_u8 (-42) == 214.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
new file mode 100644
index 00000000000..d1421d4322c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static long double
+long_double_from_u8 (uint8_t x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
new file mode 100644
index 00000000000..b68ce88529a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-double-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_double (42.L) == 42.);
+  assert (long_double_to_double (-42.L) == -42.);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
new file mode 100644
index 00000000000..78ce18b38c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+__attribute__ ((noipa, used)) static double
+long_double_to_double (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflrx\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
new file mode 100644
index 00000000000..70a8a3e7f73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-float-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_float (42.L) == 42.F);
+  assert (long_double_to_float (-42.L) == -42.F);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
new file mode 100644
index 00000000000..1f0b60a3f03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+__attribute__ ((noipa, used)) static float
+long_double_to_float (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\twflrx\t%v\d+,%v\d+,0,3\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tledbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
new file mode 100644
index 00000000000..2044baa45af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-i16-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_i16 (42.L) == 42);
+  assert (long_double_to_i16 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
new file mode 100644
index 00000000000..3c47ae97c39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static int16_t
+long_double_to_i16 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
new file mode 100644
index 00000000000..9f98ea39f6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-i32-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_i32 (42.L) == 42);
+  assert (long_double_to_i32 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
new file mode 100644
index 00000000000..978b4751bff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static int32_t
+long_double_to_i32 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
new file mode 100644
index 00000000000..f2a27ff4fec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-i64-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_i64 (42.L) == 42);
+  assert (long_double_to_i64 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
new file mode 100644
index 00000000000..38a212ac3c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static int64_t
+long_double_to_i64 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
+/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
new file mode 100644
index 00000000000..0e0624b2788
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-i8-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_i8 (42.L) == 42);
+  assert (long_double_to_i8 (-42.L) == -42);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
new file mode 100644
index 00000000000..d015b8a307b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static int8_t
+long_double_to_i8 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
new file mode 100644
index 00000000000..7bac113a04c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-u16-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_u16 (42.L) == 42);
+  /* Not (-42 & 0xffff) due to loss of precision.  */
+  assert (long_double_to_u16 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
new file mode 100644
index 00000000000..a7694ceb3ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static uint16_t
+long_double_to_u16 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
new file mode 100644
index 00000000000..b85038c0723
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-u32-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_u32 (42.L) == 42);
+  /* Not (-42 & 0xffffffff) due to loss of precision.  */
+  assert (long_double_to_u32 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
new file mode 100644
index 00000000000..ff97803d320
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static uint32_t
+long_double_to_u32 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
new file mode 100644
index 00000000000..e781637dac3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-u64-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_u64 (42.L) == 42);
+  /* Not (-42 & 0xffffffffffffffff) due to loss of precision.  */
+  assert (long_double_to_u64 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
new file mode 100644
index 00000000000..d97c0ec35dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static uint64_t
+long_double_to_u64 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclgxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
new file mode 100644
index 00000000000..7ae330b6aa1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-to-u8-scan.c"
+
+int
+main (void)
+{
+  assert (long_double_to_u8 (42.L) == 42);
+  /* Not (-42 & 0xff) due to loss of precision.  */
+  assert (long_double_to_u8 (-42.L) == 0);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
new file mode 100644
index 00000000000..0500bc1c946
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <stdint.h>
+
+__attribute__ ((noipa, used)) static uint8_t
+long_double_to_u8 (long double x)
+{
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
new file mode 100644
index 00000000000..2ce9da33b8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -funroll-loops -march=z14 -mtune=z14" } */
+
+long double a, b;
+double *c;
+long double *d;
+
+void
+e ()
+{
+  while (d != &a)
+    *d++ = b * *c++;
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
new file mode 100644
index 00000000000..a564fc62d47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
@@ -0,0 +1,60 @@
+#ifndef LONG_DOUBLE_WF_H
+#define LONG_DOUBLE_WF_H 1
+
+#include <math.h>
+
+#define ADD(x, y, z) ((x) + (z))
+#define DIV(x, y, z) ((x) / (z))
+#define FABSL(x, y, z) (fabsl (y))
+#define ISINFL(x, y, z) (isinfl (x) ? (y) : (z))
+#define MUL(x, y, z) ((x) * (z))
+#define MUL_ADD(x, y, z) ((x) * (y) + (z))
+#define MUL_SUB(x, y, z) ((x) * (y) - (z))
+#define NEG(x, y, z)                                                          \
+  ({                                                                          \
+    volatile long double r = -(y);                                            \
+    r;                                                                        \
+  })
+#define NEG_MUL_ADD(x, y, z) NEG (0, MUL_ADD (x, y, z), 0)
+#define NEG_MUL_SUB(x, y, z) NEG (0, MUL_SUB (x, y, z), 0)
+#define QUIET_IFEQUAL(x, y, z) ((x) == (y) ? (z) : 0)
+#define QUIET_IFGREATER(x, y, z) (__builtin_isgreater (x, y) ? (z) : 0)
+#define QUIET_IFLESS(x, y, z) (__builtin_isless (x, y) ? (z) : 0)
+#define QUIET_IFUNORDERED(x, y, z) (__builtin_isunordered (x, y) ? (z) : 0)
+#define SIGNALING_IFEQUAL(x, y, z) (((x) >= (y) && (x) <= (y)) ? (z) : 0)
+#define SIGNALING_IFGREATER(x, y, z) ((x) > (y) ? (z) : 0)
+#define SIGNALING_IFLESS(x, y, z) ((x) < (y) ? (z) : 0)
+#define ROUNDL(x, y, z) (roundl (y))
+#define SQRTL(x, y, z) (sqrtl (y))
+#define SUB(x, y, z) ((x) - (z))
+
+#define LONG_DOUBLE_WF(op)                                                    \
+  long double test (                                                          \
+      long double x0, long double x1, long double x2, long double x3,         \
+      long double x4, long double x5, long double x6, long double x7,         \
+      long double x8, long double x9, long double x10, long double x11,       \
+      long double x12, long double x13, long double x14, long double x15)     \
+  {                                                                           \
+    while (x15 < 1E+30)                                                       \
+      {                                                                       \
+	x0 = op (x1, x2, x3);                                                 \
+	x1 = op (x2, x3, x4) + 1;                                             \
+	x2 = op (x3, x4, x5) + 2;                                             \
+	x3 = op (x4, x5, x6) + 3;                                             \
+	x4 = op (x5, x6, x7) + 4;                                             \
+	x5 = op (x6, x7, x8) + 5;                                             \
+	x6 = op (x7, x8, x9) + 6;                                             \
+	x7 = op (x8, x9, x10) + 7;                                            \
+	x8 = op (x9, x10, x11) + 8;                                           \
+	x9 = op (x10, x11, x12) + 9;                                          \
+	x10 = op (x11, x12, x13) + 10;                                        \
+	x11 = op (x12, x13, x14) + 11;                                        \
+	x12 = op (x13, x14, x15) + 12;                                        \
+	x13 = op (x14, x15, x0) + 13;                                         \
+	x14 = op (x15, x0, x1) + 14;                                          \
+	x15 = op (x0, x1, x2) + 15;                                           \
+      }                                                                       \
+    return x15;                                                               \
+  }
+
+#endif
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
new file mode 100644
index 00000000000..de7770068ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-wfaxb-scan.c"
+
+int
+main (void)
+{
+  assert (wfaxb (1.11L, 2.22L, 3.33L) == 6.66L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
new file mode 100644
index 00000000000..2bbf408416a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+__attribute__ ((noipa, used)) static long double
+wfaxb (long double x, long double y, long double z)
+{
+  return x + y + z;
+}
+
+/* { dg-final { scan-assembler-times {\n\twfaxb\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
new file mode 100644
index 00000000000..354dbe226b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (ADD);
+
+/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
new file mode 100644
index 00000000000..d0a32d51902
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFUNORDERED);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jo == brc 0b0001, ...  */
+/* { dg-final { scan-assembler {\n\tjo\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
new file mode 100644
index 00000000000..04a34e7373c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFEQUAL);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jne == brc 0b0111, ...  */
+/* { dg-final { scan-assembler {\n\tjne\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
new file mode 100644
index 00000000000..f221a56ffb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFLESS);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jnl == brc 0b1011, ...  */
+/* { dg-final { scan-assembler {\n\tjnl\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
new file mode 100644
index 00000000000..d2353ebe30c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (QUIET_IFGREATER);
+
+/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
+/* jnh == brc 0b1101, ...  */
+/* { dg-final { scan-assembler {\n\tjnh\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
new file mode 100644
index 00000000000..7ac752dc289
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+#include "long-double-wfdxb-scan.c"
+
+int
+main (void)
+{
+  assert (wfdxb (2.22L, 1.11L, 2.L) == 1.L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
new file mode 100644
index 00000000000..31eea0f9329
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+__attribute__ ((noipa, used)) static long double
+wfdxb (long double x, long double y, long double z)
+{
+  return (x / y) / z;
+}
+
+/* { dg-final { scan-assembler-times {\n\twfdxb\t} 2 } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
new file mode 100644
index 00000000000..7d854cac1bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (DIV);
+
+/* { dg-final { scan-assembler {\n\twfdxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
new file mode 100644
index 00000000000..5e16ffa58e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (ROUNDL);
+
+/* { dg-final { scan-assembler {\n\twfixb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
new file mode 100644
index 00000000000..2e7b1c37d08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFEQUAL);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jne == brc 0b0111, ...  */
+/* { dg-final { scan-assembler {\n\tjne\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
new file mode 100644
index 00000000000..2d2020af842
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFLESS);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jnl == brc 0b1011, ...  */
+/* { dg-final { scan-assembler {\n\tjnl\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
new file mode 100644
index 00000000000..f17f83ca568
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SIGNALING_IFGREATER);
+
+/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
+/* jnh == brc 0b1101, ...  */
+/* { dg-final { scan-assembler {\n\tjnh\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
new file mode 100644
index 00000000000..c69161beca9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG);
+
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
new file mode 100644
index 00000000000..df3c1dbccb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (FABSL);
+
+/* { dg-final { scan-assembler {\n\twflpxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
new file mode 100644
index 00000000000..9335680a70c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+int a, c, d, f, k, l, m;
+long double b, e, g, h, i;
+double j;
+
+void
+n (void)
+{
+  while (m)
+    {
+      a = b * d;
+      b = c;
+      c = d * e + 2;
+      e = f + g + 4;
+      f = h + 6;
+      g = h * 0 + i + 7;
+      h = i + 9;
+      i = j * k + 0 + 10;
+      j = l;
+      m = a * b;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
new file mode 100644
index 00000000000..9cc2b85f673
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+long double a, c, d;
+int b;
+void
+e (void)
+{
+  while (d)
+    {
+      a = 0 * c + 0;
+      d = b;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
new file mode 100644
index 00000000000..c9e5a7b066c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
new file mode 100644
index 00000000000..fddad943f18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
new file mode 100644
index 00000000000..e78178b9a0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
new file mode 100644
index 00000000000..1fe71ecf09f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
new file mode 100644
index 00000000000..ce311f89db4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (MUL);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
new file mode 100644
index 00000000000..da8a73adcee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
new file mode 100644
index 00000000000..75b28137048
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_ADD);
+
+/* { dg-final { scan-assembler {\n\twfnmaxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
new file mode 100644
index 00000000000..9a07d049ed4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
+/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
new file mode 100644
index 00000000000..16b80890725
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (NEG_MUL_SUB);
+
+/* { dg-final { scan-assembler {\n\twfnmsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
new file mode 100644
index 00000000000..2f42483dfee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SQRTL);
+
+/* { dg-final { scan-assembler {\n\twfsqxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
new file mode 100644
index 00000000000..dd2f244a4eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+#include <assert.h>
+
+typedef float tf __attribute__ ((mode (TF)));
+static tf x;
+static tf y;
+
+__attribute__ ((noipa)) static tf
+sub (void)
+{
+  return x - y;
+}
+
+int
+main (void)
+{
+  x = 1.5L;
+  y = 2.5L;
+  assert (sub () == -1.0L);
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
new file mode 100644
index 00000000000..d27cf8ca3de
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (SUB);
+
+/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
new file mode 100644
index 00000000000..6915d8ed8a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=z14 -mzvector -mzarch" } */
+
+int a, b;
+
+void
+c (void)
+{
+  long double d;
+  a = d;
+  if (__builtin_isinf (d))
+    b = 0;
+}
+
+/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
new file mode 100644
index 00000000000..1134e26ee87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
+
+#include "long-double-wf.h"
+
+LONG_DOUBLE_WF (ISINFL);
+
+/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
-- 
2.25.4


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

* Re: [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs
  2020-11-03 21:36 ` [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs Ilya Leoshkevich
@ 2020-11-04 17:14   ` Andreas Krebbel
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-04 17:14 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 03.11.20 22:36, Ilya Leoshkevich wrote:
> gcc/ChangeLog:
> 
> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> 
> 	* config/s390/s390.md (RRe): Remove.
> 	(RXe): Remove.

Ok. Thanks!

Andreas

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

* Re: [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES
  2020-11-03 21:45 ` [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES Ilya Leoshkevich
@ 2020-11-04 17:14   ` Andreas Krebbel
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-04 17:14 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 03.11.20 22:45, Ilya Leoshkevich wrote:
> gcc/ChangeLog:
> 
> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> 
> 	* config/s390/s390.c (NR_C_MODES): Unhardcode.
> 	(s390_alloc_pool): Use size_t for iterating from 0 to
> 	NR_C_MODES.
> 	(s390_add_constant): Likewise.
> 	(s390_find_constant): Likewise.
> 	(s390_dump_pool): Likewise.
> 	(s390_free_pool): Likewise.

Ok. Thanks!

Andreas


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

* Re: [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible
  2020-11-03 21:45 ` [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
@ 2020-11-04 17:16   ` Andreas Krebbel
  2020-11-04 22:12     ` Ilya Leoshkevich
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-04 17:16 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 03.11.20 22:45, Ilya Leoshkevich wrote:
> On z14+, there are instructions for working with 128-bit floats (long
> doubles) in vector registers.  It's beneficial to use them instead of
> instructions that operate on floating point register pairs, because it
> allows to store 4 times more data in registers at a time, relieveing
> register pressure.  The performance of new instructions is almost the
> same.
> 
> Implement by storing TFmode values in vector registers on z14+.  Since
> not all operations are available with the new instructions, keep the old
> ones using the new FPRX2 mode, and convert between it and TFmode when
> necessary (this is called "forwarder" expanders below).  Change the
> existing TFmode expanders to call either new- or old-style ones
> depending on whether we are on z14+ or older machines ("dispatcher"
> expanders).
> 
> gcc/ChangeLog:
> 
> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> 
> 	* config/s390/s390-modes.def (FPRX2): New mode.
> 	* config/s390/s390-protos.h (s390_fma_allowed_p): New function.
> 	* config/s390/s390.c (s390_fma_allowed_p): Likewise.
> 	(s390_build_signbit_mask): Support 128-bit masks.
> 	(print_operand): Support printing the second word of a TFmode
> 	operand as vector register.
> 	(constant_modes): Add FPRX2mode.
> 	(s390_class_max_nregs): Return 1 for TFmode on z14+.
> 	(s390_is_fpr128): New function.
> 	(s390_is_vr128): Likewise.
> 	(s390_can_change_mode_class): Use s390_is_fpr128 and
> 	s390_is_vr128 in order to determine whether mode refers to a FPR
> 	pair or to a VR.
> 	* config/s390/s390.h (EXPAND_MOVTF): New macro.
> 	(EXPAND_TF): Likewise.
> 	* config/s390/s390.md (PFPO_OP_TYPE_FPRX2): PFPO_OP_TYPE_TF
> 	alias.
> 	(ALL): Add FPRX2.
> 	(FP_ALL): Add FPRX2 for z14+, restrict TFmode to z13-.
> 	(FP): Likewise.
> 	(FP_ANYTF): New mode iterator.
> 	(BFP): Add FPRX2 for z14+, restrict TFmode to z13-.
> 	(TD_TF): Likewise.
> 	(xde): Add FPRX2.
> 	(nBFP): Likewise.
> 	(nDFP): Likewise.
> 	(DSF): Likewise.
> 	(DFDI): Likewise.
> 	(SFSI): Likewise.
> 	(DF): Likewise.
> 	(SF): Likewise.
> 	(fT0): Likewise.
> 	(bt): Likewise.
> 	(_d): Likewise.
> 	(HALF_TMODE): Likewise.
> 	(tf_fpr): New mode_attr.
> 	(type): New mode_attr.
> 	(*cmp<mode>_ccz_0): Use type instead of mode with fsimp.
> 	(*cmp<mode>_ccs_0_fastmath): Likewise.
> 	(*cmptf_ccs): New pattern for wfcxb.
> 	(*cmptf_ccsfps): New pattern for wfkxb.
> 	(mov<mode>): Rename to mov<mode><tf_fpr>.
> 	(signbit<mode>2): Rename to signbit<mode>2<tf_fpr>.
> 	(isinf<mode>2): Renamed to isinf<mode>2<tf_fpr>.
> 	(*TDC_insn_<mode>): Use type instead of mode with fsimp.
> 	(fixuns_trunc<FP:mode><GPR:mode>2): Rename to
> 	fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>.
> 	(fix_trunctf<mode>2): Rename to fix_trunctf<mode>2_fpr.
> 	(floatdi<mode>2): Rename to floatdi<mode>2<tf_fpr>, use type
> 	instead of mode with itof.
> 	(floatsi<mode>2): Rename to floatsi<mode>2<tf_fpr>, use type
> 	instead of mode with itof.
> 	(*floatuns<GPR:mode><FP:mode>2): Use type instead of mode for
> 	itof.
> 	(floatuns<GPR:mode><FP:mode>2): Rename to
> 	floatuns<GPR:mode><FP:mode>2<tf_fpr>.
> 	(trunctf<mode>2): Rename to trunctf<mode>2_fpr, use type instead
> 	of mode with fsimp.
> 	(extend<DSF:mode><BFP:mode>2): Rename to
> 	extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>.
> 	(<FPINT:fpint_name><BFP:mode>2): Rename to
> 	<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>, use type instead of
> 	mode with fsimp.
> 	(rint<BFP:mode>2): Rename to rint<BFP:mode>2<BFP:tf_fpr>, use
> 	type instead of mode with fsimp.
> 	(<FPINT:fpint_name><DFP:mode>2): Use type instead of mode for
> 	fsimp.
> 	(rint<DFP:mode>2): Likewise.
> 	(trunc<BFP:mode><DFP_ALL:mode>2): Rename to
> 	trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
> 	(trunc<DFP_ALL:mode><BFP:mode>2): Rename to
> 	trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
> 	(extend<BFP:mode><DFP_ALL:mode>2): Rename to
> 	extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
> 	(extend<DFP_ALL:mode><BFP:mode>2): Rename to
> 	extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
> 	(add<mode>3): Rename to add<mode>3<tf_fpr>, use type instead of
> 	mode with fsimp.
> 	(*add<mode>3_cc): Use type instead of mode with fsimp.
> 	(*add<mode>3_cconly): Likewise.
> 	(sub<mode>3): Rename to sub<mode>3<tf_fpr>, use type instead of
> 	mode with fsimp.
> 	(*sub<mode>3_cc): Use type instead of mode with fsimp.
> 	(*sub<mode>3_cconly): Likewise.
> 	(mul<mode>3): Rename to mul<mode>3<tf_fpr>, use type instead of
> 	mode with fsimp.
> 	(fma<mode>4): Restrict using s390_fma_allowed_p.
> 	(fms<mode>4): Restrict using s390_fma_allowed_p.
> 	(div<mode>3): Rename to div<mode>3<tf_fpr>, use type instead of
> 	mode with fdiv.
> 	(neg<mode>2): Rename to neg<mode>2<tf_fpr>.
> 	(*neg<mode>2_cc): Use type instead of mode with fsimp.
> 	(*neg<mode>2_cconly): Likewise.
> 	(*neg<mode>2_nocc): Likewise.
> 	(*neg<mode>2): Likeiwse.
> 	(abs<mode>2): Rename to abs<mode>2<tf_fpr>, use type instead of
> 	mode with fdiv.
> 	(*abs<mode>2_cc): Use type instead of mode with fsimp.
> 	(*abs<mode>2_cconly): Likewise.
> 	(*abs<mode>2_nocc): Likewise.
> 	(*abs<mode>2): Likewise.
> 	(*negabs<mode>2_cc): Likewise.
> 	(*negabs<mode>2_cconly): Likewise.
> 	(*negabs<mode>2_nocc): Likewise.
> 	(*negabs<mode>2): Likewise.
> 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_fpr>, use type instead
> 	of mode with fsqrt.
> 	(cbranch<mode>4): Use FP_ANYTF instead of FP.
> 	(copysign<mode>3): Rename to copysign<mode>3<tf_fpr>, use type
> 	instead of mode with fsimp.
> 	* config/s390/s390.opt (flag_vx_long_double_fma): New
> 	undocumented option.
> 	* config/s390/vector.md (V_HW): Add TF for z14+.
> 	(V_HW2): Likewise.
> 	(VFT): Likewise.
> 	(VF_HW): Likewise.
> 	(V_128): Likewise.
> 	(tf_vr): New mode_attr.
> 	(tointvec): Add TF.
> 	(mov<mode>): Rename to mov<mode><tf_vr>.
> 	(movetf): New dispatcher.
> 	(*vec_tf_to_v1tf): Rename to *vec_tf_to_v1tf_fpr, restrict to
> 	z13-.
> 	(*vec_tf_to_v1tf_vr): New pattern for z14+.
> 	(*fprx2_to_tf): Likewise.
> 	(*mov_tf_to_fprx2_0): Likewise.
> 	(*mov_tf_to_fprx2_1): Likewise.
> 	(add<mode>3): Rename to add<mode>3<tf_vr>.
> 	(addtf3): New dispatcher.
> 	(sub<mode>3): Rename to sub<mode>3<tf_vr>.
> 	(subtf3): New dispatcher.
> 	(mul<mode>3): Rename to mul<mode>3<tf_vr>.
> 	(multf3): New dispatcher.
> 	(div<mode>3): Rename to div<mode>3<tf_vr>.
> 	(divtf3): New dispatcher.
> 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_vr>.
> 	(sqrttf2): New dispatcher.
> 	(fma<mode>4): Restrict using s390_fma_allowed_p.
> 	(fms<mode>4): Likewise.
> 	(neg_fma<mode>4): Likewise.
> 	(neg_fms<mode>4): Likewise.
> 	(neg<mode>2): Rename to neg<mode>2<tf_vr>.
> 	(negtf2): New dispatcher.
> 	(abs<mode>2): Rename to abs<mode>2<tf_vr>.
> 	(abstf2): New dispatcher.
> 	(float<mode>tf2_vr): New forwarder.
> 	(float<mode>tf2): New dispatcher.
> 	(floatuns<mode>tf2_vr): New forwarder.
> 	(floatuns<mode>tf2): New dispatcher.
> 	(fix_trunctf<mode>2_vr): New forwarder.
> 	(fix_trunctf<mode>2): New dispatcher.
> 	(fixuns_trunctf<mode>2_vr): New forwarder.
> 	(fixuns_trunctf<mode>2): New dispatcher.
> 	(<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>): New pattern.
> 	(<FPINT:fpint_name>tf2): New forwarder.
> 	(rint<mode>2<tf_vr>): New pattern.
> 	(rinttf2): New forwarder.
> 	(*trunctfdf2_vr): New pattern.
> 	(trunctfdf2_vr): New forwarder.
> 	(trunctfdf2): New dispatcher.
> 	(trunctfsf2_vr): New forwarder.
> 	(trunctfsf2): New dispatcher.
> 	(extenddftf2_vr): New pattern.
> 	(extenddftf2): New dispatcher.
> 	(extendsftf2_vr): New forwarder.
> 	(extendsftf2): New dispatcher.
> 	(signbittf2_vr): New forwarder.
> 	(signbittf2): New dispatchers.
> 	(isinftf2_vr): New forwarder.
> 	(isinftf2): New dispatcher.
> 	* config/s390/vx-builtins.md (*vftci<mode>_cconly): Use VF_HW
> 	instead of VECF_HW, add missing constraint, add vw support.
> 	(vftci<mode>_intcconly): Use VF_HW instead of VECF_HW.
> 	(*vftci<mode>): Rename to vftci<mode>, use VF_HW instead of
> 	VECF_HW, and vw support.
> 	(vftci<mode>_intcc): Use VF_HW instead of VECF_HW.

...

> +; VX: TFmode in VR: use wfcxb
> +(define_insn "*cmptf_ccs"
> +  [(set (reg CC_REGNUM)
> +	(compare (match_operand:TF 0 "register_operand" "v")
> +		 (match_operand:TF 1 "general_operand"  "v")))]

Is this really benefitial to allow general_operands here? Everything
except registers need to be reloaded anyway.  To my experience it is
helpful to emit the extra moves as early as possible to let the other
optimizers work with them.

Andreas

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

* Re: [PATCH 4/4] IBM Z: Test long doubles in vector registers
  2020-11-03 21:46 ` [PATCH 4/4] IBM Z: Test long doubles in vector registers Ilya Leoshkevich
@ 2020-11-04 17:28   ` Andreas Krebbel
  2020-11-04 22:19     ` Ilya Leoshkevich
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-04 17:28 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

These tests all use the -mzvector option but do not appear to make use of the z vector languages
extensions. I think that option could be removed. Then these tests should be moved to the vector subdir.

You could do the asm scanning also in dg-do run tests.

Andreas


On 03.11.20 22:46, Ilya Leoshkevich wrote:
> gcc/testsuite/ChangeLog:
> 
> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> 
> 	* gcc.target/s390/zvector/long-double-callee-abi-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-caller-abi-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-caller-abi-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-copysign-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-copysign-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-fprx2-constant.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-double-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-double-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-float-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-float-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i16-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i16-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i32-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i32-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i64-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i64-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i8-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-i8-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u16-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u16-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u32-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u32-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u64-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u64-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u8-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-from-u8-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-double-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-double-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-float-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-float-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i16-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i16-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i32-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i32-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i64-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i64-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i8-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-i8-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u16-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u16-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u32-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u32-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u64-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u64-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u8-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-to-u8-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-vec-duplicate.c: New test.
> 	* gcc.target/s390/zvector/long-double-wf.h: New test.
> 	* gcc.target/s390/zvector/long-double-wfaxb-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfaxb-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfaxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfcxb-0001.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfcxb-0111.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfcxb-1011.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfcxb-1101.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfdxb-run.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfdxb-scan.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfdxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfixb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfkxb-0111.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfkxb-1011.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfkxb-1101.c: New test.
> 	* gcc.target/s390/zvector/long-double-wflcxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wflpxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmaxb-2.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmaxb-3.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmaxb-disabled.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmaxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmsxb-disabled.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmsxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfmxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfnmaxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfnmsxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfsqxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfsxb-1.c: New test.
> 	* gcc.target/s390/zvector/long-double-wfsxb.c: New test.
> 	* gcc.target/s390/zvector/long-double-wftcixb-1.c: New test.
> 	* gcc.target/s390/zvector/long-double-wftcixb.c: New test.
> ---
>  .../zvector/long-double-callee-abi-scan.c     | 20 +++++++
>  .../s390/zvector/long-double-caller-abi-run.c |  4 ++
>  .../zvector/long-double-caller-abi-scan.c     | 13 ++++
>  .../s390/zvector/long-double-copysign-run.c   | 14 +++++
>  .../s390/zvector/long-double-copysign-scan.c  | 11 ++++
>  .../s390/zvector/long-double-fprx2-constant.c | 11 ++++
>  .../zvector/long-double-from-double-run.c     | 12 ++++
>  .../zvector/long-double-from-double-scan.c    |  9 +++
>  .../s390/zvector/long-double-from-float-run.c | 12 ++++
>  .../zvector/long-double-from-float-scan.c     | 10 ++++
>  .../s390/zvector/long-double-from-i16-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-i16-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-i32-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-i32-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-i64-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-i64-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-i8-run.c    | 12 ++++
>  .../s390/zvector/long-double-from-i8-scan.c   | 11 ++++
>  .../s390/zvector/long-double-from-u16-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-u16-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-u32-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-u32-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-u64-run.c   | 12 ++++
>  .../s390/zvector/long-double-from-u64-scan.c  | 11 ++++
>  .../s390/zvector/long-double-from-u8-run.c    | 12 ++++
>  .../s390/zvector/long-double-from-u8-scan.c   | 11 ++++
>  .../s390/zvector/long-double-to-double-run.c  | 12 ++++
>  .../s390/zvector/long-double-to-double-scan.c |  9 +++
>  .../s390/zvector/long-double-to-float-run.c   | 12 ++++
>  .../s390/zvector/long-double-to-float-scan.c  | 10 ++++
>  .../s390/zvector/long-double-to-i16-run.c     | 12 ++++
>  .../s390/zvector/long-double-to-i16-scan.c    | 11 ++++
>  .../s390/zvector/long-double-to-i32-run.c     | 12 ++++
>  .../s390/zvector/long-double-to-i32-scan.c    | 11 ++++
>  .../s390/zvector/long-double-to-i64-run.c     | 12 ++++
>  .../s390/zvector/long-double-to-i64-scan.c    | 13 ++++
>  .../s390/zvector/long-double-to-i8-run.c      | 12 ++++
>  .../s390/zvector/long-double-to-i8-scan.c     | 11 ++++
>  .../s390/zvector/long-double-to-u16-run.c     | 13 ++++
>  .../s390/zvector/long-double-to-u16-scan.c    | 11 ++++
>  .../s390/zvector/long-double-to-u32-run.c     | 13 ++++
>  .../s390/zvector/long-double-to-u32-scan.c    | 11 ++++
>  .../s390/zvector/long-double-to-u64-run.c     | 13 ++++
>  .../s390/zvector/long-double-to-u64-scan.c    | 11 ++++
>  .../s390/zvector/long-double-to-u8-run.c      | 13 ++++
>  .../s390/zvector/long-double-to-u8-scan.c     | 11 ++++
>  .../s390/zvector/long-double-vec-duplicate.c  | 13 ++++
>  .../gcc.target/s390/zvector/long-double-wf.h  | 60 +++++++++++++++++++
>  .../s390/zvector/long-double-wfaxb-run.c      | 11 ++++
>  .../s390/zvector/long-double-wfaxb-scan.c     | 10 ++++
>  .../s390/zvector/long-double-wfaxb.c          |  8 +++
>  .../s390/zvector/long-double-wfcxb-0001.c     | 10 ++++
>  .../s390/zvector/long-double-wfcxb-0111.c     | 10 ++++
>  .../s390/zvector/long-double-wfcxb-1011.c     | 10 ++++
>  .../s390/zvector/long-double-wfcxb-1101.c     | 10 ++++
>  .../s390/zvector/long-double-wfdxb-run.c      | 11 ++++
>  .../s390/zvector/long-double-wfdxb-scan.c     | 10 ++++
>  .../s390/zvector/long-double-wfdxb.c          |  8 +++
>  .../s390/zvector/long-double-wfixb.c          |  8 +++
>  .../s390/zvector/long-double-wfkxb-0111.c     | 10 ++++
>  .../s390/zvector/long-double-wfkxb-1011.c     | 10 ++++
>  .../s390/zvector/long-double-wfkxb-1101.c     | 10 ++++
>  .../s390/zvector/long-double-wflcxb.c         |  8 +++
>  .../s390/zvector/long-double-wflpxb.c         |  8 +++
>  .../s390/zvector/long-double-wfmaxb-2.c       | 24 ++++++++
>  .../s390/zvector/long-double-wfmaxb-3.c       | 14 +++++
>  .../zvector/long-double-wfmaxb-disabled.c     |  9 +++
>  .../s390/zvector/long-double-wfmaxb.c         |  8 +++
>  .../zvector/long-double-wfmsxb-disabled.c     |  9 +++
>  .../s390/zvector/long-double-wfmsxb.c         |  8 +++
>  .../s390/zvector/long-double-wfmxb.c          |  8 +++
>  .../zvector/long-double-wfnmaxb-disabled.c    | 10 ++++
>  .../s390/zvector/long-double-wfnmaxb.c        |  8 +++
>  .../zvector/long-double-wfnmsxb-disabled.c    | 10 ++++
>  .../s390/zvector/long-double-wfnmsxb.c        |  8 +++
>  .../s390/zvector/long-double-wfsqxb.c         |  8 +++
>  .../s390/zvector/long-double-wfsxb-1.c        | 21 +++++++
>  .../s390/zvector/long-double-wfsxb.c          |  8 +++
>  .../s390/zvector/long-double-wftcixb-1.c      | 15 +++++
>  .../s390/zvector/long-double-wftcixb.c        |  8 +++
>  80 files changed, 934 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
> 
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
> new file mode 100644
> index 00000000000..005bfa9977a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-scan.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-loops" } */
> +#include <stdarg.h>
> +
> +__attribute__ ((noipa, used)) long double
> +long_double_callee (long double x, int n, ...)
> +{
> +  long double sum = x;
> +  va_list vl;
> +  int i;
> +
> +  va_start (vl, n);
> +  for (i = 0; i < n; i++)
> +    sum += va_arg (vl, long double);
> +  va_end (vl);
> +
> +  return sum;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tvl\t} 3 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
> new file mode 100644
> index 00000000000..d1756f5d34c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-run.c
> @@ -0,0 +1,4 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include "long-double-callee-abi-scan.c"
> +#include "long-double-caller-abi-scan.c"
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
> new file mode 100644
> index 00000000000..ef690733fbf
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-scan.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +long double long_double_callee (long double x, int n, ...);
> +
> +int
> +main ()
> +{
> +  assert (long_double_callee (1.L, 2, 2.L, 3.L) == 6.L);
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tvst\t} 3 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
> new file mode 100644
> index 00000000000..c874b64d78e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-run.c
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-copysign-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_copysign (1.1L, 2.2L) == 1.1L);
> +  assert (long_double_copysign (1.1L, -2.2L) == -1.1L);
> +  assert (long_double_copysign (-1.1L, 2.2L) == 1.1L);
> +  assert (long_double_copysign (-1.1L, -2.2L) == -1.1L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
> new file mode 100644
> index 00000000000..6a44c0eff61
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_copysign (long double x, long double y)
> +{
> +  return __builtin_copysignl (x, y);
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tvsel\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
> new file mode 100644
> index 00000000000..02a6a1f69c5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-constant.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mtune=z14 -funroll-loops" } */
> +
> +long double a;
> +int d;
> +void
> +b ()
> +{
> +  for (int c = 0; c < d; ++c)
> +    a = (a - c) / (c + 1);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
> new file mode 100644
> index 00000000000..7a960ad119d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-double-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_double (42.) == 42.L);
> +  assert (long_double_from_double (-42.) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
> new file mode 100644
> index 00000000000..db9ba4534c3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-double-scan.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_double (double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
> new file mode 100644
> index 00000000000..41256b39abc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-float-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_float (42.F) == 42.L);
> +  assert (long_double_from_float (-42.F) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
> new file mode 100644
> index 00000000000..4b9b570fcfb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-scan.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_float (float x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tldebr\t} 1 } } */
> +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
> new file mode 100644
> index 00000000000..6c0fac93da5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-i16-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_i16 (42) == 42.L);
> +  assert (long_double_from_i16 (-42) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
> new file mode 100644
> index 00000000000..18af4d82f57
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_i16 (int16_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
> new file mode 100644
> index 00000000000..2baa6e156f7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-i32-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_i32 (42) == 42.L);
> +  assert (long_double_from_i32 (-42) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
> new file mode 100644
> index 00000000000..433b6bbffe5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_i32 (int32_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
> new file mode 100644
> index 00000000000..c6f460064e0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-i64-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_i64 (42) == 42.L);
> +  assert (long_double_from_i64 (-42) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
> new file mode 100644
> index 00000000000..f418dffd8b0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_i64 (int64_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
> new file mode 100644
> index 00000000000..15c46d8a909
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-i8-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_i8 (42) == 42.L);
> +  assert (long_double_from_i8 (-42) == -42.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
> new file mode 100644
> index 00000000000..7a8b3fdaad0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_i8 (int8_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
> new file mode 100644
> index 00000000000..495b3f9f18d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-u16-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_u16 (42) == 42.L);
> +  assert (long_double_from_u16 (-42) == 65494.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
> new file mode 100644
> index 00000000000..b65e10269df
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_u16 (uint16_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
> new file mode 100644
> index 00000000000..072ae99ef24
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-u32-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_u32 (42) == 42.L);
> +  assert (long_double_from_u32 (-42) == 4294967254.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
> new file mode 100644
> index 00000000000..408e3d1b570
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_u32 (uint32_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
> new file mode 100644
> index 00000000000..6146c322611
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-u64-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_u64 (42) == 42.L);
> +  assert (long_double_from_u64 (-42) == 18446744073709551574.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
> new file mode 100644
> index 00000000000..856912d5689
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_u64 (uint64_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxlgbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
> new file mode 100644
> index 00000000000..d769d006499
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-from-u8-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_from_u8 (42) == 42.L);
> +  assert (long_double_from_u8 (-42) == 214.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
> new file mode 100644
> index 00000000000..d1421d4322c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static long double
> +long_double_from_u8 (uint8_t x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
> new file mode 100644
> index 00000000000..b68ce88529a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-double-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_double (42.L) == 42.);
> +  assert (long_double_to_double (-42.L) == -42.);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
> new file mode 100644
> index 00000000000..78ce18b38c4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-scan.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +__attribute__ ((noipa, used)) static double
> +long_double_to_double (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\twflrx\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
> new file mode 100644
> index 00000000000..70a8a3e7f73
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-float-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_float (42.L) == 42.F);
> +  assert (long_double_to_float (-42.L) == -42.F);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
> new file mode 100644
> index 00000000000..1f0b60a3f03
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-scan.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +__attribute__ ((noipa, used)) static float
> +long_double_to_float (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\twflrx\t%v\d+,%v\d+,0,3\n} 1 } } */
> +/* { dg-final { scan-assembler-times {\n\tledbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
> new file mode 100644
> index 00000000000..2044baa45af
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-i16-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_i16 (42.L) == 42);
> +  assert (long_double_to_i16 (-42.L) == -42);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
> new file mode 100644
> index 00000000000..3c47ae97c39
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static int16_t
> +long_double_to_i16 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
> new file mode 100644
> index 00000000000..9f98ea39f6f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-i32-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_i32 (42.L) == 42);
> +  assert (long_double_to_i32 (-42.L) == -42);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
> new file mode 100644
> index 00000000000..978b4751bff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static int32_t
> +long_double_to_i32 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
> new file mode 100644
> index 00000000000..f2a27ff4fec
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-i64-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_i64 (42.L) == 42);
> +  assert (long_double_to_i64 (-42.L) == -42);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
> new file mode 100644
> index 00000000000..38a212ac3c7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-scan.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static int64_t
> +long_double_to_i64 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
> +/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
> +/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
> new file mode 100644
> index 00000000000..0e0624b2788
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-i8-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_i8 (42.L) == 42);
> +  assert (long_double_to_i8 (-42.L) == -42);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
> new file mode 100644
> index 00000000000..d015b8a307b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static int8_t
> +long_double_to_i8 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
> new file mode 100644
> index 00000000000..7bac113a04c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-run.c
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-u16-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_u16 (42.L) == 42);
> +  /* Not (-42 & 0xffff) due to loss of precision.  */
> +  assert (long_double_to_u16 (-42.L) == 0);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
> new file mode 100644
> index 00000000000..a7694ceb3ad
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static uint16_t
> +long_double_to_u16 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
> new file mode 100644
> index 00000000000..b85038c0723
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-run.c
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-u32-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_u32 (42.L) == 42);
> +  /* Not (-42 & 0xffffffff) due to loss of precision.  */
> +  assert (long_double_to_u32 (-42.L) == 0);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
> new file mode 100644
> index 00000000000..ff97803d320
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static uint32_t
> +long_double_to_u32 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
> new file mode 100644
> index 00000000000..e781637dac3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-run.c
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-u64-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_u64 (42.L) == 42);
> +  /* Not (-42 & 0xffffffffffffffff) due to loss of precision.  */
> +  assert (long_double_to_u64 (-42.L) == 0);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
> new file mode 100644
> index 00000000000..d97c0ec35dd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static uint64_t
> +long_double_to_u64 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tclgxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
> new file mode 100644
> index 00000000000..7ae330b6aa1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-to-u8-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (long_double_to_u8 (42.L) == 42);
> +  /* Not (-42 & 0xff) due to loss of precision.  */
> +  assert (long_double_to_u8 (-42.L) == 0);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
> new file mode 100644
> index 00000000000..0500bc1c946
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-scan.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <stdint.h>
> +
> +__attribute__ ((noipa, used)) static uint8_t
> +long_double_to_u8 (long double x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
> new file mode 100644
> index 00000000000..2ce9da33b8e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-duplicate.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -funroll-loops -march=z14 -mtune=z14" } */
> +
> +long double a, b;
> +double *c;
> +long double *d;
> +
> +void
> +e ()
> +{
> +  while (d != &a)
> +    *d++ = b * *c++;
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
> new file mode 100644
> index 00000000000..a564fc62d47
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
> @@ -0,0 +1,60 @@
> +#ifndef LONG_DOUBLE_WF_H
> +#define LONG_DOUBLE_WF_H 1
> +
> +#include <math.h>
> +
> +#define ADD(x, y, z) ((x) + (z))
> +#define DIV(x, y, z) ((x) / (z))
> +#define FABSL(x, y, z) (fabsl (y))
> +#define ISINFL(x, y, z) (isinfl (x) ? (y) : (z))
> +#define MUL(x, y, z) ((x) * (z))
> +#define MUL_ADD(x, y, z) ((x) * (y) + (z))
> +#define MUL_SUB(x, y, z) ((x) * (y) - (z))
> +#define NEG(x, y, z)                                                          \
> +  ({                                                                          \
> +    volatile long double r = -(y);                                            \
> +    r;                                                                        \
> +  })
> +#define NEG_MUL_ADD(x, y, z) NEG (0, MUL_ADD (x, y, z), 0)
> +#define NEG_MUL_SUB(x, y, z) NEG (0, MUL_SUB (x, y, z), 0)
> +#define QUIET_IFEQUAL(x, y, z) ((x) == (y) ? (z) : 0)
> +#define QUIET_IFGREATER(x, y, z) (__builtin_isgreater (x, y) ? (z) : 0)
> +#define QUIET_IFLESS(x, y, z) (__builtin_isless (x, y) ? (z) : 0)
> +#define QUIET_IFUNORDERED(x, y, z) (__builtin_isunordered (x, y) ? (z) : 0)
> +#define SIGNALING_IFEQUAL(x, y, z) (((x) >= (y) && (x) <= (y)) ? (z) : 0)
> +#define SIGNALING_IFGREATER(x, y, z) ((x) > (y) ? (z) : 0)
> +#define SIGNALING_IFLESS(x, y, z) ((x) < (y) ? (z) : 0)
> +#define ROUNDL(x, y, z) (roundl (y))
> +#define SQRTL(x, y, z) (sqrtl (y))
> +#define SUB(x, y, z) ((x) - (z))
> +
> +#define LONG_DOUBLE_WF(op)                                                    \
> +  long double test (                                                          \
> +      long double x0, long double x1, long double x2, long double x3,         \
> +      long double x4, long double x5, long double x6, long double x7,         \
> +      long double x8, long double x9, long double x10, long double x11,       \
> +      long double x12, long double x13, long double x14, long double x15)     \
> +  {                                                                           \
> +    while (x15 < 1E+30)                                                       \
> +      {                                                                       \
> +	x0 = op (x1, x2, x3);                                                 \
> +	x1 = op (x2, x3, x4) + 1;                                             \
> +	x2 = op (x3, x4, x5) + 2;                                             \
> +	x3 = op (x4, x5, x6) + 3;                                             \
> +	x4 = op (x5, x6, x7) + 4;                                             \
> +	x5 = op (x6, x7, x8) + 5;                                             \
> +	x6 = op (x7, x8, x9) + 6;                                             \
> +	x7 = op (x8, x9, x10) + 7;                                            \
> +	x8 = op (x9, x10, x11) + 8;                                           \
> +	x9 = op (x10, x11, x12) + 9;                                          \
> +	x10 = op (x11, x12, x13) + 10;                                        \
> +	x11 = op (x12, x13, x14) + 11;                                        \
> +	x12 = op (x13, x14, x15) + 12;                                        \
> +	x13 = op (x14, x15, x0) + 13;                                         \
> +	x14 = op (x15, x0, x1) + 14;                                          \
> +	x15 = op (x0, x1, x2) + 15;                                           \
> +      }                                                                       \
> +    return x15;                                                               \
> +  }
> +
> +#endif
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
> new file mode 100644
> index 00000000000..de7770068ea
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
> @@ -0,0 +1,11 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-wfaxb-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (wfaxb (1.11L, 2.22L, 3.33L) == 6.66L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
> new file mode 100644
> index 00000000000..2bbf408416a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-scan.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +__attribute__ ((noipa, used)) static long double
> +wfaxb (long double x, long double y, long double z)
> +{
> +  return x + y + z;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\twfaxb\t} 2 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
> new file mode 100644
> index 00000000000..354dbe226b0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (ADD);
> +
> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
> new file mode 100644
> index 00000000000..d0a32d51902
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0001.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (QUIET_IFUNORDERED);
> +
> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> +/* jo == brc 0b0001, ...  */
> +/* { dg-final { scan-assembler {\n\tjo\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
> new file mode 100644
> index 00000000000..04a34e7373c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-0111.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (QUIET_IFEQUAL);
> +
> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> +/* jne == brc 0b0111, ...  */
> +/* { dg-final { scan-assembler {\n\tjne\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
> new file mode 100644
> index 00000000000..f221a56ffb8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1011.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (QUIET_IFLESS);
> +
> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> +/* jnl == brc 0b1011, ...  */
> +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
> new file mode 100644
> index 00000000000..d2353ebe30c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-1101.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (QUIET_IFGREATER);
> +
> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> +/* jnh == brc 0b1101, ...  */
> +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
> new file mode 100644
> index 00000000000..7ac752dc289
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
> @@ -0,0 +1,11 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +#include "long-double-wfdxb-scan.c"
> +
> +int
> +main (void)
> +{
> +  assert (wfdxb (2.22L, 1.11L, 2.L) == 1.L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
> new file mode 100644
> index 00000000000..31eea0f9329
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-scan.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +__attribute__ ((noipa, used)) static long double
> +wfdxb (long double x, long double y, long double z)
> +{
> +  return (x / y) / z;
> +}
> +
> +/* { dg-final { scan-assembler-times {\n\twfdxb\t} 2 } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
> new file mode 100644
> index 00000000000..7d854cac1bc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (DIV);
> +
> +/* { dg-final { scan-assembler {\n\twfdxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
> new file mode 100644
> index 00000000000..5e16ffa58e6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (ROUNDL);
> +
> +/* { dg-final { scan-assembler {\n\twfixb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
> new file mode 100644
> index 00000000000..2e7b1c37d08
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-0111.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (SIGNALING_IFEQUAL);
> +
> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> +/* jne == brc 0b0111, ...  */
> +/* { dg-final { scan-assembler {\n\tjne\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
> new file mode 100644
> index 00000000000..2d2020af842
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1011.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (SIGNALING_IFLESS);
> +
> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> +/* jnl == brc 0b1011, ...  */
> +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
> new file mode 100644
> index 00000000000..f17f83ca568
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-1101.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (SIGNALING_IFGREATER);
> +
> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> +/* jnh == brc 0b1101, ...  */
> +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
> new file mode 100644
> index 00000000000..c69161beca9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (NEG);
> +
> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
> new file mode 100644
> index 00000000000..df3c1dbccb8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (FABSL);
> +
> +/* { dg-final { scan-assembler {\n\twflpxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
> new file mode 100644
> index 00000000000..9335680a70c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
> @@ -0,0 +1,24 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +int a, c, d, f, k, l, m;
> +long double b, e, g, h, i;
> +double j;
> +
> +void
> +n (void)
> +{
> +  while (m)
> +    {
> +      a = b * d;
> +      b = c;
> +      c = d * e + 2;
> +      e = f + g + 4;
> +      f = h + 6;
> +      g = h * 0 + i + 7;
> +      h = i + 9;
> +      i = j * k + 0 + 10;
> +      j = l;
> +      m = a * b;
> +    }
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
> new file mode 100644
> index 00000000000..9cc2b85f673
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +long double a, c, d;
> +int b;
> +void
> +e (void)
> +{
> +  while (d)
> +    {
> +      a = 0 * c + 0;
> +      d = b;
> +    }
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
> new file mode 100644
> index 00000000000..c9e5a7b066c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-disabled.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (MUL_ADD);
> +
> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
> new file mode 100644
> index 00000000000..fddad943f18
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (MUL_ADD);
> +
> +/* { dg-final { scan-assembler {\n\twfmaxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
> new file mode 100644
> index 00000000000..e78178b9a0b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-disabled.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (MUL_SUB);
> +
> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
> new file mode 100644
> index 00000000000..1fe71ecf09f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (MUL_SUB);
> +
> +/* { dg-final { scan-assembler {\n\twfmsxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
> new file mode 100644
> index 00000000000..ce311f89db4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (MUL);
> +
> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
> new file mode 100644
> index 00000000000..da8a73adcee
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (NEG_MUL_ADD);
> +
> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
> new file mode 100644
> index 00000000000..75b28137048
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (NEG_MUL_ADD);
> +
> +/* { dg-final { scan-assembler {\n\twfnmaxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
> new file mode 100644
> index 00000000000..9a07d049ed4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (NEG_MUL_SUB);
> +
> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
> new file mode 100644
> index 00000000000..16b80890725
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-double-fma" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (NEG_MUL_SUB);
> +
> +/* { dg-final { scan-assembler {\n\twfnmsxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
> new file mode 100644
> index 00000000000..2f42483dfee
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (SQRTL);
> +
> +/* { dg-final { scan-assembler {\n\twfsqxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
> new file mode 100644
> index 00000000000..dd2f244a4eb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
> @@ -0,0 +1,21 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +#include <assert.h>
> +
> +typedef float tf __attribute__ ((mode (TF)));
> +static tf x;
> +static tf y;
> +
> +__attribute__ ((noipa)) static tf
> +sub (void)
> +{
> +  return x - y;
> +}
> +
> +int
> +main (void)
> +{
> +  x = 1.5L;
> +  y = 2.5L;
> +  assert (sub () == -1.0L);
> +}
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
> new file mode 100644
> index 00000000000..d27cf8ca3de
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (SUB);
> +
> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
> new file mode 100644
> index 00000000000..6915d8ed8a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -march=z14 -mzvector -mzarch" } */
> +
> +int a, b;
> +
> +void
> +c (void)
> +{
> +  long double d;
> +  a = d;
> +  if (__builtin_isinf (d))
> +    b = 0;
> +}
> +
> +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
> new file mode 100644
> index 00000000000..1134e26ee87
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> +
> +#include "long-double-wf.h"
> +
> +LONG_DOUBLE_WF (ISINFL);
> +
> +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
> 


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

* Re: [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible
  2020-11-04 17:16   ` Andreas Krebbel
@ 2020-11-04 22:12     ` Ilya Leoshkevich
  2020-11-05  7:26       ` Andreas Krebbel
  0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-04 22:12 UTC (permalink / raw)
  To: Andreas Krebbel; +Cc: gcc-patches

On Wed, 2020-11-04 at 18:16 +0100, Andreas Krebbel wrote:
> On 03.11.20 22:45, Ilya Leoshkevich wrote:
> > On z14+, there are instructions for working with 128-bit floats
> > (long
> > doubles) in vector registers.  It's beneficial to use them instead
> > of
> > instructions that operate on floating point register pairs, because
> > it
> > allows to store 4 times more data in registers at a time,
> > relieveing
> > register pressure.  The performance of new instructions is almost
> > the
> > same.
> > 
> > Implement by storing TFmode values in vector registers on
> > z14+.  Since
> > not all operations are available with the new instructions, keep
> > the old
> > ones using the new FPRX2 mode, and convert between it and TFmode
> > when
> > necessary (this is called "forwarder" expanders below).  Change the
> > existing TFmode expanders to call either new- or old-style ones
> > depending on whether we are on z14+ or older machines ("dispatcher"
> > expanders).
> > 
> > gcc/ChangeLog:
> > 
> > 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> > 
> > 	* config/s390/s390-modes.def (FPRX2): New mode.
> > 	* config/s390/s390-protos.h (s390_fma_allowed_p): New function.
> > 	* config/s390/s390.c (s390_fma_allowed_p): Likewise.
> > 	(s390_build_signbit_mask): Support 128-bit masks.
> > 	(print_operand): Support printing the second word of a TFmode
> > 	operand as vector register.
> > 	(constant_modes): Add FPRX2mode.
> > 	(s390_class_max_nregs): Return 1 for TFmode on z14+.
> > 	(s390_is_fpr128): New function.
> > 	(s390_is_vr128): Likewise.
> > 	(s390_can_change_mode_class): Use s390_is_fpr128 and
> > 	s390_is_vr128 in order to determine whether mode refers to a
> > FPR
> > 	pair or to a VR.
> > 	* config/s390/s390.h (EXPAND_MOVTF): New macro.
> > 	(EXPAND_TF): Likewise.
> > 	* config/s390/s390.md (PFPO_OP_TYPE_FPRX2): PFPO_OP_TYPE_TF
> > 	alias.
> > 	(ALL): Add FPRX2.
> > 	(FP_ALL): Add FPRX2 for z14+, restrict TFmode to z13-.
> > 	(FP): Likewise.
> > 	(FP_ANYTF): New mode iterator.
> > 	(BFP): Add FPRX2 for z14+, restrict TFmode to z13-.
> > 	(TD_TF): Likewise.
> > 	(xde): Add FPRX2.
> > 	(nBFP): Likewise.
> > 	(nDFP): Likewise.
> > 	(DSF): Likewise.
> > 	(DFDI): Likewise.
> > 	(SFSI): Likewise.
> > 	(DF): Likewise.
> > 	(SF): Likewise.
> > 	(fT0): Likewise.
> > 	(bt): Likewise.
> > 	(_d): Likewise.
> > 	(HALF_TMODE): Likewise.
> > 	(tf_fpr): New mode_attr.
> > 	(type): New mode_attr.
> > 	(*cmp<mode>_ccz_0): Use type instead of mode with fsimp.
> > 	(*cmp<mode>_ccs_0_fastmath): Likewise.
> > 	(*cmptf_ccs): New pattern for wfcxb.
> > 	(*cmptf_ccsfps): New pattern for wfkxb.
> > 	(mov<mode>): Rename to mov<mode><tf_fpr>.
> > 	(signbit<mode>2): Rename to signbit<mode>2<tf_fpr>.
> > 	(isinf<mode>2): Renamed to isinf<mode>2<tf_fpr>.
> > 	(*TDC_insn_<mode>): Use type instead of mode with fsimp.
> > 	(fixuns_trunc<FP:mode><GPR:mode>2): Rename to
> > 	fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>.
> > 	(fix_trunctf<mode>2): Rename to fix_trunctf<mode>2_fpr.
> > 	(floatdi<mode>2): Rename to floatdi<mode>2<tf_fpr>, use type
> > 	instead of mode with itof.
> > 	(floatsi<mode>2): Rename to floatsi<mode>2<tf_fpr>, use type
> > 	instead of mode with itof.
> > 	(*floatuns<GPR:mode><FP:mode>2): Use type instead of mode for
> > 	itof.
> > 	(floatuns<GPR:mode><FP:mode>2): Rename to
> > 	floatuns<GPR:mode><FP:mode>2<tf_fpr>.
> > 	(trunctf<mode>2): Rename to trunctf<mode>2_fpr, use type
> > instead
> > 	of mode with fsimp.
> > 	(extend<DSF:mode><BFP:mode>2): Rename to
> > 	extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>.
> > 	(<FPINT:fpint_name><BFP:mode>2): Rename to
> > 	<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>, use type instead of
> > 	mode with fsimp.
> > 	(rint<BFP:mode>2): Rename to rint<BFP:mode>2<BFP:tf_fpr>, use
> > 	type instead of mode with fsimp.
> > 	(<FPINT:fpint_name><DFP:mode>2): Use type instead of mode for
> > 	fsimp.
> > 	(rint<DFP:mode>2): Likewise.
> > 	(trunc<BFP:mode><DFP_ALL:mode>2): Rename to
> > 	trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
> > 	(trunc<DFP_ALL:mode><BFP:mode>2): Rename to
> > 	trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
> > 	(extend<BFP:mode><DFP_ALL:mode>2): Rename to
> > 	extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
> > 	(extend<DFP_ALL:mode><BFP:mode>2): Rename to
> > 	extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
> > 	(add<mode>3): Rename to add<mode>3<tf_fpr>, use type instead of
> > 	mode with fsimp.
> > 	(*add<mode>3_cc): Use type instead of mode with fsimp.
> > 	(*add<mode>3_cconly): Likewise.
> > 	(sub<mode>3): Rename to sub<mode>3<tf_fpr>, use type instead of
> > 	mode with fsimp.
> > 	(*sub<mode>3_cc): Use type instead of mode with fsimp.
> > 	(*sub<mode>3_cconly): Likewise.
> > 	(mul<mode>3): Rename to mul<mode>3<tf_fpr>, use type instead of
> > 	mode with fsimp.
> > 	(fma<mode>4): Restrict using s390_fma_allowed_p.
> > 	(fms<mode>4): Restrict using s390_fma_allowed_p.
> > 	(div<mode>3): Rename to div<mode>3<tf_fpr>, use type instead of
> > 	mode with fdiv.
> > 	(neg<mode>2): Rename to neg<mode>2<tf_fpr>.
> > 	(*neg<mode>2_cc): Use type instead of mode with fsimp.
> > 	(*neg<mode>2_cconly): Likewise.
> > 	(*neg<mode>2_nocc): Likewise.
> > 	(*neg<mode>2): Likeiwse.
> > 	(abs<mode>2): Rename to abs<mode>2<tf_fpr>, use type instead of
> > 	mode with fdiv.
> > 	(*abs<mode>2_cc): Use type instead of mode with fsimp.
> > 	(*abs<mode>2_cconly): Likewise.
> > 	(*abs<mode>2_nocc): Likewise.
> > 	(*abs<mode>2): Likewise.
> > 	(*negabs<mode>2_cc): Likewise.
> > 	(*negabs<mode>2_cconly): Likewise.
> > 	(*negabs<mode>2_nocc): Likewise.
> > 	(*negabs<mode>2): Likewise.
> > 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_fpr>, use type instead
> > 	of mode with fsqrt.
> > 	(cbranch<mode>4): Use FP_ANYTF instead of FP.
> > 	(copysign<mode>3): Rename to copysign<mode>3<tf_fpr>, use type
> > 	instead of mode with fsimp.
> > 	* config/s390/s390.opt (flag_vx_long_double_fma): New
> > 	undocumented option.
> > 	* config/s390/vector.md (V_HW): Add TF for z14+.
> > 	(V_HW2): Likewise.
> > 	(VFT): Likewise.
> > 	(VF_HW): Likewise.
> > 	(V_128): Likewise.
> > 	(tf_vr): New mode_attr.
> > 	(tointvec): Add TF.
> > 	(mov<mode>): Rename to mov<mode><tf_vr>.
> > 	(movetf): New dispatcher.
> > 	(*vec_tf_to_v1tf): Rename to *vec_tf_to_v1tf_fpr, restrict to
> > 	z13-.
> > 	(*vec_tf_to_v1tf_vr): New pattern for z14+.
> > 	(*fprx2_to_tf): Likewise.
> > 	(*mov_tf_to_fprx2_0): Likewise.
> > 	(*mov_tf_to_fprx2_1): Likewise.
> > 	(add<mode>3): Rename to add<mode>3<tf_vr>.
> > 	(addtf3): New dispatcher.
> > 	(sub<mode>3): Rename to sub<mode>3<tf_vr>.
> > 	(subtf3): New dispatcher.
> > 	(mul<mode>3): Rename to mul<mode>3<tf_vr>.
> > 	(multf3): New dispatcher.
> > 	(div<mode>3): Rename to div<mode>3<tf_vr>.
> > 	(divtf3): New dispatcher.
> > 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_vr>.
> > 	(sqrttf2): New dispatcher.
> > 	(fma<mode>4): Restrict using s390_fma_allowed_p.
> > 	(fms<mode>4): Likewise.
> > 	(neg_fma<mode>4): Likewise.
> > 	(neg_fms<mode>4): Likewise.
> > 	(neg<mode>2): Rename to neg<mode>2<tf_vr>.
> > 	(negtf2): New dispatcher.
> > 	(abs<mode>2): Rename to abs<mode>2<tf_vr>.
> > 	(abstf2): New dispatcher.
> > 	(float<mode>tf2_vr): New forwarder.
> > 	(float<mode>tf2): New dispatcher.
> > 	(floatuns<mode>tf2_vr): New forwarder.
> > 	(floatuns<mode>tf2): New dispatcher.
> > 	(fix_trunctf<mode>2_vr): New forwarder.
> > 	(fix_trunctf<mode>2): New dispatcher.
> > 	(fixuns_trunctf<mode>2_vr): New forwarder.
> > 	(fixuns_trunctf<mode>2): New dispatcher.
> > 	(<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>): New pattern.
> > 	(<FPINT:fpint_name>tf2): New forwarder.
> > 	(rint<mode>2<tf_vr>): New pattern.
> > 	(rinttf2): New forwarder.
> > 	(*trunctfdf2_vr): New pattern.
> > 	(trunctfdf2_vr): New forwarder.
> > 	(trunctfdf2): New dispatcher.
> > 	(trunctfsf2_vr): New forwarder.
> > 	(trunctfsf2): New dispatcher.
> > 	(extenddftf2_vr): New pattern.
> > 	(extenddftf2): New dispatcher.
> > 	(extendsftf2_vr): New forwarder.
> > 	(extendsftf2): New dispatcher.
> > 	(signbittf2_vr): New forwarder.
> > 	(signbittf2): New dispatchers.
> > 	(isinftf2_vr): New forwarder.
> > 	(isinftf2): New dispatcher.
> > 	* config/s390/vx-builtins.md (*vftci<mode>_cconly): Use VF_HW
> > 	instead of VECF_HW, add missing constraint, add vw support.
> > 	(vftci<mode>_intcconly): Use VF_HW instead of VECF_HW.
> > 	(*vftci<mode>): Rename to vftci<mode>, use VF_HW instead of
> > 	VECF_HW, and vw support.
> > 	(vftci<mode>_intcc): Use VF_HW instead of VECF_HW.
> 
> ...
> 
> > +; VX: TFmode in VR: use wfcxb
> > +(define_insn "*cmptf_ccs"
> > +  [(set (reg CC_REGNUM)
> > +	(compare (match_operand:TF 0 "register_operand" "v")
> > +		 (match_operand:TF 1 "general_operand"  "v")))]
> 
> Is this really benefitial to allow general_operands here? Everything
> except registers need to be reloaded anyway.  To my experience it is
> helpful to emit the extra moves as early as possible to let the other
> optimizers work with them.

The rtxes recognized by this pattern are initially generated by the
generic cbranch expander, which allows general_operands and thus
doesn't immediately reload.  If we don't allow general_operands here,
rtxes generated by cbranch will be unrecognizable.


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

* Re: [PATCH 4/4] IBM Z: Test long doubles in vector registers
  2020-11-04 17:28   ` Andreas Krebbel
@ 2020-11-04 22:19     ` Ilya Leoshkevich
  2020-11-05  7:28       ` Andreas Krebbel
  0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2020-11-04 22:19 UTC (permalink / raw)
  To: Andreas Krebbel; +Cc: gcc-patches

On Wed, 2020-11-04 at 18:28 +0100, Andreas Krebbel wrote:
> These tests all use the -mzvector option but do not appear to make
> use of the z vector languages
> extensions. I think that option could be removed. Then these tests
> should be moved to the vector subdir.

Will change, thanks!

> You could do the asm scanning also in dg-do run tests.

This doesn't seem to work.  For example, if I add 

/* { dg-final { scan-assembler-times {aaa} 999 } } */

to long-double-from-double-run.c, it won't fail.

> 
> Andreas
> 
> 
> On 03.11.20 22:46, Ilya Leoshkevich wrote:
> > gcc/testsuite/ChangeLog:
> > 
> > 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
> > 
> > 	* gcc.target/s390/zvector/long-double-callee-abi-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-caller-abi-run.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-caller-abi-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-copysign-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-copysign-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-fprx2-constant.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-double-run.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-double-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-float-run.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-float-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-i16-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-i16-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-i32-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-i32-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-i64-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-i64-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-i8-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-i8-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-u16-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-u16-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-u32-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-u32-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-u64-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-u64-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-from-u8-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-from-u8-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-double-run.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-to-double-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-to-float-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-float-scan.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-to-i16-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i16-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i32-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i32-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i64-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i64-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i8-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-i8-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u16-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u16-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u32-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u32-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u64-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u64-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u8-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-to-u8-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-vec-duplicate.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-wf.h: New test.
> > 	* gcc.target/s390/zvector/long-double-wfaxb-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfaxb-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfaxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfcxb-0001.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfcxb-0111.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfcxb-1011.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfcxb-1101.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfdxb-run.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfdxb-scan.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfdxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfixb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfkxb-0111.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfkxb-1011.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfkxb-1101.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wflcxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wflpxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfmaxb-2.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfmaxb-3.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfmaxb-disabled.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-wfmaxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfmsxb-disabled.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-wfmsxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfmxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-wfnmaxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c: New
> > test.
> > 	* gcc.target/s390/zvector/long-double-wfnmsxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfsqxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfsxb-1.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wfsxb.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wftcixb-1.c: New test.
> > 	* gcc.target/s390/zvector/long-double-wftcixb.c: New test.
> > ---
> >  .../zvector/long-double-callee-abi-scan.c     | 20 +++++++
> >  .../s390/zvector/long-double-caller-abi-run.c |  4 ++
> >  .../zvector/long-double-caller-abi-scan.c     | 13 ++++
> >  .../s390/zvector/long-double-copysign-run.c   | 14 +++++
> >  .../s390/zvector/long-double-copysign-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-fprx2-constant.c | 11 ++++
> >  .../zvector/long-double-from-double-run.c     | 12 ++++
> >  .../zvector/long-double-from-double-scan.c    |  9 +++
> >  .../s390/zvector/long-double-from-float-run.c | 12 ++++
> >  .../zvector/long-double-from-float-scan.c     | 10 ++++
> >  .../s390/zvector/long-double-from-i16-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-i16-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-i32-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-i32-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-i64-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-i64-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-i8-run.c    | 12 ++++
> >  .../s390/zvector/long-double-from-i8-scan.c   | 11 ++++
> >  .../s390/zvector/long-double-from-u16-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-u16-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-u32-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-u32-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-u64-run.c   | 12 ++++
> >  .../s390/zvector/long-double-from-u64-scan.c  | 11 ++++
> >  .../s390/zvector/long-double-from-u8-run.c    | 12 ++++
> >  .../s390/zvector/long-double-from-u8-scan.c   | 11 ++++
> >  .../s390/zvector/long-double-to-double-run.c  | 12 ++++
> >  .../s390/zvector/long-double-to-double-scan.c |  9 +++
> >  .../s390/zvector/long-double-to-float-run.c   | 12 ++++
> >  .../s390/zvector/long-double-to-float-scan.c  | 10 ++++
> >  .../s390/zvector/long-double-to-i16-run.c     | 12 ++++
> >  .../s390/zvector/long-double-to-i16-scan.c    | 11 ++++
> >  .../s390/zvector/long-double-to-i32-run.c     | 12 ++++
> >  .../s390/zvector/long-double-to-i32-scan.c    | 11 ++++
> >  .../s390/zvector/long-double-to-i64-run.c     | 12 ++++
> >  .../s390/zvector/long-double-to-i64-scan.c    | 13 ++++
> >  .../s390/zvector/long-double-to-i8-run.c      | 12 ++++
> >  .../s390/zvector/long-double-to-i8-scan.c     | 11 ++++
> >  .../s390/zvector/long-double-to-u16-run.c     | 13 ++++
> >  .../s390/zvector/long-double-to-u16-scan.c    | 11 ++++
> >  .../s390/zvector/long-double-to-u32-run.c     | 13 ++++
> >  .../s390/zvector/long-double-to-u32-scan.c    | 11 ++++
> >  .../s390/zvector/long-double-to-u64-run.c     | 13 ++++
> >  .../s390/zvector/long-double-to-u64-scan.c    | 11 ++++
> >  .../s390/zvector/long-double-to-u8-run.c      | 13 ++++
> >  .../s390/zvector/long-double-to-u8-scan.c     | 11 ++++
> >  .../s390/zvector/long-double-vec-duplicate.c  | 13 ++++
> >  .../gcc.target/s390/zvector/long-double-wf.h  | 60
> > +++++++++++++++++++
> >  .../s390/zvector/long-double-wfaxb-run.c      | 11 ++++
> >  .../s390/zvector/long-double-wfaxb-scan.c     | 10 ++++
> >  .../s390/zvector/long-double-wfaxb.c          |  8 +++
> >  .../s390/zvector/long-double-wfcxb-0001.c     | 10 ++++
> >  .../s390/zvector/long-double-wfcxb-0111.c     | 10 ++++
> >  .../s390/zvector/long-double-wfcxb-1011.c     | 10 ++++
> >  .../s390/zvector/long-double-wfcxb-1101.c     | 10 ++++
> >  .../s390/zvector/long-double-wfdxb-run.c      | 11 ++++
> >  .../s390/zvector/long-double-wfdxb-scan.c     | 10 ++++
> >  .../s390/zvector/long-double-wfdxb.c          |  8 +++
> >  .../s390/zvector/long-double-wfixb.c          |  8 +++
> >  .../s390/zvector/long-double-wfkxb-0111.c     | 10 ++++
> >  .../s390/zvector/long-double-wfkxb-1011.c     | 10 ++++
> >  .../s390/zvector/long-double-wfkxb-1101.c     | 10 ++++
> >  .../s390/zvector/long-double-wflcxb.c         |  8 +++
> >  .../s390/zvector/long-double-wflpxb.c         |  8 +++
> >  .../s390/zvector/long-double-wfmaxb-2.c       | 24 ++++++++
> >  .../s390/zvector/long-double-wfmaxb-3.c       | 14 +++++
> >  .../zvector/long-double-wfmaxb-disabled.c     |  9 +++
> >  .../s390/zvector/long-double-wfmaxb.c         |  8 +++
> >  .../zvector/long-double-wfmsxb-disabled.c     |  9 +++
> >  .../s390/zvector/long-double-wfmsxb.c         |  8 +++
> >  .../s390/zvector/long-double-wfmxb.c          |  8 +++
> >  .../zvector/long-double-wfnmaxb-disabled.c    | 10 ++++
> >  .../s390/zvector/long-double-wfnmaxb.c        |  8 +++
> >  .../zvector/long-double-wfnmsxb-disabled.c    | 10 ++++
> >  .../s390/zvector/long-double-wfnmsxb.c        |  8 +++
> >  .../s390/zvector/long-double-wfsqxb.c         |  8 +++
> >  .../s390/zvector/long-double-wfsxb-1.c        | 21 +++++++
> >  .../s390/zvector/long-double-wfsxb.c          |  8 +++
> >  .../s390/zvector/long-double-wftcixb-1.c      | 15 +++++
> >  .../s390/zvector/long-double-wftcixb.c        |  8 +++
> >  80 files changed, 934 insertions(+)
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-callee-abi-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-caller-abi-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-caller-abi-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-copysign-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-copysign-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-fprx2-constant.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-double-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-double-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-float-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-float-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i16-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i16-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i32-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i32-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i64-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i64-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i8-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i8-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u16-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u16-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u32-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u32-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u64-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u64-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u8-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u8-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-double-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-double-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-float-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-float-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i16-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i16-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i32-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i32-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i64-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i64-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i8-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-i8-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u16-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u16-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u32-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u32-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u64-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u64-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u8-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-to-u8-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-vec-duplicate.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wf.h
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfaxb-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfaxb-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfaxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfcxb-0001.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfcxb-0111.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfcxb-1011.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfcxb-1101.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfdxb-run.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfdxb-scan.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfdxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfixb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfkxb-0111.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfkxb-1011.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfkxb-1101.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wflcxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wflpxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmaxb-2.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmaxb-3.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmaxb-disabled.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmaxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmsxb-disabled.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmsxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmaxb-disabled.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmaxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmsxb-disabled.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmsxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfsqxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfsxb-1.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfsxb.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wftcixb-1.c
> >  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wftcixb.c
> > 
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > callee-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-callee-abi-scan.c
> > new file mode 100644
> > index 00000000000..005bfa9977a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-
> > scan.c
> > @@ -0,0 +1,20 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-
> > loops" } */
> > +#include <stdarg.h>
> > +
> > +__attribute__ ((noipa, used)) long double
> > +long_double_callee (long double x, int n, ...)
> > +{
> > +  long double sum = x;
> > +  va_list vl;
> > +  int i;
> > +
> > +  va_start (vl, n);
> > +  for (i = 0; i < n; i++)
> > +    sum += va_arg (vl, long double);
> > +  va_end (vl);
> > +
> > +  return sum;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tvl\t} 3 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > caller-abi-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-caller-abi-run.c
> > new file mode 100644
> > index 00000000000..d1756f5d34c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-
> > run.c
> > @@ -0,0 +1,4 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include "long-double-callee-abi-scan.c"
> > +#include "long-double-caller-abi-scan.c"
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > caller-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-caller-abi-scan.c
> > new file mode 100644
> > index 00000000000..ef690733fbf
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-
> > scan.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +long double long_double_callee (long double x, int n, ...);
> > +
> > +int
> > +main ()
> > +{
> > +  assert (long_double_callee (1.L, 2, 2.L, 3.L) == 6.L);
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tvst\t} 3 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > copysign-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > copysign-run.c
> > new file mode 100644
> > index 00000000000..c874b64d78e
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-
> > run.c
> > @@ -0,0 +1,14 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-copysign-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_copysign (1.1L, 2.2L) == 1.1L);
> > +  assert (long_double_copysign (1.1L, -2.2L) == -1.1L);
> > +  assert (long_double_copysign (-1.1L, 2.2L) == 1.1L);
> > +  assert (long_double_copysign (-1.1L, -2.2L) == -1.1L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > copysign-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-copysign-scan.c
> > new file mode 100644
> > index 00000000000..6a44c0eff61
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_copysign (long double x, long double y)
> > +{
> > +  return __builtin_copysignl (x, y);
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tvsel\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > fprx2-constant.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-fprx2-constant.c
> > new file mode 100644
> > index 00000000000..02a6a1f69c5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-
> > constant.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mtune=z14 -funroll-loops" } */
> > +
> > +long double a;
> > +int d;
> > +void
> > +b ()
> > +{
> > +  for (int c = 0; c < d; ++c)
> > +    a = (a - c) / (c + 1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-double-run.c
> > new file mode 100644
> > index 00000000000..7a960ad119d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-
> > double-run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-double-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_double (42.) == 42.L);
> > +  assert (long_double_from_double (-42.) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-double-scan.c
> > new file mode 100644
> > index 00000000000..db9ba4534c3
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-
> > double-scan.c
> > @@ -0,0 +1,9 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_double (double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-float-run.c
> > new file mode 100644
> > index 00000000000..41256b39abc
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-float-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_float (42.F) == 42.L);
> > +  assert (long_double_from_float (-42.F) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-float-scan.c
> > new file mode 100644
> > index 00000000000..4b9b570fcfb
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-
> > scan.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_float (float x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tldebr\t} 1 } } */
> > +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i16-run.c
> > new file mode 100644
> > index 00000000000..6c0fac93da5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-i16-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_i16 (42) == 42.L);
> > +  assert (long_double_from_i16 (-42) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i16-scan.c
> > new file mode 100644
> > index 00000000000..18af4d82f57
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_i16 (int16_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i32-run.c
> > new file mode 100644
> > index 00000000000..2baa6e156f7
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-i32-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_i32 (42) == 42.L);
> > +  assert (long_double_from_i32 (-42) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i32-scan.c
> > new file mode 100644
> > index 00000000000..433b6bbffe5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_i32 (int32_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i64-run.c
> > new file mode 100644
> > index 00000000000..c6f460064e0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-i64-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_i64 (42) == 42.L);
> > +  assert (long_double_from_i64 (-42) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-i64-scan.c
> > new file mode 100644
> > index 00000000000..f418dffd8b0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_i64 (int64_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i8-run.c
> > new file mode 100644
> > index 00000000000..15c46d8a909
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-i8-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_i8 (42) == 42.L);
> > +  assert (long_double_from_i8 (-42) == -42.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-i8-scan.c
> > new file mode 100644
> > index 00000000000..7a8b3fdaad0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_i8 (int8_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u16-run.c
> > new file mode 100644
> > index 00000000000..495b3f9f18d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-u16-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_u16 (42) == 42.L);
> > +  assert (long_double_from_u16 (-42) == 65494.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u16-scan.c
> > new file mode 100644
> > index 00000000000..b65e10269df
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_u16 (uint16_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u32-run.c
> > new file mode 100644
> > index 00000000000..072ae99ef24
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-u32-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_u32 (42) == 42.L);
> > +  assert (long_double_from_u32 (-42) == 4294967254.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u32-scan.c
> > new file mode 100644
> > index 00000000000..408e3d1b570
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_u32 (uint32_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u64-run.c
> > new file mode 100644
> > index 00000000000..6146c322611
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-u64-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_u64 (42) == 42.L);
> > +  assert (long_double_from_u64 (-42) == 18446744073709551574.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-from-u64-scan.c
> > new file mode 100644
> > index 00000000000..856912d5689
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_u64 (uint64_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxlgbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u8-run.c
> > new file mode 100644
> > index 00000000000..d769d006499
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-from-u8-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_from_u8 (42) == 42.L);
> > +  assert (long_double_from_u8 (-42) == 214.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > from-u8-scan.c
> > new file mode 100644
> > index 00000000000..d1421d4322c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +long_double_from_u8 (uint8_t x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > to-double-run.c
> > new file mode 100644
> > index 00000000000..b68ce88529a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-double-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_double (42.L) == 42.);
> > +  assert (long_double_to_double (-42.L) == -42.);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > to-double-scan.c
> > new file mode 100644
> > index 00000000000..78ce18b38c4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-
> > scan.c
> > @@ -0,0 +1,9 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +__attribute__ ((noipa, used)) static double
> > +long_double_to_double (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\twflrx\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > float-run.c
> > new file mode 100644
> > index 00000000000..70a8a3e7f73
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-float-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_float (42.L) == 42.F);
> > +  assert (long_double_to_float (-42.L) == -42.F);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > to-float-scan.c
> > new file mode 100644
> > index 00000000000..1f0b60a3f03
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-
> > scan.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +__attribute__ ((noipa, used)) static float
> > +long_double_to_float (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times
> > {\n\twflrx\t%v\d+,%v\d+,0,3\n} 1 } } */
> > +/* { dg-final { scan-assembler-times {\n\tledbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i16-run.c
> > new file mode 100644
> > index 00000000000..2044baa45af
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-i16-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_i16 (42.L) == 42);
> > +  assert (long_double_to_i16 (-42.L) == -42);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i16-scan.c
> > new file mode 100644
> > index 00000000000..3c47ae97c39
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static int16_t
> > +long_double_to_i16 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i32-run.c
> > new file mode 100644
> > index 00000000000..9f98ea39f6f
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-i32-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_i32 (42.L) == 42);
> > +  assert (long_double_to_i32 (-42.L) == -42);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i32-scan.c
> > new file mode 100644
> > index 00000000000..978b4751bff
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static int32_t
> > +long_double_to_i32 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i64-run.c
> > new file mode 100644
> > index 00000000000..f2a27ff4fec
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-
> > run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-i64-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_i64 (42.L) == 42);
> > +  assert (long_double_to_i64 (-42.L) == -42);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i64-scan.c
> > new file mode 100644
> > index 00000000000..38a212ac3c7
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-
> > scan.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static int64_t
> > +long_double_to_i64 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times
> > {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
> > +/* { dg-final { scan-assembler-times
> > {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
> > +/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-
> > run.c
> > new file mode 100644
> > index 00000000000..0e0624b2788
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-i8-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_i8 (42.L) == 42);
> > +  assert (long_double_to_i8 (-42.L) == -42);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > i8-scan.c
> > new file mode 100644
> > index 00000000000..d015b8a307b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static int8_t
> > +long_double_to_i8 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u16-run.c
> > new file mode 100644
> > index 00000000000..7bac113a04c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-
> > run.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-u16-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_u16 (42.L) == 42);
> > +  /* Not (-42 & 0xffff) due to loss of precision.  */
> > +  assert (long_double_to_u16 (-42.L) == 0);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u16-scan.c
> > new file mode 100644
> > index 00000000000..a7694ceb3ad
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static uint16_t
> > +long_double_to_u16 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u32-run.c
> > new file mode 100644
> > index 00000000000..b85038c0723
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-
> > run.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-u32-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_u32 (42.L) == 42);
> > +  /* Not (-42 & 0xffffffff) due to loss of precision.  */
> > +  assert (long_double_to_u32 (-42.L) == 0);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u32-scan.c
> > new file mode 100644
> > index 00000000000..ff97803d320
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static uint32_t
> > +long_double_to_u32 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u64-run.c
> > new file mode 100644
> > index 00000000000..e781637dac3
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-
> > run.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-u64-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_u64 (42.L) == 42);
> > +  /* Not (-42 & 0xffffffffffffffff) due to loss of precision.  */
> > +  assert (long_double_to_u64 (-42.L) == 0);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u64-scan.c
> > new file mode 100644
> > index 00000000000..d97c0ec35dd
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static uint64_t
> > +long_double_to_u64 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tclgxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-
> > run.c
> > new file mode 100644
> > index 00000000000..7ae330b6aa1
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-to-u8-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (long_double_to_u8 (42.L) == 42);
> > +  /* Not (-42 & 0xff) due to loss of precision.  */
> > +  assert (long_double_to_u8 (-42.L) == 0);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
> > u8-scan.c
> > new file mode 100644
> > index 00000000000..0500bc1c946
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-
> > scan.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <stdint.h>
> > +
> > +__attribute__ ((noipa, used)) static uint8_t
> > +long_double_to_u8 (long double x)
> > +{
> > +  return x;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-
> > duplicate.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > vec-duplicate.c
> > new file mode 100644
> > index 00000000000..2ce9da33b8e
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-
> > duplicate.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -funroll-loops -march=z14 -mtune=z14" } */
> > +
> > +long double a, b;
> > +double *c;
> > +long double *d;
> > +
> > +void
> > +e ()
> > +{
> > +  while (d != &a)
> > +    *d++ = b * *c++;
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h 
> > b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
> > new file mode 100644
> > index 00000000000..a564fc62d47
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
> > @@ -0,0 +1,60 @@
> > +#ifndef LONG_DOUBLE_WF_H
> > +#define LONG_DOUBLE_WF_H 1
> > +
> > +#include <math.h>
> > +
> > +#define ADD(x, y, z) ((x) + (z))
> > +#define DIV(x, y, z) ((x) / (z))
> > +#define FABSL(x, y, z) (fabsl (y))
> > +#define ISINFL(x, y, z) (isinfl (x) ? (y) : (z))
> > +#define MUL(x, y, z) ((x) * (z))
> > +#define MUL_ADD(x, y, z) ((x) * (y) + (z))
> > +#define MUL_SUB(x, y, z) ((x) * (y) - (z))
> > +#define NEG(x, y,
> > z)                                                          \
> > +  ({                                                              
> >             \
> > +    volatile long double r =
> > -(y);                                            \
> > +    r;                                                            
> >             \
> > +  })
> > +#define NEG_MUL_ADD(x, y, z) NEG (0, MUL_ADD (x, y, z), 0)
> > +#define NEG_MUL_SUB(x, y, z) NEG (0, MUL_SUB (x, y, z), 0)
> > +#define QUIET_IFEQUAL(x, y, z) ((x) == (y) ? (z) : 0)
> > +#define QUIET_IFGREATER(x, y, z) (__builtin_isgreater (x, y) ? (z)
> > : 0)
> > +#define QUIET_IFLESS(x, y, z) (__builtin_isless (x, y) ? (z) : 0)
> > +#define QUIET_IFUNORDERED(x, y, z) (__builtin_isunordered (x, y) ?
> > (z) : 0)
> > +#define SIGNALING_IFEQUAL(x, y, z) (((x) >= (y) && (x) <= (y)) ?
> > (z) : 0)
> > +#define SIGNALING_IFGREATER(x, y, z) ((x) > (y) ? (z) : 0)
> > +#define SIGNALING_IFLESS(x, y, z) ((x) < (y) ? (z) : 0)
> > +#define ROUNDL(x, y, z) (roundl (y))
> > +#define SQRTL(x, y, z) (sqrtl (y))
> > +#define SUB(x, y, z) ((x) - (z))
> > +
> > +#define
> > LONG_DOUBLE_WF(op)                                                 
> >    \
> > +  long double test
> > (                                                          \
> > +      long double x0, long double x1, long double x2, long double
> > x3,         \
> > +      long double x4, long double x5, long double x6, long double
> > x7,         \
> > +      long double x8, long double x9, long double x10, long double
> > x11,       \
> > +      long double x12, long double x13, long double x14, long
> > double x15)     \
> > +  {                                                               
> >             \
> > +    while (x15 <
> > 1E+30)                                                       \
> > +      {                                                           
> >             \
> > +	x0 = op (x1, x2,
> > x3);                                                 \
> > +	x1 = op (x2, x3, x4) +
> > 1;                                             \
> > +	x2 = op (x3, x4, x5) +
> > 2;                                             \
> > +	x3 = op (x4, x5, x6) +
> > 3;                                             \
> > +	x4 = op (x5, x6, x7) +
> > 4;                                             \
> > +	x5 = op (x6, x7, x8) +
> > 5;                                             \
> > +	x6 = op (x7, x8, x9) +
> > 6;                                             \
> > +	x7 = op (x8, x9, x10) +
> > 7;                                            \
> > +	x8 = op (x9, x10, x11) +
> > 8;                                           \
> > +	x9 = op (x10, x11, x12) +
> > 9;                                          \
> > +	x10 = op (x11, x12, x13) +
> > 10;                                        \
> > +	x11 = op (x12, x13, x14) +
> > 11;                                        \
> > +	x12 = op (x13, x14, x15) +
> > 12;                                        \
> > +	x13 = op (x14, x15, x0) +
> > 13;                                         \
> > +	x14 = op (x15, x0, x1) +
> > 14;                                          \
> > +	x15 = op (x0, x1, x2) +
> > 15;                                           \
> > +      }                                                           
> >             \
> > +    return
> > x15;                                                               
> > \
> > +  }
> > +
> > +#endif
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfaxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfaxb-run.c
> > new file mode 100644
> > index 00000000000..de7770068ea
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-wfaxb-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (wfaxb (1.11L, 2.22L, 3.33L) == 6.66L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfaxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfaxb-scan.c
> > new file mode 100644
> > index 00000000000..2bbf408416a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-
> > scan.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +wfaxb (long double x, long double y, long double z)
> > +{
> > +  return x + y + z;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\twfaxb\t} 2 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
> > new file mode 100644
> > index 00000000000..354dbe226b0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (ADD);
> > +
> > +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-0001.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-0001.c
> > new file mode 100644
> > index 00000000000..d0a32d51902
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
> > 0001.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (QUIET_IFUNORDERED);
> > +
> > +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> > +/* jo == brc 0b0001, ...  */
> > +/* { dg-final { scan-assembler {\n\tjo\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-0111.c
> > new file mode 100644
> > index 00000000000..04a34e7373c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
> > 0111.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (QUIET_IFEQUAL);
> > +
> > +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> > +/* jne == brc 0b0111, ...  */
> > +/* { dg-final { scan-assembler {\n\tjne\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-1011.c
> > new file mode 100644
> > index 00000000000..f221a56ffb8
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
> > 1011.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (QUIET_IFLESS);
> > +
> > +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> > +/* jnl == brc 0b1011, ...  */
> > +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfcxb-1101.c
> > new file mode 100644
> > index 00000000000..d2353ebe30c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
> > 1101.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (QUIET_IFGREATER);
> > +
> > +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
> > +/* jnh == brc 0b1101, ...  */
> > +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfdxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfdxb-run.c
> > new file mode 100644
> > index 00000000000..7ac752dc289
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +#include "long-double-wfdxb-scan.c"
> > +
> > +int
> > +main (void)
> > +{
> > +  assert (wfdxb (2.22L, 1.11L, 2.L) == 1.L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfdxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfdxb-scan.c
> > new file mode 100644
> > index 00000000000..31eea0f9329
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-
> > scan.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +__attribute__ ((noipa, used)) static long double
> > +wfdxb (long double x, long double y, long double z)
> > +{
> > +  return (x / y) / z;
> > +}
> > +
> > +/* { dg-final { scan-assembler-times {\n\twfdxb\t} 2 } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfdxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
> > new file mode 100644
> > index 00000000000..7d854cac1bc
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (DIV);
> > +
> > +/* { dg-final { scan-assembler {\n\twfdxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
> > new file mode 100644
> > index 00000000000..5e16ffa58e6
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (ROUNDL);
> > +
> > +/* { dg-final { scan-assembler {\n\twfixb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-0111.c
> > new file mode 100644
> > index 00000000000..2e7b1c37d08
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
> > 0111.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (SIGNALING_IFEQUAL);
> > +
> > +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> > +/* jne == brc 0b0111, ...  */
> > +/* { dg-final { scan-assembler {\n\tjne\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-1011.c
> > new file mode 100644
> > index 00000000000..2d2020af842
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
> > 1011.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (SIGNALING_IFLESS);
> > +
> > +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> > +/* jnl == brc 0b1011, ...  */
> > +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfkxb-1101.c
> > new file mode 100644
> > index 00000000000..f17f83ca568
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
> > 1101.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (SIGNALING_IFGREATER);
> > +
> > +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
> > +/* jnh == brc 0b1101, ...  */
> > +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wflcxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wflcxb.c
> > new file mode 100644
> > index 00000000000..c69161beca9
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (NEG);
> > +
> > +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wflpxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wflpxb.c
> > new file mode 100644
> > index 00000000000..df3c1dbccb8
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (FABSL);
> > +
> > +/* { dg-final { scan-assembler {\n\twflpxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb-2.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb-2.c
> > new file mode 100644
> > index 00000000000..9335680a70c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
> > @@ -0,0 +1,24 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +int a, c, d, f, k, l, m;
> > +long double b, e, g, h, i;
> > +double j;
> > +
> > +void
> > +n (void)
> > +{
> > +  while (m)
> > +    {
> > +      a = b * d;
> > +      b = c;
> > +      c = d * e + 2;
> > +      e = f + g + 4;
> > +      f = h + 6;
> > +      g = h * 0 + i + 7;
> > +      h = i + 9;
> > +      i = j * k + 0 + 10;
> > +      j = l;
> > +      m = a * b;
> > +    }
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb-3.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb-3.c
> > new file mode 100644
> > index 00000000000..9cc2b85f673
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
> > @@ -0,0 +1,14 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +long double a, c, d;
> > +int b;
> > +void
> > +e (void)
> > +{
> > +  while (d)
> > +    {
> > +      a = 0 * c + 0;
> > +      d = b;
> > +    }
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmaxb-disabled.c
> > new file mode 100644
> > index 00000000000..c9e5a7b066c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-
> > disabled.c
> > @@ -0,0 +1,9 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (MUL_ADD);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmaxb.c
> > new file mode 100644
> > index 00000000000..fddad943f18
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (MUL_ADD);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmaxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfmsxb-disabled.c
> > new file mode 100644
> > index 00000000000..e78178b9a0b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-
> > disabled.c
> > @@ -0,0 +1,9 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (MUL_SUB);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmsxb.c
> > new file mode 100644
> > index 00000000000..1fe71ecf09f
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (MUL_SUB);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmsxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfmxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
> > new file mode 100644
> > index 00000000000..ce311f89db4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (MUL);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmaxb-disabled.c
> > new file mode 100644
> > index 00000000000..da8a73adcee
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-
> > disabled.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (NEG_MUL_ADD);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmaxb.c
> > new file mode 100644
> > index 00000000000..75b28137048
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (NEG_MUL_ADD);
> > +
> > +/* { dg-final { scan-assembler {\n\twfnmaxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
> > double-wfnmsxb-disabled.c
> > new file mode 100644
> > index 00000000000..9a07d049ed4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-
> > disabled.c
> > @@ -0,0 +1,10 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (NEG_MUL_SUB);
> > +
> > +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> > +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfnmsxb.c
> > new file mode 100644
> > index 00000000000..16b80890725
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
> > double-fma" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (NEG_MUL_SUB);
> > +
> > +/* { dg-final { scan-assembler {\n\twfnmsxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfsqxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfsqxb.c
> > new file mode 100644
> > index 00000000000..2f42483dfee
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (SQRTL);
> > +
> > +/* { dg-final { scan-assembler {\n\twfsqxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfsxb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfsxb-1.c
> > new file mode 100644
> > index 00000000000..dd2f244a4eb
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +#include <assert.h>
> > +
> > +typedef float tf __attribute__ ((mode (TF)));
> > +static tf x;
> > +static tf y;
> > +
> > +__attribute__ ((noipa)) static tf
> > +sub (void)
> > +{
> > +  return x - y;
> > +}
> > +
> > +int
> > +main (void)
> > +{
> > +  x = 1.5L;
> > +  y = 2.5L;
> > +  assert (sub () == -1.0L);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wfsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
> > new file mode 100644
> > index 00000000000..d27cf8ca3de
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (SUB);
> > +
> > +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wftcixb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wftcixb-1.c
> > new file mode 100644
> > index 00000000000..6915d8ed8a4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O1 -march=z14 -mzvector -mzarch" } */
> > +
> > +int a, b;
> > +
> > +void
> > +c (void)
> > +{
> > +  long double d;
> > +  a = d;
> > +  if (__builtin_isinf (d))
> > +    b = 0;
> > +}
> > +
> > +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
> > diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wftcixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
> > wftcixb.c
> > new file mode 100644
> > index 00000000000..1134e26ee87
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
> > @@ -0,0 +1,8 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
> > +
> > +#include "long-double-wf.h"
> > +
> > +LONG_DOUBLE_WF (ISINFL);
> > +
> > +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
> > 


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

* Re: [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible
  2020-11-04 22:12     ` Ilya Leoshkevich
@ 2020-11-05  7:26       ` Andreas Krebbel
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-05  7:26 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 04.11.20 23:12, Ilya Leoshkevich wrote:
> On Wed, 2020-11-04 at 18:16 +0100, Andreas Krebbel wrote:
>> On 03.11.20 22:45, Ilya Leoshkevich wrote:
>>> On z14+, there are instructions for working with 128-bit floats
>>> (long
>>> doubles) in vector registers.  It's beneficial to use them instead
>>> of
>>> instructions that operate on floating point register pairs, because
>>> it
>>> allows to store 4 times more data in registers at a time,
>>> relieveing
>>> register pressure.  The performance of new instructions is almost
>>> the
>>> same.
>>>
>>> Implement by storing TFmode values in vector registers on
>>> z14+.  Since
>>> not all operations are available with the new instructions, keep
>>> the old
>>> ones using the new FPRX2 mode, and convert between it and TFmode
>>> when
>>> necessary (this is called "forwarder" expanders below).  Change the
>>> existing TFmode expanders to call either new- or old-style ones
>>> depending on whether we are on z14+ or older machines ("dispatcher"
>>> expanders).
>>>
>>> gcc/ChangeLog:
>>>
>>> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
>>>
>>> 	* config/s390/s390-modes.def (FPRX2): New mode.
>>> 	* config/s390/s390-protos.h (s390_fma_allowed_p): New function.
>>> 	* config/s390/s390.c (s390_fma_allowed_p): Likewise.
>>> 	(s390_build_signbit_mask): Support 128-bit masks.
>>> 	(print_operand): Support printing the second word of a TFmode
>>> 	operand as vector register.
>>> 	(constant_modes): Add FPRX2mode.
>>> 	(s390_class_max_nregs): Return 1 for TFmode on z14+.
>>> 	(s390_is_fpr128): New function.
>>> 	(s390_is_vr128): Likewise.
>>> 	(s390_can_change_mode_class): Use s390_is_fpr128 and
>>> 	s390_is_vr128 in order to determine whether mode refers to a
>>> FPR
>>> 	pair or to a VR.
>>> 	* config/s390/s390.h (EXPAND_MOVTF): New macro.
>>> 	(EXPAND_TF): Likewise.
>>> 	* config/s390/s390.md (PFPO_OP_TYPE_FPRX2): PFPO_OP_TYPE_TF
>>> 	alias.
>>> 	(ALL): Add FPRX2.
>>> 	(FP_ALL): Add FPRX2 for z14+, restrict TFmode to z13-.
>>> 	(FP): Likewise.
>>> 	(FP_ANYTF): New mode iterator.
>>> 	(BFP): Add FPRX2 for z14+, restrict TFmode to z13-.
>>> 	(TD_TF): Likewise.
>>> 	(xde): Add FPRX2.
>>> 	(nBFP): Likewise.
>>> 	(nDFP): Likewise.
>>> 	(DSF): Likewise.
>>> 	(DFDI): Likewise.
>>> 	(SFSI): Likewise.
>>> 	(DF): Likewise.
>>> 	(SF): Likewise.
>>> 	(fT0): Likewise.
>>> 	(bt): Likewise.
>>> 	(_d): Likewise.
>>> 	(HALF_TMODE): Likewise.
>>> 	(tf_fpr): New mode_attr.
>>> 	(type): New mode_attr.
>>> 	(*cmp<mode>_ccz_0): Use type instead of mode with fsimp.
>>> 	(*cmp<mode>_ccs_0_fastmath): Likewise.
>>> 	(*cmptf_ccs): New pattern for wfcxb.
>>> 	(*cmptf_ccsfps): New pattern for wfkxb.
>>> 	(mov<mode>): Rename to mov<mode><tf_fpr>.
>>> 	(signbit<mode>2): Rename to signbit<mode>2<tf_fpr>.
>>> 	(isinf<mode>2): Renamed to isinf<mode>2<tf_fpr>.
>>> 	(*TDC_insn_<mode>): Use type instead of mode with fsimp.
>>> 	(fixuns_trunc<FP:mode><GPR:mode>2): Rename to
>>> 	fixuns_trunc<FP:mode><GPR:mode>2<FP:tf_fpr>.
>>> 	(fix_trunctf<mode>2): Rename to fix_trunctf<mode>2_fpr.
>>> 	(floatdi<mode>2): Rename to floatdi<mode>2<tf_fpr>, use type
>>> 	instead of mode with itof.
>>> 	(floatsi<mode>2): Rename to floatsi<mode>2<tf_fpr>, use type
>>> 	instead of mode with itof.
>>> 	(*floatuns<GPR:mode><FP:mode>2): Use type instead of mode for
>>> 	itof.
>>> 	(floatuns<GPR:mode><FP:mode>2): Rename to
>>> 	floatuns<GPR:mode><FP:mode>2<tf_fpr>.
>>> 	(trunctf<mode>2): Rename to trunctf<mode>2_fpr, use type
>>> instead
>>> 	of mode with fsimp.
>>> 	(extend<DSF:mode><BFP:mode>2): Rename to
>>> 	extend<DSF:mode><BFP:mode>2<BFP:tf_fpr>.
>>> 	(<FPINT:fpint_name><BFP:mode>2): Rename to
>>> 	<FPINT:fpint_name><BFP:mode>2<BFP:tf_fpr>, use type instead of
>>> 	mode with fsimp.
>>> 	(rint<BFP:mode>2): Rename to rint<BFP:mode>2<BFP:tf_fpr>, use
>>> 	type instead of mode with fsimp.
>>> 	(<FPINT:fpint_name><DFP:mode>2): Use type instead of mode for
>>> 	fsimp.
>>> 	(rint<DFP:mode>2): Likewise.
>>> 	(trunc<BFP:mode><DFP_ALL:mode>2): Rename to
>>> 	trunc<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
>>> 	(trunc<DFP_ALL:mode><BFP:mode>2): Rename to
>>> 	trunc<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
>>> 	(extend<BFP:mode><DFP_ALL:mode>2): Rename to
>>> 	extend<BFP:mode><DFP_ALL:mode>2<BFP:tf_fpr>.
>>> 	(extend<DFP_ALL:mode><BFP:mode>2): Rename to
>>> 	extend<DFP_ALL:mode><BFP:mode>2<BFP:tf_fpr>.
>>> 	(add<mode>3): Rename to add<mode>3<tf_fpr>, use type instead of
>>> 	mode with fsimp.
>>> 	(*add<mode>3_cc): Use type instead of mode with fsimp.
>>> 	(*add<mode>3_cconly): Likewise.
>>> 	(sub<mode>3): Rename to sub<mode>3<tf_fpr>, use type instead of
>>> 	mode with fsimp.
>>> 	(*sub<mode>3_cc): Use type instead of mode with fsimp.
>>> 	(*sub<mode>3_cconly): Likewise.
>>> 	(mul<mode>3): Rename to mul<mode>3<tf_fpr>, use type instead of
>>> 	mode with fsimp.
>>> 	(fma<mode>4): Restrict using s390_fma_allowed_p.
>>> 	(fms<mode>4): Restrict using s390_fma_allowed_p.
>>> 	(div<mode>3): Rename to div<mode>3<tf_fpr>, use type instead of
>>> 	mode with fdiv.
>>> 	(neg<mode>2): Rename to neg<mode>2<tf_fpr>.
>>> 	(*neg<mode>2_cc): Use type instead of mode with fsimp.
>>> 	(*neg<mode>2_cconly): Likewise.
>>> 	(*neg<mode>2_nocc): Likewise.
>>> 	(*neg<mode>2): Likeiwse.
>>> 	(abs<mode>2): Rename to abs<mode>2<tf_fpr>, use type instead of
>>> 	mode with fdiv.
>>> 	(*abs<mode>2_cc): Use type instead of mode with fsimp.
>>> 	(*abs<mode>2_cconly): Likewise.
>>> 	(*abs<mode>2_nocc): Likewise.
>>> 	(*abs<mode>2): Likewise.
>>> 	(*negabs<mode>2_cc): Likewise.
>>> 	(*negabs<mode>2_cconly): Likewise.
>>> 	(*negabs<mode>2_nocc): Likewise.
>>> 	(*negabs<mode>2): Likewise.
>>> 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_fpr>, use type instead
>>> 	of mode with fsqrt.
>>> 	(cbranch<mode>4): Use FP_ANYTF instead of FP.
>>> 	(copysign<mode>3): Rename to copysign<mode>3<tf_fpr>, use type
>>> 	instead of mode with fsimp.
>>> 	* config/s390/s390.opt (flag_vx_long_double_fma): New
>>> 	undocumented option.
>>> 	* config/s390/vector.md (V_HW): Add TF for z14+.
>>> 	(V_HW2): Likewise.
>>> 	(VFT): Likewise.
>>> 	(VF_HW): Likewise.
>>> 	(V_128): Likewise.
>>> 	(tf_vr): New mode_attr.
>>> 	(tointvec): Add TF.
>>> 	(mov<mode>): Rename to mov<mode><tf_vr>.
>>> 	(movetf): New dispatcher.
>>> 	(*vec_tf_to_v1tf): Rename to *vec_tf_to_v1tf_fpr, restrict to
>>> 	z13-.
>>> 	(*vec_tf_to_v1tf_vr): New pattern for z14+.
>>> 	(*fprx2_to_tf): Likewise.
>>> 	(*mov_tf_to_fprx2_0): Likewise.
>>> 	(*mov_tf_to_fprx2_1): Likewise.
>>> 	(add<mode>3): Rename to add<mode>3<tf_vr>.
>>> 	(addtf3): New dispatcher.
>>> 	(sub<mode>3): Rename to sub<mode>3<tf_vr>.
>>> 	(subtf3): New dispatcher.
>>> 	(mul<mode>3): Rename to mul<mode>3<tf_vr>.
>>> 	(multf3): New dispatcher.
>>> 	(div<mode>3): Rename to div<mode>3<tf_vr>.
>>> 	(divtf3): New dispatcher.
>>> 	(sqrt<mode>2): Rename to sqrt<mode>2<tf_vr>.
>>> 	(sqrttf2): New dispatcher.
>>> 	(fma<mode>4): Restrict using s390_fma_allowed_p.
>>> 	(fms<mode>4): Likewise.
>>> 	(neg_fma<mode>4): Likewise.
>>> 	(neg_fms<mode>4): Likewise.
>>> 	(neg<mode>2): Rename to neg<mode>2<tf_vr>.
>>> 	(negtf2): New dispatcher.
>>> 	(abs<mode>2): Rename to abs<mode>2<tf_vr>.
>>> 	(abstf2): New dispatcher.
>>> 	(float<mode>tf2_vr): New forwarder.
>>> 	(float<mode>tf2): New dispatcher.
>>> 	(floatuns<mode>tf2_vr): New forwarder.
>>> 	(floatuns<mode>tf2): New dispatcher.
>>> 	(fix_trunctf<mode>2_vr): New forwarder.
>>> 	(fix_trunctf<mode>2): New dispatcher.
>>> 	(fixuns_trunctf<mode>2_vr): New forwarder.
>>> 	(fixuns_trunctf<mode>2): New dispatcher.
>>> 	(<FPINT:fpint_name><VF_HW:mode>2<VF_HW:tf_vr>): New pattern.
>>> 	(<FPINT:fpint_name>tf2): New forwarder.
>>> 	(rint<mode>2<tf_vr>): New pattern.
>>> 	(rinttf2): New forwarder.
>>> 	(*trunctfdf2_vr): New pattern.
>>> 	(trunctfdf2_vr): New forwarder.
>>> 	(trunctfdf2): New dispatcher.
>>> 	(trunctfsf2_vr): New forwarder.
>>> 	(trunctfsf2): New dispatcher.
>>> 	(extenddftf2_vr): New pattern.
>>> 	(extenddftf2): New dispatcher.
>>> 	(extendsftf2_vr): New forwarder.
>>> 	(extendsftf2): New dispatcher.
>>> 	(signbittf2_vr): New forwarder.
>>> 	(signbittf2): New dispatchers.
>>> 	(isinftf2_vr): New forwarder.
>>> 	(isinftf2): New dispatcher.
>>> 	* config/s390/vx-builtins.md (*vftci<mode>_cconly): Use VF_HW
>>> 	instead of VECF_HW, add missing constraint, add vw support.
>>> 	(vftci<mode>_intcconly): Use VF_HW instead of VECF_HW.
>>> 	(*vftci<mode>): Rename to vftci<mode>, use VF_HW instead of
>>> 	VECF_HW, and vw support.
>>> 	(vftci<mode>_intcc): Use VF_HW instead of VECF_HW.
>>
>> ...
>>
>>> +; VX: TFmode in VR: use wfcxb
>>> +(define_insn "*cmptf_ccs"
>>> +  [(set (reg CC_REGNUM)
>>> +	(compare (match_operand:TF 0 "register_operand" "v")
>>> +		 (match_operand:TF 1 "general_operand"  "v")))]
>>
>> Is this really benefitial to allow general_operands here? Everything
>> except registers need to be reloaded anyway.  To my experience it is
>> helpful to emit the extra moves as early as possible to let the other
>> optimizers work with them.
> 
> The rtxes recognized by this pattern are initially generated by the
> generic cbranch expander, which allows general_operands and thus
> doesn't immediately reload.  If we don't allow general_operands here,
> rtxes generated by cbranch will be unrecognizable.

Yes, the expander would have to change as well. It would need to force the operand into a reg
whenever TFmodes are supposed to live in VRs. It would be nice to see if it would do any good. But
I'm ok with it as is.

One other thing I noticed is that the new "float<mode>tf2" expander in vector.md is lacking a
TARGET_ZARCH in the insn condition. Did you have multilibs enabled when running the regression tests?

Andreas

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

* Re: [PATCH 4/4] IBM Z: Test long doubles in vector registers
  2020-11-04 22:19     ` Ilya Leoshkevich
@ 2020-11-05  7:28       ` Andreas Krebbel
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Krebbel @ 2020-11-05  7:28 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: gcc-patches

On 04.11.20 23:19, Ilya Leoshkevich wrote:
> On Wed, 2020-11-04 at 18:28 +0100, Andreas Krebbel wrote:
>> These tests all use the -mzvector option but do not appear to make
>> use of the z vector languages
>> extensions. I think that option could be removed. Then these tests
>> should be moved to the vector subdir.
> 
> Will change, thanks!
> 
>> You could do the asm scanning also in dg-do run tests.
> 
> This doesn't seem to work.  For example, if I add 
> 
> /* { dg-final { scan-assembler-times {aaa} 999 } } */
> 
> to long-double-from-double-run.c, it won't fail.

You will have to add --save-temps to dg-options to make it work. Otherwise the scan test will stay
unresolved.

Andreas

> 
>>
>> Andreas
>>
>>
>> On 03.11.20 22:46, Ilya Leoshkevich wrote:
>>> gcc/testsuite/ChangeLog:
>>>
>>> 2020-11-03  Ilya Leoshkevich  <iii@linux.ibm.com>
>>>
>>> 	* gcc.target/s390/zvector/long-double-callee-abi-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-caller-abi-run.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-caller-abi-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-copysign-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-copysign-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-fprx2-constant.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-double-run.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-double-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-float-run.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-float-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-i16-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-i16-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-i32-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-i32-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-i64-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-i64-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-i8-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-i8-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-u16-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-u16-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-u32-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-u32-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-u64-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-u64-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-from-u8-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-from-u8-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-double-run.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-to-double-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-to-float-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-float-scan.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-to-i16-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i16-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i32-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i32-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i64-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i64-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i8-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-i8-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u16-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u16-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u32-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u32-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u64-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u64-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u8-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-to-u8-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-vec-duplicate.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-wf.h: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfaxb-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfaxb-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfaxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfcxb-0001.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfcxb-0111.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfcxb-1011.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfcxb-1101.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfdxb-run.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfdxb-scan.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfdxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfixb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfkxb-0111.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfkxb-1011.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfkxb-1101.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wflcxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wflpxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfmaxb-2.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfmaxb-3.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfmaxb-disabled.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-wfmaxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfmsxb-disabled.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-wfmsxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfmxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfnmaxb-disabled.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-wfnmaxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfnmsxb-disabled.c: New
>>> test.
>>> 	* gcc.target/s390/zvector/long-double-wfnmsxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfsqxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfsxb-1.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wfsxb.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wftcixb-1.c: New test.
>>> 	* gcc.target/s390/zvector/long-double-wftcixb.c: New test.
>>> ---
>>>  .../zvector/long-double-callee-abi-scan.c     | 20 +++++++
>>>  .../s390/zvector/long-double-caller-abi-run.c |  4 ++
>>>  .../zvector/long-double-caller-abi-scan.c     | 13 ++++
>>>  .../s390/zvector/long-double-copysign-run.c   | 14 +++++
>>>  .../s390/zvector/long-double-copysign-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-fprx2-constant.c | 11 ++++
>>>  .../zvector/long-double-from-double-run.c     | 12 ++++
>>>  .../zvector/long-double-from-double-scan.c    |  9 +++
>>>  .../s390/zvector/long-double-from-float-run.c | 12 ++++
>>>  .../zvector/long-double-from-float-scan.c     | 10 ++++
>>>  .../s390/zvector/long-double-from-i16-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-i16-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-i32-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-i32-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-i64-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-i64-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-i8-run.c    | 12 ++++
>>>  .../s390/zvector/long-double-from-i8-scan.c   | 11 ++++
>>>  .../s390/zvector/long-double-from-u16-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-u16-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-u32-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-u32-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-u64-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-from-u64-scan.c  | 11 ++++
>>>  .../s390/zvector/long-double-from-u8-run.c    | 12 ++++
>>>  .../s390/zvector/long-double-from-u8-scan.c   | 11 ++++
>>>  .../s390/zvector/long-double-to-double-run.c  | 12 ++++
>>>  .../s390/zvector/long-double-to-double-scan.c |  9 +++
>>>  .../s390/zvector/long-double-to-float-run.c   | 12 ++++
>>>  .../s390/zvector/long-double-to-float-scan.c  | 10 ++++
>>>  .../s390/zvector/long-double-to-i16-run.c     | 12 ++++
>>>  .../s390/zvector/long-double-to-i16-scan.c    | 11 ++++
>>>  .../s390/zvector/long-double-to-i32-run.c     | 12 ++++
>>>  .../s390/zvector/long-double-to-i32-scan.c    | 11 ++++
>>>  .../s390/zvector/long-double-to-i64-run.c     | 12 ++++
>>>  .../s390/zvector/long-double-to-i64-scan.c    | 13 ++++
>>>  .../s390/zvector/long-double-to-i8-run.c      | 12 ++++
>>>  .../s390/zvector/long-double-to-i8-scan.c     | 11 ++++
>>>  .../s390/zvector/long-double-to-u16-run.c     | 13 ++++
>>>  .../s390/zvector/long-double-to-u16-scan.c    | 11 ++++
>>>  .../s390/zvector/long-double-to-u32-run.c     | 13 ++++
>>>  .../s390/zvector/long-double-to-u32-scan.c    | 11 ++++
>>>  .../s390/zvector/long-double-to-u64-run.c     | 13 ++++
>>>  .../s390/zvector/long-double-to-u64-scan.c    | 11 ++++
>>>  .../s390/zvector/long-double-to-u8-run.c      | 13 ++++
>>>  .../s390/zvector/long-double-to-u8-scan.c     | 11 ++++
>>>  .../s390/zvector/long-double-vec-duplicate.c  | 13 ++++
>>>  .../gcc.target/s390/zvector/long-double-wf.h  | 60
>>> +++++++++++++++++++
>>>  .../s390/zvector/long-double-wfaxb-run.c      | 11 ++++
>>>  .../s390/zvector/long-double-wfaxb-scan.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfaxb.c          |  8 +++
>>>  .../s390/zvector/long-double-wfcxb-0001.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfcxb-0111.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfcxb-1011.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfcxb-1101.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfdxb-run.c      | 11 ++++
>>>  .../s390/zvector/long-double-wfdxb-scan.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfdxb.c          |  8 +++
>>>  .../s390/zvector/long-double-wfixb.c          |  8 +++
>>>  .../s390/zvector/long-double-wfkxb-0111.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfkxb-1011.c     | 10 ++++
>>>  .../s390/zvector/long-double-wfkxb-1101.c     | 10 ++++
>>>  .../s390/zvector/long-double-wflcxb.c         |  8 +++
>>>  .../s390/zvector/long-double-wflpxb.c         |  8 +++
>>>  .../s390/zvector/long-double-wfmaxb-2.c       | 24 ++++++++
>>>  .../s390/zvector/long-double-wfmaxb-3.c       | 14 +++++
>>>  .../zvector/long-double-wfmaxb-disabled.c     |  9 +++
>>>  .../s390/zvector/long-double-wfmaxb.c         |  8 +++
>>>  .../zvector/long-double-wfmsxb-disabled.c     |  9 +++
>>>  .../s390/zvector/long-double-wfmsxb.c         |  8 +++
>>>  .../s390/zvector/long-double-wfmxb.c          |  8 +++
>>>  .../zvector/long-double-wfnmaxb-disabled.c    | 10 ++++
>>>  .../s390/zvector/long-double-wfnmaxb.c        |  8 +++
>>>  .../zvector/long-double-wfnmsxb-disabled.c    | 10 ++++
>>>  .../s390/zvector/long-double-wfnmsxb.c        |  8 +++
>>>  .../s390/zvector/long-double-wfsqxb.c         |  8 +++
>>>  .../s390/zvector/long-double-wfsxb-1.c        | 21 +++++++
>>>  .../s390/zvector/long-double-wfsxb.c          |  8 +++
>>>  .../s390/zvector/long-double-wftcixb-1.c      | 15 +++++
>>>  .../s390/zvector/long-double-wftcixb.c        |  8 +++
>>>  80 files changed, 934 insertions(+)
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-callee-abi-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-caller-abi-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-caller-abi-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-copysign-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-copysign-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-fprx2-constant.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-double-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-double-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-float-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-float-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i16-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i16-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i32-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i32-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i64-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i64-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i8-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i8-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u16-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u16-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u32-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u32-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u64-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u64-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u8-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u8-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-double-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-double-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-float-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-float-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i16-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i16-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i32-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i32-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i64-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i64-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i8-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-i8-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u16-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u16-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u32-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u32-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u64-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u64-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u8-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-to-u8-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-vec-duplicate.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wf.h
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfaxb-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfaxb-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfaxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfcxb-0001.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfcxb-0111.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfcxb-1011.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfcxb-1101.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfdxb-run.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfdxb-scan.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfdxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfixb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfkxb-0111.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfkxb-1011.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfkxb-1101.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wflcxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wflpxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmaxb-2.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmaxb-3.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmaxb-disabled.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmaxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmsxb-disabled.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmsxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmaxb-disabled.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmaxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmsxb-disabled.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmsxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfsqxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfsxb-1.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfsxb.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wftcixb-1.c
>>>  create mode 100644 gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wftcixb.c
>>>
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> callee-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-callee-abi-scan.c
>>> new file mode 100644
>>> index 00000000000..005bfa9977a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-callee-abi-
>>> scan.c
>>> @@ -0,0 +1,20 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-
>>> loops" } */
>>> +#include <stdarg.h>
>>> +
>>> +__attribute__ ((noipa, used)) long double
>>> +long_double_callee (long double x, int n, ...)
>>> +{
>>> +  long double sum = x;
>>> +  va_list vl;
>>> +  int i;
>>> +
>>> +  va_start (vl, n);
>>> +  for (i = 0; i < n; i++)
>>> +    sum += va_arg (vl, long double);
>>> +  va_end (vl);
>>> +
>>> +  return sum;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tvl\t} 3 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> caller-abi-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-caller-abi-run.c
>>> new file mode 100644
>>> index 00000000000..d1756f5d34c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-
>>> run.c
>>> @@ -0,0 +1,4 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include "long-double-callee-abi-scan.c"
>>> +#include "long-double-caller-abi-scan.c"
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> caller-abi-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-caller-abi-scan.c
>>> new file mode 100644
>>> index 00000000000..ef690733fbf
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-caller-abi-
>>> scan.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +long double long_double_callee (long double x, int n, ...);
>>> +
>>> +int
>>> +main ()
>>> +{
>>> +  assert (long_double_callee (1.L, 2, 2.L, 3.L) == 6.L);
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tvst\t} 3 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> copysign-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> copysign-run.c
>>> new file mode 100644
>>> index 00000000000..c874b64d78e
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-
>>> run.c
>>> @@ -0,0 +1,14 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-copysign-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_copysign (1.1L, 2.2L) == 1.1L);
>>> +  assert (long_double_copysign (1.1L, -2.2L) == -1.1L);
>>> +  assert (long_double_copysign (-1.1L, 2.2L) == 1.1L);
>>> +  assert (long_double_copysign (-1.1L, -2.2L) == -1.1L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> copysign-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-copysign-scan.c
>>> new file mode 100644
>>> index 00000000000..6a44c0eff61
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-copysign-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_copysign (long double x, long double y)
>>> +{
>>> +  return __builtin_copysignl (x, y);
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tvsel\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> fprx2-constant.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-fprx2-constant.c
>>> new file mode 100644
>>> index 00000000000..02a6a1f69c5
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-fprx2-
>>> constant.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mtune=z14 -funroll-loops" } */
>>> +
>>> +long double a;
>>> +int d;
>>> +void
>>> +b ()
>>> +{
>>> +  for (int c = 0; c < d; ++c)
>>> +    a = (a - c) / (c + 1);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-double-run.c
>>> new file mode 100644
>>> index 00000000000..7a960ad119d
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-
>>> double-run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-double-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_double (42.) == 42.L);
>>> +  assert (long_double_from_double (-42.) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-double-scan.c
>>> new file mode 100644
>>> index 00000000000..db9ba4534c3
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-
>>> double-scan.c
>>> @@ -0,0 +1,9 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_double (double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-float-run.c
>>> new file mode 100644
>>> index 00000000000..41256b39abc
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-float-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_float (42.F) == 42.L);
>>> +  assert (long_double_from_float (-42.F) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-float-scan.c
>>> new file mode 100644
>>> index 00000000000..4b9b570fcfb
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-float-
>>> scan.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_float (float x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tldebr\t} 1 } } */
>>> +/* { dg-final { scan-assembler-times {\n\twflld\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i16-run.c
>>> new file mode 100644
>>> index 00000000000..6c0fac93da5
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-i16-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_i16 (42) == 42.L);
>>> +  assert (long_double_from_i16 (-42) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i16-scan.c
>>> new file mode 100644
>>> index 00000000000..18af4d82f57
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i16-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_i16 (int16_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i32-run.c
>>> new file mode 100644
>>> index 00000000000..2baa6e156f7
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-i32-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_i32 (42) == 42.L);
>>> +  assert (long_double_from_i32 (-42) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i32-scan.c
>>> new file mode 100644
>>> index 00000000000..433b6bbffe5
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i32-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_i32 (int32_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i64-run.c
>>> new file mode 100644
>>> index 00000000000..c6f460064e0
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-i64-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_i64 (42) == 42.L);
>>> +  assert (long_double_from_i64 (-42) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-i64-scan.c
>>> new file mode 100644
>>> index 00000000000..f418dffd8b0
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i64-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_i64 (int64_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxgbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i8-run.c
>>> new file mode 100644
>>> index 00000000000..15c46d8a909
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-i8-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_i8 (42) == 42.L);
>>> +  assert (long_double_from_i8 (-42) == -42.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-i8-scan.c
>>> new file mode 100644
>>> index 00000000000..7a8b3fdaad0
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-i8-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_i8 (int8_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u16-run.c
>>> new file mode 100644
>>> index 00000000000..495b3f9f18d
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-u16-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_u16 (42) == 42.L);
>>> +  assert (long_double_from_u16 (-42) == 65494.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u16-scan.c
>>> new file mode 100644
>>> index 00000000000..b65e10269df
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u16-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_u16 (uint16_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u32-run.c
>>> new file mode 100644
>>> index 00000000000..072ae99ef24
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-u32-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_u32 (42) == 42.L);
>>> +  assert (long_double_from_u32 (-42) == 4294967254.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u32-scan.c
>>> new file mode 100644
>>> index 00000000000..408e3d1b570
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u32-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_u32 (uint32_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u64-run.c
>>> new file mode 100644
>>> index 00000000000..6146c322611
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-u64-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_u64 (42) == 42.L);
>>> +  assert (long_double_from_u64 (-42) == 18446744073709551574.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-from-u64-scan.c
>>> new file mode 100644
>>> index 00000000000..856912d5689
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u64-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_u64 (uint64_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxlgbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u8-run.c
>>> new file mode 100644
>>> index 00000000000..d769d006499
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-from-u8-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_from_u8 (42) == 42.L);
>>> +  assert (long_double_from_u8 (-42) == 214.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> from-u8-scan.c
>>> new file mode 100644
>>> index 00000000000..d1421d4322c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-from-u8-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +long_double_from_u8 (uint8_t x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcxlfbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> double-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> to-double-run.c
>>> new file mode 100644
>>> index 00000000000..b68ce88529a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-double-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_double (42.L) == 42.);
>>> +  assert (long_double_to_double (-42.L) == -42.);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> double-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> to-double-scan.c
>>> new file mode 100644
>>> index 00000000000..78ce18b38c4
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-double-
>>> scan.c
>>> @@ -0,0 +1,9 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +__attribute__ ((noipa, used)) static double
>>> +long_double_to_double (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\twflrx\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> float-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> float-run.c
>>> new file mode 100644
>>> index 00000000000..70a8a3e7f73
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-float-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_float (42.L) == 42.F);
>>> +  assert (long_double_to_float (-42.L) == -42.F);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> float-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> to-float-scan.c
>>> new file mode 100644
>>> index 00000000000..1f0b60a3f03
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-float-
>>> scan.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +__attribute__ ((noipa, used)) static float
>>> +long_double_to_float (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times
>>> {\n\twflrx\t%v\d+,%v\d+,0,3\n} 1 } } */
>>> +/* { dg-final { scan-assembler-times {\n\tledbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i16-run.c
>>> new file mode 100644
>>> index 00000000000..2044baa45af
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-i16-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_i16 (42.L) == 42);
>>> +  assert (long_double_to_i16 (-42.L) == -42);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i16-scan.c
>>> new file mode 100644
>>> index 00000000000..3c47ae97c39
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i16-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static int16_t
>>> +long_double_to_i16 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i32-run.c
>>> new file mode 100644
>>> index 00000000000..9f98ea39f6f
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-i32-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_i32 (42.L) == 42);
>>> +  assert (long_double_to_i32 (-42.L) == -42);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i32-scan.c
>>> new file mode 100644
>>> index 00000000000..978b4751bff
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i32-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static int32_t
>>> +long_double_to_i32 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i64-run.c
>>> new file mode 100644
>>> index 00000000000..f2a27ff4fec
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-
>>> run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-i64-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_i64 (42.L) == 42);
>>> +  assert (long_double_to_i64 (-42.L) == -42);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i64-scan.c
>>> new file mode 100644
>>> index 00000000000..38a212ac3c7
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i64-
>>> scan.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static int64_t
>>> +long_double_to_i64 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times
>>> {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
>>> +/* { dg-final { scan-assembler-times
>>> {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
>>> +/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-
>>> run.c
>>> new file mode 100644
>>> index 00000000000..0e0624b2788
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-run.c
>>> @@ -0,0 +1,12 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-i8-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_i8 (42.L) == 42);
>>> +  assert (long_double_to_i8 (-42.L) == -42);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> i8-scan.c
>>> new file mode 100644
>>> index 00000000000..d015b8a307b
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-i8-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static int8_t
>>> +long_double_to_i8 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tcfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u16-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u16-run.c
>>> new file mode 100644
>>> index 00000000000..7bac113a04c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-
>>> run.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-u16-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_u16 (42.L) == 42);
>>> +  /* Not (-42 & 0xffff) due to loss of precision.  */
>>> +  assert (long_double_to_u16 (-42.L) == 0);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u16-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u16-scan.c
>>> new file mode 100644
>>> index 00000000000..a7694ceb3ad
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u16-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static uint16_t
>>> +long_double_to_u16 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u32-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u32-run.c
>>> new file mode 100644
>>> index 00000000000..b85038c0723
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-
>>> run.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-u32-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_u32 (42.L) == 42);
>>> +  /* Not (-42 & 0xffffffff) due to loss of precision.  */
>>> +  assert (long_double_to_u32 (-42.L) == 0);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u32-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u32-scan.c
>>> new file mode 100644
>>> index 00000000000..ff97803d320
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u32-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static uint32_t
>>> +long_double_to_u32 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u64-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u64-run.c
>>> new file mode 100644
>>> index 00000000000..e781637dac3
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-
>>> run.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-u64-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_u64 (42.L) == 42);
>>> +  /* Not (-42 & 0xffffffffffffffff) due to loss of precision.  */
>>> +  assert (long_double_to_u64 (-42.L) == 0);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u64-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u64-scan.c
>>> new file mode 100644
>>> index 00000000000..d97c0ec35dd
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u64-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static uint64_t
>>> +long_double_to_u64 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tclgxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u8-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-
>>> run.c
>>> new file mode 100644
>>> index 00000000000..7ae330b6aa1
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-run.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-to-u8-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (long_double_to_u8 (42.L) == 42);
>>> +  /* Not (-42 & 0xff) due to loss of precision.  */
>>> +  assert (long_double_to_u8 (-42.L) == 0);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u8-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-
>>> u8-scan.c
>>> new file mode 100644
>>> index 00000000000..0500bc1c946
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-to-u8-
>>> scan.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <stdint.h>
>>> +
>>> +__attribute__ ((noipa, used)) static uint8_t
>>> +long_double_to_u8 (long double x)
>>> +{
>>> +  return x;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\tclfxbr\t} 1 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-
>>> duplicate.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> vec-duplicate.c
>>> new file mode 100644
>>> index 00000000000..2ce9da33b8e
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-vec-
>>> duplicate.c
>>> @@ -0,0 +1,13 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -funroll-loops -march=z14 -mtune=z14" } */
>>> +
>>> +long double a, b;
>>> +double *c;
>>> +long double *d;
>>> +
>>> +void
>>> +e ()
>>> +{
>>> +  while (d != &a)
>>> +    *d++ = b * *c++;
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h 
>>> b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
>>> new file mode 100644
>>> index 00000000000..a564fc62d47
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wf.h
>>> @@ -0,0 +1,60 @@
>>> +#ifndef LONG_DOUBLE_WF_H
>>> +#define LONG_DOUBLE_WF_H 1
>>> +
>>> +#include <math.h>
>>> +
>>> +#define ADD(x, y, z) ((x) + (z))
>>> +#define DIV(x, y, z) ((x) / (z))
>>> +#define FABSL(x, y, z) (fabsl (y))
>>> +#define ISINFL(x, y, z) (isinfl (x) ? (y) : (z))
>>> +#define MUL(x, y, z) ((x) * (z))
>>> +#define MUL_ADD(x, y, z) ((x) * (y) + (z))
>>> +#define MUL_SUB(x, y, z) ((x) * (y) - (z))
>>> +#define NEG(x, y,
>>> z)                                                          \
>>> +  ({                                                              
>>>             \
>>> +    volatile long double r =
>>> -(y);                                            \
>>> +    r;                                                            
>>>             \
>>> +  })
>>> +#define NEG_MUL_ADD(x, y, z) NEG (0, MUL_ADD (x, y, z), 0)
>>> +#define NEG_MUL_SUB(x, y, z) NEG (0, MUL_SUB (x, y, z), 0)
>>> +#define QUIET_IFEQUAL(x, y, z) ((x) == (y) ? (z) : 0)
>>> +#define QUIET_IFGREATER(x, y, z) (__builtin_isgreater (x, y) ? (z)
>>> : 0)
>>> +#define QUIET_IFLESS(x, y, z) (__builtin_isless (x, y) ? (z) : 0)
>>> +#define QUIET_IFUNORDERED(x, y, z) (__builtin_isunordered (x, y) ?
>>> (z) : 0)
>>> +#define SIGNALING_IFEQUAL(x, y, z) (((x) >= (y) && (x) <= (y)) ?
>>> (z) : 0)
>>> +#define SIGNALING_IFGREATER(x, y, z) ((x) > (y) ? (z) : 0)
>>> +#define SIGNALING_IFLESS(x, y, z) ((x) < (y) ? (z) : 0)
>>> +#define ROUNDL(x, y, z) (roundl (y))
>>> +#define SQRTL(x, y, z) (sqrtl (y))
>>> +#define SUB(x, y, z) ((x) - (z))
>>> +
>>> +#define
>>> LONG_DOUBLE_WF(op)                                                 
>>>    \
>>> +  long double test
>>> (                                                          \
>>> +      long double x0, long double x1, long double x2, long double
>>> x3,         \
>>> +      long double x4, long double x5, long double x6, long double
>>> x7,         \
>>> +      long double x8, long double x9, long double x10, long double
>>> x11,       \
>>> +      long double x12, long double x13, long double x14, long
>>> double x15)     \
>>> +  {                                                               
>>>             \
>>> +    while (x15 <
>>> 1E+30)                                                       \
>>> +      {                                                           
>>>             \
>>> +	x0 = op (x1, x2,
>>> x3);                                                 \
>>> +	x1 = op (x2, x3, x4) +
>>> 1;                                             \
>>> +	x2 = op (x3, x4, x5) +
>>> 2;                                             \
>>> +	x3 = op (x4, x5, x6) +
>>> 3;                                             \
>>> +	x4 = op (x5, x6, x7) +
>>> 4;                                             \
>>> +	x5 = op (x6, x7, x8) +
>>> 5;                                             \
>>> +	x6 = op (x7, x8, x9) +
>>> 6;                                             \
>>> +	x7 = op (x8, x9, x10) +
>>> 7;                                            \
>>> +	x8 = op (x9, x10, x11) +
>>> 8;                                           \
>>> +	x9 = op (x10, x11, x12) +
>>> 9;                                          \
>>> +	x10 = op (x11, x12, x13) +
>>> 10;                                        \
>>> +	x11 = op (x12, x13, x14) +
>>> 11;                                        \
>>> +	x12 = op (x13, x14, x15) +
>>> 12;                                        \
>>> +	x13 = op (x14, x15, x0) +
>>> 13;                                         \
>>> +	x14 = op (x15, x0, x1) +
>>> 14;                                          \
>>> +	x15 = op (x0, x1, x2) +
>>> 15;                                           \
>>> +      }                                                           
>>>             \
>>> +    return
>>> x15;                                                               
>>> \
>>> +  }
>>> +
>>> +#endif
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfaxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfaxb-run.c
>>> new file mode 100644
>>> index 00000000000..de7770068ea
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-run.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-wfaxb-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (wfaxb (1.11L, 2.22L, 3.33L) == 6.66L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfaxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfaxb-scan.c
>>> new file mode 100644
>>> index 00000000000..2bbf408416a
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb-
>>> scan.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +wfaxb (long double x, long double y, long double z)
>>> +{
>>> +  return x + y + z;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\twfaxb\t} 2 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
>>> new file mode 100644
>>> index 00000000000..354dbe226b0
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfaxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (ADD);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-0001.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-0001.c
>>> new file mode 100644
>>> index 00000000000..d0a32d51902
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
>>> 0001.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (QUIET_IFUNORDERED);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
>>> +/* jo == brc 0b0001, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjo\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-0111.c
>>> new file mode 100644
>>> index 00000000000..04a34e7373c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
>>> 0111.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (QUIET_IFEQUAL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
>>> +/* jne == brc 0b0111, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjne\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-1011.c
>>> new file mode 100644
>>> index 00000000000..f221a56ffb8
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
>>> 1011.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (QUIET_IFLESS);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
>>> +/* jnl == brc 0b1011, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfcxb-1101.c
>>> new file mode 100644
>>> index 00000000000..d2353ebe30c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfcxb-
>>> 1101.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (QUIET_IFGREATER);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfcxb\t} } } */
>>> +/* jnh == brc 0b1101, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfdxb-run.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfdxb-run.c
>>> new file mode 100644
>>> index 00000000000..7ac752dc289
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-run.c
>>> @@ -0,0 +1,11 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +#include "long-double-wfdxb-scan.c"
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  assert (wfdxb (2.22L, 1.11L, 2.L) == 1.L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfdxb-scan.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfdxb-scan.c
>>> new file mode 100644
>>> index 00000000000..31eea0f9329
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb-
>>> scan.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +__attribute__ ((noipa, used)) static long double
>>> +wfdxb (long double x, long double y, long double z)
>>> +{
>>> +  return (x / y) / z;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times {\n\twfdxb\t} 2 } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfdxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
>>> new file mode 100644
>>> index 00000000000..7d854cac1bc
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfdxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (DIV);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfdxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
>>> new file mode 100644
>>> index 00000000000..5e16ffa58e6
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfixb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (ROUNDL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfixb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-0111.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-0111.c
>>> new file mode 100644
>>> index 00000000000..2e7b1c37d08
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
>>> 0111.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (SIGNALING_IFEQUAL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
>>> +/* jne == brc 0b0111, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjne\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-1011.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-1011.c
>>> new file mode 100644
>>> index 00000000000..2d2020af842
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
>>> 1011.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (SIGNALING_IFLESS);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
>>> +/* jnl == brc 0b1011, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjnl\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-1101.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfkxb-1101.c
>>> new file mode 100644
>>> index 00000000000..f17f83ca568
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfkxb-
>>> 1101.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (SIGNALING_IFGREATER);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfkxb\t} } } */
>>> +/* jnh == brc 0b1101, ...  */
>>> +/* { dg-final { scan-assembler {\n\tjnh\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wflcxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wflcxb.c
>>> new file mode 100644
>>> index 00000000000..c69161beca9
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflcxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (NEG);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wflpxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wflpxb.c
>>> new file mode 100644
>>> index 00000000000..df3c1dbccb8
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wflpxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (FABSL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twflpxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb-2.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb-2.c
>>> new file mode 100644
>>> index 00000000000..9335680a70c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-2.c
>>> @@ -0,0 +1,24 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +int a, c, d, f, k, l, m;
>>> +long double b, e, g, h, i;
>>> +double j;
>>> +
>>> +void
>>> +n (void)
>>> +{
>>> +  while (m)
>>> +    {
>>> +      a = b * d;
>>> +      b = c;
>>> +      c = d * e + 2;
>>> +      e = f + g + 4;
>>> +      f = h + 6;
>>> +      g = h * 0 + i + 7;
>>> +      h = i + 9;
>>> +      i = j * k + 0 + 10;
>>> +      j = l;
>>> +      m = a * b;
>>> +    }
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb-3.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb-3.c
>>> new file mode 100644
>>> index 00000000000..9cc2b85f673
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-3.c
>>> @@ -0,0 +1,14 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +long double a, c, d;
>>> +int b;
>>> +void
>>> +e (void)
>>> +{
>>> +  while (d)
>>> +    {
>>> +      a = 0 * c + 0;
>>> +      d = b;
>>> +    }
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmaxb-disabled.c
>>> new file mode 100644
>>> index 00000000000..c9e5a7b066c
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb-
>>> disabled.c
>>> @@ -0,0 +1,9 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (MUL_ADD);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmaxb.c
>>> new file mode 100644
>>> index 00000000000..fddad943f18
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmaxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (MUL_ADD);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmaxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfmsxb-disabled.c
>>> new file mode 100644
>>> index 00000000000..e78178b9a0b
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb-
>>> disabled.c
>>> @@ -0,0 +1,9 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (MUL_SUB);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmsxb.c
>>> new file mode 100644
>>> index 00000000000..1fe71ecf09f
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmsxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (MUL_SUB);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmsxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfmxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
>>> new file mode 100644
>>> index 00000000000..ce311f89db4
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfmxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (MUL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmaxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmaxb-disabled.c
>>> new file mode 100644
>>> index 00000000000..da8a73adcee
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb-
>>> disabled.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (NEG_MUL_ADD);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twfaxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmaxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmaxb.c
>>> new file mode 100644
>>> index 00000000000..75b28137048
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmaxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (NEG_MUL_ADD);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfnmaxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmsxb-disabled.c b/gcc/testsuite/gcc.target/s390/zvector/long-
>>> double-wfnmsxb-disabled.c
>>> new file mode 100644
>>> index 00000000000..9a07d049ed4
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb-
>>> disabled.c
>>> @@ -0,0 +1,10 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (NEG_MUL_SUB);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfmxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
>>> +/* { dg-final { scan-assembler {\n\twflcxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfnmsxb.c
>>> new file mode 100644
>>> index 00000000000..16b80890725
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfnmsxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -mvx-long-
>>> double-fma" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (NEG_MUL_SUB);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfnmsxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfsqxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfsqxb.c
>>> new file mode 100644
>>> index 00000000000..2f42483dfee
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsqxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (SQRTL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfsqxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfsxb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfsxb-1.c
>>> new file mode 100644
>>> index 00000000000..dd2f244a4eb
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb-1.c
>>> @@ -0,0 +1,21 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +#include <assert.h>
>>> +
>>> +typedef float tf __attribute__ ((mode (TF)));
>>> +static tf x;
>>> +static tf y;
>>> +
>>> +__attribute__ ((noipa)) static tf
>>> +sub (void)
>>> +{
>>> +  return x - y;
>>> +}
>>> +
>>> +int
>>> +main (void)
>>> +{
>>> +  x = 1.5L;
>>> +  y = 2.5L;
>>> +  assert (sub () == -1.0L);
>>> +}
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wfsxb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
>>> new file mode 100644
>>> index 00000000000..d27cf8ca3de
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wfsxb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (SUB);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twfsxb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wftcixb-1.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wftcixb-1.c
>>> new file mode 100644
>>> index 00000000000..6915d8ed8a4
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb-1.c
>>> @@ -0,0 +1,15 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O1 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +int a, b;
>>> +
>>> +void
>>> +c (void)
>>> +{
>>> +  long double d;
>>> +  a = d;
>>> +  if (__builtin_isinf (d))
>>> +    b = 0;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
>>> diff --git a/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wftcixb.c b/gcc/testsuite/gcc.target/s390/zvector/long-double-
>>> wftcixb.c
>>> new file mode 100644
>>> index 00000000000..1134e26ee87
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/s390/zvector/long-double-wftcixb.c
>>> @@ -0,0 +1,8 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */
>>> +
>>> +#include "long-double-wf.h"
>>> +
>>> +LONG_DOUBLE_WF (ISINFL);
>>> +
>>> +/* { dg-final { scan-assembler {\n\twftcixb\t} } } */
>>>
> 


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

end of thread, other threads:[~2020-11-05  7:28 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03 21:36 [PATCH 0/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
2020-11-03 21:36 ` [PATCH 1/4] IBM Z: Remove unused RRe and RXe mode_attrs Ilya Leoshkevich
2020-11-04 17:14   ` Andreas Krebbel
2020-11-03 21:45 ` [PATCH 2/4] IBM Z: Unhardcode NR_C_MODES Ilya Leoshkevich
2020-11-04 17:14   ` Andreas Krebbel
2020-11-03 21:45 ` [PATCH 3/4] IBM Z: Store long doubles in vector registers when possible Ilya Leoshkevich
2020-11-04 17:16   ` Andreas Krebbel
2020-11-04 22:12     ` Ilya Leoshkevich
2020-11-05  7:26       ` Andreas Krebbel
2020-11-03 21:46 ` [PATCH 4/4] IBM Z: Test long doubles in vector registers Ilya Leoshkevich
2020-11-04 17:28   ` Andreas Krebbel
2020-11-04 22:19     ` Ilya Leoshkevich
2020-11-05  7:28       ` Andreas Krebbel

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