[PATCH 15/16] S/390: arch12: Support new vector floating point modes.

Andreas Krebbel krebbel@linux.vnet.ibm.com
Fri Mar 24 14:13:00 GMT 2017


This patch adds support for the new floating point vector elements (SF
and TF) introduced with arch12.

gcc/ChangeLog:

2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

	* config/s390/s390.c (s390_expand_vec_compare): Support other
	vector floating point modes than just V2DF.
	(s390_expand_vcond): Likewise.
	(s390_hard_regno_mode_ok): Allow SFmode values in VRs.
	(s390_cannot_change_mode_class): Prevent mode changes between TF
	and V1TF in vector registers.
	* config/s390/s390.md (DF, SF): New mode attributes.
	("*cmp<mode>_ccs", "add<mode>3", "sub<mode>3", "mul<mode>3")
	("fma<mode>4", "fms<mode>4", "div<mode>3", "*neg<mode>2"): Add
	SFmode support for VRs.
	* config/s390/vector.md (V_HW, V_HW2, VT_HW, ti*, nonvec): Add new
	vector fp modes.
	(VFT, VF_HW): New mode iterators.
	(vw, sdx): New mode attributes.
	("addv2df3", "subv2df3", "mulv2df3", "divv2df3", "sqrtv2df2")
	("fmav2df4","fmsv2df4", "negv2df2", "absv2df2", "*negabsv2df2")
	("smaxv2df3", "sminv2df3", "*vec_cmp<VFCMP_HW_OP:code>v2df_nocc")
	("vec_cmpuneqv2df", "vec_cmpltgtv2df", "vec_orderedv2df")
	("vec_unorderedv2df"): Adjust the v2df only patterns to support
	also the new vector floating point modes.  Renaming to ...

	("add<mode>3", "sub<mode>3", "mul<mode>3", "div<mode>3")
	("sqrt<mode>2", "fma<mode>4", "fms<mode>4", "neg<mode>2")
	("abs<mode>2", "negabs<mode>2", "smax<mode>3")
	("smin<mode>3", "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc")
	("vec_cmpuneq<mode>", "vec_cmpltgt<mode>", "vec_ordered<mode>")
	("vec_unordered<mode>"): ... these.

	("neg_fma<mode>4", "neg_fms<mode>4", "*smax<mode>3_vxe")
	("*smin<mode>3_vxe", "*sminv2df3_vx", "*vec_extendv4sf")
	("*vec_extendv2df"): New insn definitions.

gcc/testsuite/ChangeLog:

2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

	* gcc.target/s390/vxe/negfma-1.c: New test.
---
 gcc/ChangeLog                                |  34 +++
 gcc/config/s390/s390-builtins.def            |   2 +-
 gcc/config/s390/s390.c                       |  13 +-
 gcc/config/s390/s390.md                      | 144 ++++++------
 gcc/config/s390/vector.md                    | 313 ++++++++++++++++++---------
 gcc/testsuite/ChangeLog                      |   4 +
 gcc/testsuite/gcc.target/s390/vxe/negfma-1.c |  49 +++++
 7 files changed, 388 insertions(+), 171 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/vxe/negfma-1.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3753ad6..bd60982 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,39 @@
 2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
+	* config/s390/s390.c (s390_expand_vec_compare): Support other
+	vector floating point modes than just V2DF.
+	(s390_expand_vcond): Likewise.
+	(s390_hard_regno_mode_ok): Allow SFmode values in VRs.
+	(s390_cannot_change_mode_class): Prevent mode changes between TF
+	and V1TF in vector registers.
+	* config/s390/s390.md (DF, SF): New mode attributes.
+	("*cmp<mode>_ccs", "add<mode>3", "sub<mode>3", "mul<mode>3")
+	("fma<mode>4", "fms<mode>4", "div<mode>3", "*neg<mode>2"): Add
+	SFmode support for VRs.
+	* config/s390/vector.md (V_HW, V_HW2, VT_HW, ti*, nonvec): Add new
+	vector fp modes.
+	(VFT, VF_HW): New mode iterators.
+	(vw, sdx): New mode attributes.
+	("addv2df3", "subv2df3", "mulv2df3", "divv2df3", "sqrtv2df2")
+	("fmav2df4","fmsv2df4", "negv2df2", "absv2df2", "*negabsv2df2")
+	("smaxv2df3", "sminv2df3", "*vec_cmp<VFCMP_HW_OP:code>v2df_nocc")
+	("vec_cmpuneqv2df", "vec_cmpltgtv2df", "vec_orderedv2df")
+	("vec_unorderedv2df"): Adjust the v2df only patterns to support
+	also the new vector floating point modes.  Renaming to ...
+
+	("add<mode>3", "sub<mode>3", "mul<mode>3", "div<mode>3")
+	("sqrt<mode>2", "fma<mode>4", "fms<mode>4", "neg<mode>2")
+	("abs<mode>2", "negabs<mode>2", "smax<mode>3")
+	("smin<mode>3", "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc")
+	("vec_cmpuneq<mode>", "vec_cmpltgt<mode>", "vec_ordered<mode>")
+	("vec_unordered<mode>"): ... these.
+
+	("neg_fma<mode>4", "neg_fms<mode>4", "*smax<mode>3_vxe")
+	("*smin<mode>3_vxe", "*sminv2df3_vx", "*vec_extendv4sf")
+	("*vec_extendv2df"): New insn definitions.
+
+2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
 	* config/s390/s390.md ("*adddi3_sign", "*subdi3_sign", "mulditi3")
 	("mulditi3_2", "*muldi3_sign"): New patterns.
 	("muldi3", "*muldi3", "mulsi3", "*mulsi3"): Add an expander and
diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def
index 27cb6a8..bb2d743 100644
--- a/gcc/config/s390/s390-builtins.def
+++ b/gcc/config/s390/s390-builtins.def
@@ -2496,7 +2496,7 @@ B_DEF      (s390_vec_ctsl,              vec_ctsl,           0,
 B_DEF      (s390_vec_ctul,              vec_ctul,           0,                  B_VX,               O2_U3,              BT_FN_UV2DI_V2DF_INT)                    /* vclgdb */
 B_DEF      (s390_vcgdb,                 vec_df_to_di_s64,   0,                  B_VX,               O2_U3,              BT_FN_V2DI_V2DF_INT)                     /* vcgdb */
 B_DEF      (s390_vclgdb,                vec_df_to_di_u64,   0,                  B_VX,               O2_U3,              BT_FN_UV2DI_V2DF_INT)                    /* vclgdb */
-B_DEF      (s390_vfidb,                 vfidb,              0,                  B_VX,               O2_U4 | O3_U3,      BT_FN_V2DF_V2DF_UCHAR_UCHAR)
+B_DEF      (s390_vfidb,                 vfiv2df,            0,                  B_VX,               O2_U4 | O3_U3,      BT_FN_V2DF_V2DF_UCHAR_UCHAR)
 B_DEF      (s390_vec_ld2f,              vec_ld2f,           0,                  B_VX,               0,                  BT_FN_V2DF_FLTCONSTPTR)                  /* vldeb */
 B_DEF      (s390_vec_st2f,              vec_st2f,           0,                  B_VX,               0,                  BT_FN_VOID_V2DF_FLTPTR)                  /* vledb */
 B_DEF      (s390_vfmadb,                fmav2df4,           0,                  B_VX,               0,                  BT_FN_V2DF_V2DF_V2DF_V2DF)
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index e800323..1d26979 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6201,7 +6201,7 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
   bool neg_p = false, swap_p = false;
   rtx tmp;
 
-  if (GET_MODE (cmp_op1) == V2DFmode)
+  if (GET_MODE_CLASS (GET_MODE (cmp_op1)) == MODE_VECTOR_FLOAT)
     {
       switch (cond)
 	{
@@ -6447,7 +6447,8 @@ s390_expand_vcond (rtx target, rtx then, rtx els,
 
   /* We always use an integral type vector to hold the comparison
      result.  */
-  result_mode = cmp_mode == V2DFmode ? V2DImode : cmp_mode;
+  result_mode = mode_for_vector (int_mode_for_mode (GET_MODE_INNER (cmp_mode)),
+				 GET_MODE_NUNITS (cmp_mode));
   result_target = gen_reg_rtx (result_mode);
 
   /* We allow vector immediates as comparison operands that
@@ -10112,6 +10113,7 @@ s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
       return ((GET_MODE_CLASS (mode) == MODE_INT
 	       && s390_class_max_nregs (VEC_REGS, mode) == 1)
 	      || mode == DFmode
+	      || (TARGET_VXE && mode == SFmode)
 	      || s390_vector_mode_supported_p (mode));
       break;
     case FP_REGS:
@@ -10256,6 +10258,13 @@ s390_cannot_change_mode_class (machine_mode from_mode,
   machine_mode small_mode;
   machine_mode big_mode;
 
+  /* V1TF and TF have different representations in vector
+     registers.  */
+  if (reg_classes_intersect_p (VEC_REGS, rclass)
+      && ((from_mode == V1TFmode && to_mode == TFmode)
+	  || (from_mode == TFmode && to_mode == V1TFmode)))
+    return 1;
+
   if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode))
     return 0;
 
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 93a0bc6..7e9add7 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -674,6 +674,12 @@
 (define_mode_attr DFDI [(TF "0") (DF "*") (SF "0")
 			(TD "0") (DD "0") (DD "0")
 			(TI "0") (DI "*") (SI "0")])
+(define_mode_attr DF [(TF "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 "*")
+		      (TD "0") (DD "0") (DD "0")
+		      (TI "0") (DI "0") (SI "0")])
 
 ;; This attribute is used in the operand constraint list
 ;; for instructions dealing with the sign bit of 32 or 64bit fp values.
@@ -1325,20 +1331,21 @@
  })
 
 
-; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcdb
+; VX: TFmode in FPR pairs: use cxbr instead of wfcxb
+; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcsb, wfcdb
 (define_insn "*cmp<mode>_ccs"
   [(set (reg CC_REGNUM)
-        (compare (match_operand:FP 0 "register_operand" "f,f,v")
-                 (match_operand:FP 1 "general_operand"  "f,R,v")))]
+        (compare (match_operand:FP 0 "register_operand" "f,f,v,v")
+                 (match_operand:FP 1 "general_operand"  "f,R,v,v")))]
   "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT"
   "@
    c<xde><bt>r\t%0,%1
    c<xde>b\t%0,%1
