S/390: arch12: Support new vector floating point modes.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 24 Mar 2017 14:03:24 +0000 (14:03 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 24 Mar 2017 14:03:24 +0000 (14:03 +0000)
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.

From-SVN: r246458

gcc/ChangeLog
gcc/config/s390/s390-builtins.def
gcc/config/s390/s390.c
gcc/config/s390/s390.md
gcc/config/s390/vector.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/vxe/negfma-1.c [new file with mode: 0644]

index ca127058bd53c93633ad5e8a9c963dcc92db0a05..7083cd982edfb4da5b2ec1a3bd1c0899608c8639 100644 (file)
@@ -1,3 +1,37 @@
+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")
index 27cb6a860003787d296ee8fd0180d38db5f26207..bb2d743dd55d9985bf3a484a77ea1d8df64f86f7 100644 (file)
@@ -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)
index e8003233165387c37b0a7a0ad760130581b3ca03..1d26979cdea05072190441d7da34d8ed00567ff8 100644 (file)
@@ -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;
 
index 93a0bc6767ed0df8fdf0b607ab82dc60f2990e44..7e9add7c340a1f553971bb9354e7f4cfc8a7b65e 100644 (file)
 (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.
  })
 
 
-; 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
 
 ; 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")))]
 ; 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"
 ; 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)))]
 
 ; 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.
 
 ; 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>")])
 
 
 ;;
 
 (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"
 
 ; 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>")])
 
 
 ;;
index 6a726a30e30fd95180dbb34c45fe51ca468b65f5..7535b9ddb1707c805dd5ee39ddf37e568e3ecf2f 100644 (file)
   [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])
 (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])
 
 (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")
                            (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")
 ;; 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)
   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)
 ;;
 
 ; 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>"
   "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
index 914b4b53fd817e54c76f2a5e777acf72ebfacfe7..bd0a9b01db387a490acbe9c3a8e61bf79f45fa92 100644 (file)
@@ -1,3 +1,7 @@
+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.
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 (file)
index 0000000..4c976b0
--- /dev/null
@@ -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 } } */