@@ -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
@@ -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)
@@ -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;
@@ -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>")])
;;
@@ -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
@@ -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.
new file mode 100644
@@ -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 } } */