S/390: arch12: Support new vector floating point modes.

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
This commit is contained in:
Andreas Krebbel 2017-03-24 14:03:24 +00:00 committed by Andreas Krebbel
parent 7d2fd07577
commit 2de2b3f93b
7 changed files with 390 additions and 173 deletions

View 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")

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

View 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;

View File

@ -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>")])
;;

View File

@ -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")])
(define_insn "negv2df2"
[(set (match_operand:V2DF 0 "register_operand" "=v")
(neg:V2DF (match_operand:V2DF 1 "register_operand" "v")))]
"TARGET_VX"
"vflcdb\t%v0,%v1"
; 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")])
(define_insn "absv2df2"
[(set (match_operand:V2DF 0 "register_operand" "=v")
(abs:V2DF (match_operand:V2DF 1 "register_operand" "v")))]
"TARGET_VX"
"vflpdb\t%v0,%v1"
; 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 "*negabsv2df2"
[(set (match_operand:V2DF 0 "register_operand" "=v")
(neg:V2DF (abs: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"
"vflndb\t%v0,%v1"
"<vw>flc<sdx>b\t%v0,%v1"
[(set_attr "op_type" "VRR")])
; 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"
"<vw>flp<sdx>b\t%v0,%v1"
[(set_attr "op_type" "VRR")])
; 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"
"<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

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

View File

@ -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 } } */