-   wfcdb\t%0,%1"
-  [(set_attr "op_type" "RRE,RXE,VRR")
-   (set_attr "cpu_facility" "*,*,vx")
-   (set_attr "enabled" "*,<DSF>,<DFDI>")])
-
+   wfcdb\t%0,%1
+   wfcsb\t%0,%1"
+  [(set_attr "op_type" "RRE,RXE,VRR,VRR")
+   (set_attr "cpu_facility" "*,*,vx,vxe")
+   (set_attr "enabled" "*,<DSF>,<DF>,<SF>")])
 
 ; Compare and Branch instructions
 
@@ -5159,6 +5166,7 @@
 ; extend(sf|df)(df|tf)2 instruction pattern(s).
 ;
 
+; wflls
 (define_insn "*extendsfdf2_z13"
   [(set (match_operand:DF                  0 "register_operand"     "=f,f,v")
         (float_extend:DF (match_operand:SF 1 "nonimmediate_operand"  "f,R,v")))]
@@ -5811,20 +5819,21 @@
 ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
 ; FIXME: wfadb does not clobber cc
 (define_insn "add<mode>3"
-  [(set (match_operand:FP 0 "register_operand"              "=f,f,f,v")
-        (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v")
-		 (match_operand:FP 2 "general_operand"       "f,f,R,v")))
+  [(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")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_HARD_FLOAT"
   "@
    a<xde>tr\t%0,%1,%2
    a<xde>br\t%0,%2
    a<xde>b\t%0,%2
-   wfadb\t%v0,%v1,%v2"
-  [(set_attr "op_type"      "RRF,RRE,RXE,VRR")
+   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 "cpu_facility" "*,*,*,vx")
-   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,*,vx,vxe")
+   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
 ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
 (define_insn "*add<mode>3_cc"
@@ -6249,28 +6258,30 @@
 ; sub(tf|df|sf|td|dd)3 instruction pattern(s).
 ;
 
+; 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"
-  [(set (match_operand:FP           0 "register_operand" "=f,f,f,v")
-        (minus:FP (match_operand:FP 1 "register_operand"  "f,0,0,v")
-                  (match_operand:FP 2 "general_operand"   "f,f,R,v")))
+  [(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")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_HARD_FLOAT"
   "@
    s<xde>tr\t%0,%1,%2
    s<xde>br\t%0,%2
    s<xde>b\t%0,%2
-   wfsdb\t%v0,%v1,%v2"
-  [(set_attr "op_type"      "RRF,RRE,RXE,VRR")
+   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 "cpu_facility" "*,*,*,vx")
-   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,*,vx,vxe")
+   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
 ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
 (define_insn "*sub<mode>3_cc"
   [(set (reg CC_REGNUM)
 	(compare (minus:FP (match_operand:FP 1 "nonimmediate_operand" "f,0,0")
-                           (match_operand:FP 2 "general_operand"      "f,f,R"))
+			   (match_operand:FP 2 "general_operand"      "f,f,R"))
 		 (match_operand:FP 3 "const0_operand" "")))
    (set (match_operand:FP 0 "register_operand" "=f,f,f")
 	(minus:FP (match_dup 1) (match_dup 2)))]
@@ -6736,51 +6747,54 @@
 
 ; mxbr, mdbr, meebr, mxb, mxb, meeb, mdtr, mxtr
 (define_insn "mul<mode>3"
-  [(set (match_operand:FP          0 "register_operand"     "=f,f,f,v")
-        (mult:FP (match_operand:FP 1 "nonimmediate_operand" "%f,0,0,v")
-                 (match_operand:FP 2 "general_operand"       "f,f,R,v")))]
+  [(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")))]
   "TARGET_HARD_FLOAT"
   "@
    m<xdee>tr\t%0,%1,%2
    m<xdee>br\t%0,%2
    m<xdee>b\t%0,%2
-   wfmdb\t%v0,%v1,%v2"
-  [(set_attr "op_type"      "RRF,RRE,RXE,VRR")
+   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 "cpu_facility" "*,*,*,vx")
-   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,*,vx,vxe")
+   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
 ; madbr, maebr, maxb, madb, maeb
 (define_insn "fma<mode>4"
-  [(set (match_operand:DSF          0 "register_operand"     "=f,f,v")
-	(fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,v")
-		 (match_operand:DSF 2 "nonimmediate_operand"  "f,R,v")
-		 (match_operand:DSF 3 "register_operand"      "0,0,v")))]
+  [(set (match_operand:DSF          0 "register_operand"     "=f,f,v,v")
+	(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"
   "@
    ma<xde>br\t%0,%1,%2
    ma<xde>b\t%0,%1,%2
-   wfmadb\t%v0,%v1,%v2,%v3"
-  [(set_attr "op_type"      "RRE,RXE,VRR")
+   wfmadb\t%v0,%v1,%v2,%v3
+   wfmasb\t%v0,%v1,%v2,%v3"
+  [(set_attr "op_type"      "RRE,RXE,VRR,VRR")
    (set_attr "type"         "fmadd<mode>")
-   (set_attr "cpu_facility" "*,*,vx")
-   (set_attr "enabled"      "*,*,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,vx,vxe")
+   (set_attr "enabled"      "*,*,<DF>,<SF>")])
 
 ; msxbr, msdbr, msebr, msxb, msdb, mseb
 (define_insn "fms<mode>4"
-  [(set (match_operand:DSF                   0 "register_operand"     "=f,f,v")
-	(fma:DSF (match_operand:DSF          1 "nonimmediate_operand" "%f,f,v")
-		 (match_operand:DSF          2 "nonimmediate_operand"  "f,R,v")
-		 (neg:DSF (match_operand:DSF 3 "register_operand"      "0,0,v"))))]
+  [(set (match_operand:DSF                   0 "register_operand"     "=f,f,v,v")
+	(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"
   "@
    ms<xde>br\t%0,%1,%2
    ms<xde>b\t%0,%1,%2
-   wfmsdb\t%v0,%v1,%v2,%v3"
-  [(set_attr "op_type"      "RRE,RXE,VRR")
+   wfmsdb\t%v0,%v1,%v2,%v3
+   wfmssb\t%v0,%v1,%v2,%v3"
+  [(set_attr "op_type"      "RRE,RXE,VRR,VRR")
    (set_attr "type"         "fmadd<mode>")
-   (set_attr "cpu_facility" "*,*,vx")
-   (set_attr "enabled"      "*,*,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,vx,vxe")
+   (set_attr "enabled"      "*,*,<DF>,<SF>")])
 
 ;;
 ;;- Divide and modulo instructions.
@@ -7212,19 +7226,20 @@
 
 ; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr
 (define_insn "div<mode>3"
-  [(set (match_operand:FP         0 "register_operand" "=f,f,f,v")
-        (div:FP (match_operand:FP 1 "register_operand"  "f,0,0,v")
-		(match_operand:FP 2 "general_operand"   "f,f,R,v")))]
+  [(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")))]
   "TARGET_HARD_FLOAT"
   "@
    d<xde>tr\t%0,%1,%2
    d<xde>br\t%0,%2
    d<xde>b\t%0,%2
-   wfddb\t%v0,%v1,%v2"
-  [(set_attr "op_type"      "RRF,RRE,RXE,VRR")
+   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 "cpu_facility" "*,*,*,vx")
-   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DFDI>")])
+   (set_attr "cpu_facility" "*,*,*,vx,vxe")
+   (set_attr "enabled"      "<nBFP>,<nDFP>,<DSF>,<DF>,<SF>")])
 
 
 ;;
@@ -8423,11 +8438,10 @@
 
 (define_expand "neg<mode>2"
   [(parallel
-    [(set (match_operand:BFP 0 "register_operand" "=f")
-          (neg:BFP (match_operand:BFP 1 "register_operand" "f")))
+    [(set (match_operand:BFP          0 "register_operand")
+          (neg:BFP (match_operand:BFP 1 "register_operand")))
      (clobber (reg:CC CC_REGNUM))])]
-  "TARGET_HARD_FLOAT"
-  "")
+  "TARGET_HARD_FLOAT")
 
 ; lcxbr, lcdbr, lcebr
 (define_insn "*neg<mode>2_cc"
@@ -8463,18 +8477,20 @@
 
 ; lcxbr, lcdbr, lcebr
 ; FIXME: wflcdb does not clobber cc
+; FIXME: Does wflcdb ever match here?
 (define_insn "*neg<mode>2"
-  [(set (match_operand:BFP          0 "register_operand" "=f,v")
-        (neg:BFP (match_operand:BFP 1 "register_operand"  "f,v")))
+  [(set (match_operand:BFP          0 "register_operand" "=f,v,v")
+        (neg:BFP (match_operand:BFP 1 "register_operand"  "f,v,v")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_HARD_FLOAT"
   "@
    lc<xde>br\t%0,%1
-   wflcdb\t%0,%1"
-  [(set_attr "op_type"      "RRE,VRR")
-   (set_attr "cpu_facility" "*,vx")
-   (set_attr "type"         "fsimp<mode>,*")
-   (set_attr "enabled"      "*,<DFDI>")])
+   wflcdb\t%0,%1
+   wflcsb\t%0,%1"
+  [(set_attr "op_type"      "RRE,VRR,VRR")
+   (set_attr "cpu_facility" "*,vx,vxe")
+   (set_attr "type"         "fsimp<mode>,*,*")
+   (set_attr "enabled"      "*,<DF>,<SF>")])
 
 
 ;;
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index 6a726a3..7535b9d 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -26,16 +26,16 @@
   [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF
    V2SF V4SF V1DF V2DF V1TF V1TI TI])
 
-; All vector modes directly supported by the hardware having full vector reg size
+; 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 V2DF])
-(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF])
+(define_mode_iterator V_HW  [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
+(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
 
 (define_mode_iterator V_HW_64 [V2DI V2DF])
 
 ; Including TI for instructions that support it (va, vn, ...)
-(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI])
+(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")])
 
 ; All full size integer vector modes supported in a vector register + TImode
 (define_mode_iterator VIT_HW    [V16QI V8HI V4SI V2DI V1TI TI])
@@ -51,6 +51,15 @@
 (define_mode_iterator VI  [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI])
 (define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI])
 
+(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE")
+			   V1DF V2DF
+			   (V1TF "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 V_8   [V1QI])
 (define_mode_iterator V_16  [V2QI  V1HI])
 (define_mode_iterator V_32  [V4QI  V2HI V1SI V1SF])
@@ -59,26 +68,30 @@
 
 (define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF])
 
-; A blank for vector modes and a * for TImode.  This is used to hide
-; the TImode expander name in case it is defined already.  See addti3
-; for an example.
-(define_mode_attr ti* [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "")
-		       (V1HI "") (V2HI "") (V4HI "") (V8HI "")
-		       (V1SI "") (V2SI "") (V4SI "")
-		       (V1DI "") (V2DI "")
-		       (V1TI "*") (TI "*")])
+; Empty string for all but TImode.  This is used to hide the TImode
+; expander name in case it is defined already.  See addti3 for an
+; example.
+(define_mode_attr ti* [(V1QI "")  (V2QI "") (V4QI "") (V8QI "") (V16QI "")
+		       (V1HI "")  (V2HI "") (V4HI "") (V8HI "")
+		       (V1SI "")  (V2SI "") (V4SI "")
+		       (V1DI "")  (V2DI "")
+		       (V1TI "")  (TI "*")
+		       (V1SF "")  (V2SF "") (V4SF "")
+		       (V1DF "")  (V2DF "")
+		       (V1TF "")  (TF "")])
 
 ; 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")
 			  (V1SI "SI") (V2SI "SI") (V4SI "SI")
 			  (V1DI "DI") (V2DI "DI")
-			  (V1TI "TI")
+			  (V1TI "TI") (TI "TI")
 			  (V1SF "SF") (V2SF "SF") (V4SF "SF")
 			  (V1DF "DF") (V2DF "DF")
-			  (V1TF "TF")])
+			  (V1TF "TF") (TF "TF")])
 
-; The instruction suffix
+; The instruction suffix for integer instructions and instructions
+; which do not care about whether it is floating point or integer.
 (define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b")
 			(V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h")
 			(V1SI "f") (V2SI "f") (V4SI "f")
@@ -105,6 +118,13 @@
 			    (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI")
 			    (V1DF "V1DI") (V2DF "V2DI")
 			    (V1TF "V1TI")])
+(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v")
+		      (DF "w") (V1DF "w") (V2DF "v")
+		      (TF "w") (V1TF "w")])
+
+(define_mode_attr sdx [(SF "s") (V1SF "s") (V2SF "s") (V4SF "s")
+		       (DF "d") (V1DF "d") (V2DF "d")
+		       (TF "x") (V1TF "x")])
 
 ; Vector with doubled element size.
 (define_mode_attr vec_double [(V1QI "V1HI") (V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI")
@@ -1029,92 +1049,139 @@
 ;; Vector floating point arithmetic instructions
 ;;
 
-(define_insn "addv2df3"
-  [(set (match_operand:V2DF            0 "register_operand" "=v")
-	(plus:V2DF (match_operand:V2DF 1 "register_operand" "%v")
-		   (match_operand:V2DF 2 "register_operand"  "v")))]
+; vfasb, vfadb, wfasb, wfadb, wfaxb
+(define_insn "add<mode>3"
+  [(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")))]
   "TARGET_VX"
-  "vfadb\t%v0,%v1,%v2"
+  "<vw>fa<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "subv2df3"
-  [(set (match_operand:V2DF             0 "register_operand" "=v")
-	(minus:V2DF (match_operand:V2DF 1 "register_operand" "%v")
-		    (match_operand:V2DF 2 "register_operand"  "v")))]
+; vfssb, vfsdb, wfssb, wfsdb, wfsxb
+(define_insn "sub<mode>3"
+  [(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")))]
   "TARGET_VX"
-  "vfsdb\t%v0,%v1,%v2"
+  "<vw>fs<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "mulv2df3"
-  [(set (match_operand:V2DF            0 "register_operand" "=v")
-	(mult:V2DF (match_operand:V2DF 1 "register_operand" "%v")
-		   (match_operand:V2DF 2 "register_operand"  "v")))]
+; vfmsb, vfmdb, wfmsb, wfmdb, wfmxb
+(define_insn "mul<mode>3"
+  [(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")))]
   "TARGET_VX"
-  "vfmdb\t%v0,%v1,%v2"
+  "<vw>fm<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "divv2df3"
-  [(set (match_operand:V2DF           0 "register_operand" "=v")
-	(div:V2DF (match_operand:V2DF 1 "register_operand"  "v")
-		  (match_operand:V2DF 2 "register_operand"  "v")))]
+; vfdsb, vfddb, wfdsb, wfddb, wfdxb
+(define_insn "div<mode>3"
+  [(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")))]
   "TARGET_VX"
-  "vfddb\t%v0,%v1,%v2"
+  "<vw>fd<sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "sqrtv2df2"
-  [(set (match_operand:V2DF            0 "register_operand" "=v")
-	(sqrt:V2DF (match_operand:V2DF 1 "register_operand"  "v")))]
+; vfsqsb, vfsqdb, wfsqsb, wfsqdb, wfsqxb
+(define_insn "sqrt<mode>2"
+  [(set (match_operand:VF_HW           0 "register_operand" "=v")
+	(sqrt:VF_HW (match_operand:VF_HW 1 "register_operand"  "v")))]
   "TARGET_VX"
-  "vfsqdb\t%v0,%v1"
+  "<vw>fsq<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "fmav2df4"
-  [(set (match_operand:V2DF           0 "register_operand" "=v")
-	(fma:V2DF (match_operand:V2DF 1 "register_operand" "%v")
-		  (match_operand:V2DF 2 "register_operand"  "v")
-		  (match_operand:V2DF 3 "register_operand"  "v")))]
+; 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"
-  "vfmadb\t%v0,%v1,%v2,%v3"
+  "<vw>fma<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "fmsv2df4"
-  [(set (match_operand:V2DF                     0 "register_operand" "=v")
-	(fma:V2DF (match_operand:V2DF           1 "register_operand" "%v")
-		  (match_operand:V2DF           2 "register_operand"  "v")
-		  (neg:V2DF (match_operand:V2DF 3 "register_operand"  "v"))))]
+; vfmssb, vfmsdb, wfmssb, wfmsdb, wfmsxb
+(define_insn "fms<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")
+		 (neg:VF_HW (match_operand:VF_HW 3 "register_operand"  "v"))))]
   "TARGET_VX"
-  "vfmsdb\t%v0,%v1,%v2,%v3"
+  "<vw>fms<sdx>b\t%v0,%v1,%v2,%v3"
+  [(set_attr "op_type" "VRR")])
+
+; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb
+(define_insn "neg_fma<mode>4"
+  [(set (match_operand:VF_HW             0 "register_operand" "=v")
+	(neg:VF_HW
+	 (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"
+  "<vw>fnma<sdx>b\t%v0,%v1,%v2,%v3"
+  [(set_attr "op_type" "VRR")])
+
+; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb
+(define_insn "neg_fms<mode>4"
+  [(set (match_operand:VF_HW                      0 "register_operand" "=v")
+	(neg:VF_HW
+	 (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"
+  "<vw>fnms<sdx>b\t%v0,%v1,%v2,%v3"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "negv2df2"
-  [(set (match_operand:V2DF           0 "register_operand" "=v")
-	(neg:V2DF (match_operand:V2DF 1 "register_operand"  "v")))]
+; vflcsb, vflcdb, wflcsb, wflcdb, wflcxb
+(define_insn "neg<mode>2"
+  [(set (match_operand:VFT          0 "register_operand" "=v")
+	(neg:VFT (match_operand:VFT 1 "register_operand"  "v")))]
   "TARGET_VX"
-  "vflcdb\t%v0,%v1"
+  "<vw>flc<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "absv2df2"
-  [(set (match_operand:V2DF           0 "register_operand" "=v")
-	(abs:V2DF (match_operand:V2DF 1 "register_operand"  "v")))]
+; vflpsb, vflpdb, wflpsb, wflpdb, wflpxb
+(define_insn "abs<mode>2"
+  [(set (match_operand:VFT          0 "register_operand" "=v")
+	(abs:VFT (match_operand:VFT 1 "register_operand"  "v")))]
   "TARGET_VX"
-  "vflpdb\t%v0,%v1"
+  "<vw>flp<sdx>b\t%v0,%v1"
   [(set_attr "op_type" "VRR")])
 
-(define_insn "*negabsv2df2"
-  [(set (match_operand:V2DF                     0 "register_operand" "=v")
-	(neg:V2DF (abs:V2DF (match_operand:V2DF 1 "register_operand"  "v"))))]
+; vflnsb, vflndb, wflnsb, wflndb, wflnxb
+(define_insn "negabs<mode>2"
+  [(set (match_operand:VFT                   0 "register_operand" "=v")
+	(neg:VFT (abs:VFT (match_operand:VFT 1 "register_operand"  "v"))))]
   "TARGET_VX"
-  "vflndb\t%v0,%v1"
+  "<vw>fln<sdx>b\t%v0,%v1"
+  [(set_attr "op_type" "VRR")])
+
+(define_expand "smax<mode>3"
+  [(set (match_operand:VF_HW             0 "register_operand")
+	(smax:VF_HW (match_operand:VF_HW 1 "register_operand")
+		    (match_operand:VF_HW 2 "register_operand")))]
+  "TARGET_VX")
+
+; vfmaxsb, vfmaxdb, wfmaxsb, wfmaxdb, wfmaxxb
+(define_insn "*smax<mode>3_vxe"
+  [(set (match_operand:VF_HW             0 "register_operand" "=v")
+	(smax:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
+		    (match_operand:VF_HW 2 "register_operand"  "v")))]
+  "TARGET_VXE"
+  "<vw>fmax<sdx>b\t%v0,%v1,%v2,4"
   [(set_attr "op_type" "VRR")])
 
 ; Emulate with compare + select
-(define_insn_and_split "smaxv2df3"
+(define_insn_and_split "*smaxv2df3_vx"
   [(set (match_operand:V2DF            0 "register_operand" "=v")
 	(smax:V2DF (match_operand:V2DF 1 "register_operand" "%v")
 		   (match_operand:V2DF 2 "register_operand"  "v")))]
-  "TARGET_VX"
+  "TARGET_VX && !TARGET_VXE"
   "#"
-  ""
+  "&& 1"
   [(set (match_dup 3)
 	(gt:V2DI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
@@ -1127,14 +1194,29 @@
   operands[4] = CONST0_RTX (V2DImode);
 })
 
+(define_expand "smin<mode>3"
+  [(set (match_operand:VF_HW             0 "register_operand")
+	(smin:VF_HW (match_operand:VF_HW 1 "register_operand")
+		    (match_operand:VF_HW 2 "register_operand")))]
+  "TARGET_VX")
+
+; vfminsb, vfmindb, wfminsb, wfmindb, wfminxb
+(define_insn "*smin<mode>3_vxe"
+  [(set (match_operand:VF_HW             0 "register_operand" "=v")
+	(smin:VF_HW (match_operand:VF_HW 1 "register_operand" "%v")
+		    (match_operand:VF_HW 2 "register_operand"  "v")))]
+  "TARGET_VXE"
+  "<vw>fmin<sdx>b\t%v0,%v1,%v2,4"
+  [(set_attr "op_type" "VRR")])
+
 ; Emulate with compare + select
-(define_insn_and_split "sminv2df3"
+(define_insn_and_split "*sminv2df3_vx"
   [(set (match_operand:V2DF            0 "register_operand" "=v")
 	(smin:V2DF (match_operand:V2DF 1 "register_operand" "%v")
 		   (match_operand:V2DF 2 "register_operand"  "v")))]
-  "TARGET_VX"
+  "TARGET_VX && !TARGET_VXE"
   "#"
-  ""
+  "&& 1"
   [(set (match_dup 3)
 	(gt:V2DI (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
@@ -1166,65 +1248,66 @@
 ;;
 
 ; EQ, GT, GE
-(define_insn "*vec_cmp<VFCMP_HW_OP:code>v2df_nocc"
-  [(set (match_operand:V2DI                   0 "register_operand" "=v")
-	(VFCMP_HW_OP:V2DI (match_operand:V2DF 1 "register_operand"  "v")
-			  (match_operand:V2DF 2 "register_operand"  "v")))]
+; vfcesb, vfcedb, wfcexb, vfchsb, vfchdb, wfchxb, vfchesb, vfchedb, wfchexb
+(define_insn "*vec_cmp<VFCMP_HW_OP:code><mode>_nocc"
+  [(set (match_operand:<tointvec>                  0 "register_operand" "=v")
+	(VFCMP_HW_OP:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+			     (match_operand:VFT 2 "register_operand"  "v")))]
    "TARGET_VX"
-   "vfc<VFCMP_HW_OP:asm_fcmp_op>db\t%v0,%v1,%v2"
+   "<vw>fc<VFCMP_HW_OP:asm_fcmp_op><sdx>b\t%v0,%v1,%v2"
   [(set_attr "op_type" "VRR")])
 
 ; Expanders for not directly supported comparisons
 
 ; UNEQ a u== b -> !(a > b | b > a)
-(define_expand "vec_cmpuneqv2df"
-  [(set (match_operand:V2DI          0 "register_operand" "=v")
-	(gt:V2DI (match_operand:V2DF 1 "register_operand"  "v")
-		 (match_operand:V2DF 2 "register_operand"  "v")))
+(define_expand "vec_cmpuneq<mode>"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+		    (match_operand:VFT 2 "register_operand"  "v")))
    (set (match_dup 3)
-	(gt:V2DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))
-   (set (match_dup 0) (not:V2DI (match_dup 0)))]
+	(gt:<tointvec> (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
+   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
   "TARGET_VX"
 {
-  operands[3] = gen_reg_rtx (V2DImode);
+  operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
 ; LTGT a <> b -> a > b | b > a
-(define_expand "vec_cmpltgtv2df"
-  [(set (match_operand:V2DI          0 "register_operand" "=v")
-	(gt:V2DI (match_operand:V2DF 1 "register_operand"  "v")
-		 (match_operand:V2DF 2 "register_operand"  "v")))
-   (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))]
+(define_expand "vec_cmpltgt<mode>"
+  [(set (match_operand:<tointvec>         0 "register_operand" "=v")
+	(gt:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+		    (match_operand:VFT 2 "register_operand"  "v")))
+   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
   "TARGET_VX"
 {
-  operands[3] = gen_reg_rtx (V2DImode);
+  operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
 ; ORDERED (a, b): a >= b | b > a
-(define_expand "vec_orderedv2df"
-  [(set (match_operand:V2DI          0 "register_operand" "=v")
-	(ge:V2DI (match_operand:V2DF 1 "register_operand"  "v")
-		 (match_operand:V2DF 2 "register_operand"  "v")))
-   (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))]
+(define_expand "vec_ordered<mode>"
+  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
+	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+		 (match_operand:VFT 2 "register_operand"  "v")))
+   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))]
   "TARGET_VX"
 {
-  operands[3] = gen_reg_rtx (V2DImode);
+  operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
 ; UNORDERED (a, b): !ORDERED (a, b)
-(define_expand "vec_unorderedv2df"
-  [(set (match_operand:V2DI          0 "register_operand" "=v")
-	(ge:V2DI (match_operand:V2DF 1 "register_operand"  "v")
-		 (match_operand:V2DF 2 "register_operand"  "v")))
-   (set (match_dup 3) (gt:V2DI (match_dup 2) (match_dup 1)))
-   (set (match_dup 0) (ior:V2DI (match_dup 0) (match_dup 3)))
-   (set (match_dup 0) (not:V2DI (match_dup 0)))]
+(define_expand "vec_unordered<mode>"
+  [(set (match_operand:<tointvec>          0 "register_operand" "=v")
+	(ge:<tointvec> (match_operand:VFT 1 "register_operand"  "v")
+		 (match_operand:VFT 2 "register_operand"  "v")))
+   (set (match_dup 3) (gt:<tointvec> (match_dup 2) (match_dup 1)))
+   (set (match_dup 0) (ior:<tointvec> (match_dup 0) (match_dup 3)))
+   (set (match_dup 0) (not:<tointvec> (match_dup 0)))]
   "TARGET_VX"
 {
-  operands[3] = gen_reg_rtx (V2DImode);
+  operands[3] = gen_reg_rtx (<tointvec>mode);
 })
 
 (define_insn "*vec_load_pair<mode>"
@@ -1563,6 +1646,28 @@
   "vupllf\t%0,%1"
   [(set_attr "op_type" "VRR")])
 
+;; vector load lengthened
+
+; vflls
+(define_insn "*vec_extendv4sf"
+  [(set (match_operand:V2DF 0 "register_operand" "=v")
+	(float_extend:V2DF
+	 (vec_select:V2SF
+	  (match_operand:V4SF 1 "register_operand" "v")
+	  (parallel [(const_int 0) (const_int 2)]))))]
+  "TARGET_VX"
+  "vldeb\t%v0,%v1"
+  [(set_attr "op_type" "VRR")])
+
+(define_insn "*vec_extendv2df"
+  [(set (match_operand:V1TF 0 "register_operand" "=v")
+	(float_extend:V1TF
+	 (vec_select:V1DF
+	  (match_operand:V2DF 1 "register_operand" "v")
+	  (parallel [(const_int 0)]))))]
+  "TARGET_VXE"
+  "wflld\t%v0,%v1"
+  [(set_attr "op_type" "VRR")])
 
 ; reduc_smin
 ; reduc_smax
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9247f53..b843b78 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
+	* gcc.target/s390/vxe/negfma-1.c: New test.
+
+2017-03-24  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
 	* gcc.target/s390/arch12/aghsghmgh-1.c: New test.
 	* gcc.target/s390/arch12/mul-1.c: New test.
 	* gcc.target/s390/arch12/mul-2.c: New test.
diff --git a/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c b/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c
new file mode 100644
index 0000000..4c976b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch -march=arch12" } */
+
+typedef float       v4sf __attribute__((vector_size(16)));
+typedef double      v2df __attribute__((vector_size(16)));
+typedef long double v1tf __attribute__((vector_size(16)));
+
+v4sf
+neg_vfnmasb (v4sf a, v4sf b, v4sf c)
+{
+  return -(a * b + c);
+}
+/* { dg-final { scan-assembler-times "vfnmasb\t%v24,%v24,%v26,%v28" 1 } } */
+
+v2df
+neg_vfnmadb (v2df a, v2df b, v2df c)
+{
+  return -(a * b + c);
+}
+/* { dg-final { scan-assembler-times "vfnmadb\t%v24,%v24,%v26,%v28" 1 } } */
+
+v1tf
+neg_wfnmaxb (v1tf a, v1tf b, v1tf c)
+{
+  return -(a * b + c);
+}
+/* { dg-final { scan-assembler-times "wfnmaxb\t%v24,%v24,%v26,%v28" 1 } } */
+
+
+v4sf
+neg_vfnmssb (v4sf a, v4sf b, v4sf c)
+{
+  return -(a * b - c);
+}
+/* { dg-final { scan-assembler-times "vfnmssb\t%v24,%v24,%v26,%v28" 1 } } */
+
+v2df
+neg_vfnmsdb (v2df a, v2df b, v2df c)
+{
+  return -(a * b - c);
+}
+/* { dg-final { scan-assembler-times "vfnmsdb\t%v24,%v24,%v26,%v28" 1 } } */
+
+v1tf
+neg_wfnmsxb (v1tf a, v1tf b, v1tf c)
+{
+  return -(a * b - c);
+}
+/* { dg-final { scan-assembler-times "wfnmsxb\t%v24,%v24,%v26,%v28" 1 } } */
-- 
2.9.1



More information about the Gcc-patches mailing list