+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")
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)
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)
{
/* 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
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:
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;
(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>")])
;;
[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
+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.
--- /dev/null
+/* { 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 } } */