From 2de2b3f93b964081665a990a8b5645709302d834 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Fri, 24 Mar 2017 14:03:24 +0000 Subject: [PATCH] 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 * 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_ccs", "add3", "sub3", "mul3") ("fma4", "fms4", "div3", "*neg2"): 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_cmpv2df_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 ... ("add3", "sub3", "mul3", "div3") ("sqrt2", "fma4", "fms4", "neg2") ("abs2", "negabs2", "smax3") ("smin3", "*vec_cmp_nocc") ("vec_cmpuneq", "vec_cmpltgt", "vec_ordered") ("vec_unordered"): ... these. ("neg_fma4", "neg_fms4", "*smax3_vxe") ("*smin3_vxe", "*sminv2df3_vx", "*vec_extendv4sf") ("*vec_extendv2df"): New insn definitions. gcc/testsuite/ChangeLog: 2017-03-24 Andreas Krebbel * gcc.target/s390/vxe/negfma-1.c: New test. From-SVN: r246458 --- gcc/ChangeLog | 34 ++ gcc/config/s390/s390-builtins.def | 2 +- gcc/config/s390/s390.c | 13 +- gcc/config/s390/s390.md | 144 +++++---- gcc/config/s390/vector.md | 313 +++++++++++++------ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.target/s390/vxe/negfma-1.c | 49 +++ 7 files changed, 388 insertions(+), 171 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/vxe/negfma-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ca127058bd5..7083cd982ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2017-03-24 Andreas Krebbel + + * 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_ccs", "add3", "sub3", "mul3") + ("fma4", "fms4", "div3", "*neg2"): 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_cmpv2df_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 ... + + ("add3", "sub3", "mul3", "div3") + ("sqrt2", "fma4", "fms4", "neg2") + ("abs2", "negabs2", "smax3") + ("smin3", "*vec_cmp_nocc") + ("vec_cmpuneq", "vec_cmpltgt", "vec_ordered") + ("vec_unordered"): ... these. + + ("neg_fma4", "neg_fms4", "*smax3_vxe") + ("*smin3_vxe", "*sminv2df3_vx", "*vec_extendv4sf") + ("*vec_extendv2df"): New insn definitions. + 2017-03-24 Andreas Krebbel * config/s390/s390.md ("*adddi3_sign", "*subdi3_sign", "mulditi3") diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def index 27cb6a86000..bb2d743dd55 100644 --- a/gcc/config/s390/s390-builtins.def +++ b/gcc/config/s390/s390-builtins.def @@ -2496,7 +2496,7 @@ B_DEF (s390_vec_ctsl, vec_ctsl, 0, B_DEF (s390_vec_ctul, vec_ctul, 0, B_VX, O2_U3, BT_FN_UV2DI_V2DF_INT) /* vclgdb */ B_DEF (s390_vcgdb, vec_df_to_di_s64, 0, B_VX, O2_U3, BT_FN_V2DI_V2DF_INT) /* vcgdb */ B_DEF (s390_vclgdb, vec_df_to_di_u64, 0, B_VX, O2_U3, BT_FN_UV2DI_V2DF_INT) /* vclgdb */ -B_DEF (s390_vfidb, vfidb, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DF_V2DF_UCHAR_UCHAR) +B_DEF (s390_vfidb, vfiv2df, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DF_V2DF_UCHAR_UCHAR) B_DEF (s390_vec_ld2f, vec_ld2f, 0, B_VX, 0, BT_FN_V2DF_FLTCONSTPTR) /* vldeb */ B_DEF (s390_vec_st2f, vec_st2f, 0, B_VX, 0, BT_FN_VOID_V2DF_FLTPTR) /* vledb */ B_DEF (s390_vfmadb, fmav2df4, 0, B_VX, 0, BT_FN_V2DF_V2DF_V2DF_V2DF) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index e8003233165..1d26979cdea 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -6201,7 +6201,7 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond, bool neg_p = false, swap_p = false; rtx tmp; - if (GET_MODE (cmp_op1) == V2DFmode) + if (GET_MODE_CLASS (GET_MODE (cmp_op1)) == MODE_VECTOR_FLOAT) { switch (cond) { @@ -6447,7 +6447,8 @@ s390_expand_vcond (rtx target, rtx then, rtx els, /* We always use an integral type vector to hold the comparison result. */ - result_mode = cmp_mode == V2DFmode ? V2DImode : cmp_mode; + result_mode = mode_for_vector (int_mode_for_mode (GET_MODE_INNER (cmp_mode)), + GET_MODE_NUNITS (cmp_mode)); result_target = gen_reg_rtx (result_mode); /* We allow vector immediates as comparison operands that @@ -10112,6 +10113,7 @@ s390_hard_regno_mode_ok (unsigned int regno, machine_mode mode) return ((GET_MODE_CLASS (mode) == MODE_INT && s390_class_max_nregs (VEC_REGS, mode) == 1) || mode == DFmode + || (TARGET_VXE && mode == SFmode) || s390_vector_mode_supported_p (mode)); break; case FP_REGS: @@ -10256,6 +10258,13 @@ s390_cannot_change_mode_class (machine_mode from_mode, machine_mode small_mode; machine_mode big_mode; + /* V1TF and TF have different representations in vector + registers. */ + if (reg_classes_intersect_p (VEC_REGS, rclass) + && ((from_mode == V1TFmode && to_mode == TFmode) + || (from_mode == TFmode && to_mode == V1TFmode))) + return 1; + if (GET_MODE_SIZE (from_mode) == GET_MODE_SIZE (to_mode)) return 0; diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 93a0bc6767e..7e9add7c340 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -674,6 +674,12 @@ (define_mode_attr DFDI [(TF "0") (DF "*") (SF "0") (TD "0") (DD "0") (DD "0") (TI "0") (DI "*") (SI "0")]) +(define_mode_attr DF [(TF "0") (DF "*") (SF "0") + (TD "0") (DD "0") (DD "0") + (TI "0") (DI "0") (SI "0")]) +(define_mode_attr SF [(TF "0") (DF "0") (SF "*") + (TD "0") (DD "0") (DD "0") + (TI "0") (DI "0") (SI "0")]) ;; This attribute is used in the operand constraint list ;; for instructions dealing with the sign bit of 32 or 64bit fp values. @@ -1325,20 +1331,21 @@ }) -; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcdb +; VX: TFmode in FPR pairs: use cxbr instead of wfcxb +; cxtr, cdtr, cxbr, cdbr, cebr, cdb, ceb, wfcsb, wfcdb (define_insn "*cmp_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" "@ cr\t%0,%1 cb\t%0,%1 - wfcdb\t%0,%1" - [(set_attr "op_type" "RRE,RXE,VRR") - (set_attr "cpu_facility" "*,*,vx") - (set_attr "enabled" "*,,")]) - + 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" "*,,,")]) ; 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 "add3" - [(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" "@ atr\t%0,%1,%2 abr\t%0,%2 ab\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") - (set_attr "cpu_facility" "*,*,*,vx") - (set_attr "enabled" ",,,")]) + (set_attr "cpu_facility" "*,*,*,vx,vxe") + (set_attr "enabled" ",,,,")]) ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr (define_insn "*add3_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 "sub3" - [(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" "@ str\t%0,%1,%2 sbr\t%0,%2 sb\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") - (set_attr "cpu_facility" "*,*,*,vx") - (set_attr "enabled" ",,,")]) + (set_attr "cpu_facility" "*,*,*,vx,vxe") + (set_attr "enabled" ",,,,")]) ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr (define_insn "*sub3_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 "mul3" - [(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" "@ mtr\t%0,%1,%2 mbr\t%0,%2 mb\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") - (set_attr "cpu_facility" "*,*,*,vx") - (set_attr "enabled" ",,,")]) + (set_attr "cpu_facility" "*,*,*,vx,vxe") + (set_attr "enabled" ",,,,")]) ; madbr, maebr, maxb, madb, maeb (define_insn "fma4" - [(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" "@ mabr\t%0,%1,%2 mab\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") - (set_attr "cpu_facility" "*,*,vx") - (set_attr "enabled" "*,*,")]) + (set_attr "cpu_facility" "*,*,vx,vxe") + (set_attr "enabled" "*,*,,")]) ; msxbr, msdbr, msebr, msxb, msdb, mseb (define_insn "fms4" - [(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" "@ msbr\t%0,%1,%2 msb\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") - (set_attr "cpu_facility" "*,*,vx") - (set_attr "enabled" "*,*,")]) + (set_attr "cpu_facility" "*,*,vx,vxe") + (set_attr "enabled" "*,*,,")]) ;; ;;- Divide and modulo instructions. @@ -7212,19 +7226,20 @@ ; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr (define_insn "div3" - [(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" "@ dtr\t%0,%1,%2 dbr\t%0,%2 db\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") - (set_attr "cpu_facility" "*,*,*,vx") - (set_attr "enabled" ",,,")]) + (set_attr "cpu_facility" "*,*,*,vx,vxe") + (set_attr "enabled" ",,,,")]) ;; @@ -8423,11 +8438,10 @@ (define_expand "neg2" [(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 "*neg2_cc" @@ -8463,18 +8477,20 @@ ; lcxbr, lcdbr, lcebr ; FIXME: wflcdb does not clobber cc +; FIXME: Does wflcdb ever match here? (define_insn "*neg2" - [(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" "@ lcbr\t%0,%1 - wflcdb\t%0,%1" - [(set_attr "op_type" "RRE,VRR") - (set_attr "cpu_facility" "*,vx") - (set_attr "type" "fsimp,*") - (set_attr "enabled" "*,")]) + 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,*,*") + (set_attr "enabled" "*,,")]) ;; diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 6a726a30e30..7535b9ddb17 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -26,16 +26,16 @@ [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI V1SF V2SF V4SF V1DF V2DF V1TF V1TI TI]) -; All vector modes directly supported by the hardware having full vector reg size +; All modes directly supported by the hardware having full vector reg size ; V_HW2 is duplicate of V_HW for having two iterators expanding ; independently e.g. vcond -(define_mode_iterator V_HW [V16QI V8HI V4SI V2DI V2DF]) -(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF]) +(define_mode_iterator V_HW [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")]) +(define_mode_iterator V_HW2 [V16QI V8HI V4SI V2DI V2DF (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")]) (define_mode_iterator V_HW_64 [V2DI V2DF]) ; Including TI for instructions that support it (va, vn, ...) -(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI]) +(define_mode_iterator VT_HW [V16QI V8HI V4SI V2DI V2DF V1TI TI (V4SF "TARGET_VXE") (V1TF "TARGET_VXE")]) ; All full size integer vector modes supported in a vector register + TImode (define_mode_iterator VIT_HW [V16QI V8HI V4SI V2DI V1TI TI]) @@ -51,6 +51,15 @@ (define_mode_iterator VI [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI V1DI V2DI]) (define_mode_iterator VI_QHS [V1QI V2QI V4QI V8QI V16QI V1HI V2HI V4HI V8HI V1SI V2SI V4SI]) +(define_mode_iterator VFT [(V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE") + V1DF V2DF + (V1TF "TARGET_VXE")]) + +; FP vector modes directly supported by the HW. This does not include +; vector modes using only part of a vector register and should be used +; for instructions which might trigger IEEE exceptions. +(define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE")]) + (define_mode_iterator V_8 [V1QI]) (define_mode_iterator V_16 [V2QI V1HI]) (define_mode_iterator V_32 [V4QI V2HI V1SI V1SF]) @@ -59,26 +68,30 @@ (define_mode_iterator V_128_NOSINGLE [V16QI V8HI V4SI V4SF V2DI V2DF]) -; A blank for vector modes and a * for TImode. This is used to hide -; the TImode expander name in case it is defined already. See addti3 -; for an example. -(define_mode_attr ti* [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "") - (V1HI "") (V2HI "") (V4HI "") (V8HI "") - (V1SI "") (V2SI "") (V4SI "") - (V1DI "") (V2DI "") - (V1TI "*") (TI "*")]) +; Empty string for all but TImode. This is used to hide the TImode +; expander name in case it is defined already. See addti3 for an +; example. +(define_mode_attr ti* [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "") + (V1HI "") (V2HI "") (V4HI "") (V8HI "") + (V1SI "") (V2SI "") (V4SI "") + (V1DI "") (V2DI "") + (V1TI "") (TI "*") + (V1SF "") (V2SF "") (V4SF "") + (V1DF "") (V2DF "") + (V1TF "") (TF "")]) ; The element type of the vector. (define_mode_attr non_vec[(V1QI "QI") (V2QI "QI") (V4QI "QI") (V8QI "QI") (V16QI "QI") (V1HI "HI") (V2HI "HI") (V4HI "HI") (V8HI "HI") (V1SI "SI") (V2SI "SI") (V4SI "SI") (V1DI "DI") (V2DI "DI") - (V1TI "TI") + (V1TI "TI") (TI "TI") (V1SF "SF") (V2SF "SF") (V4SF "SF") (V1DF "DF") (V2DF "DF") - (V1TF "TF")]) + (V1TF "TF") (TF "TF")]) -; The instruction suffix +; The instruction suffix for integer instructions and instructions +; which do not care about whether it is floating point or integer. (define_mode_attr bhfgq[(V1QI "b") (V2QI "b") (V4QI "b") (V8QI "b") (V16QI "b") (V1HI "h") (V2HI "h") (V4HI "h") (V8HI "h") (V1SI "f") (V2SI "f") (V4SI "f") @@ -105,6 +118,13 @@ (V1SF "V1SI") (V2SF "V2SI") (V4SF "V4SI") (V1DF "V1DI") (V2DF "V2DI") (V1TF "V1TI")]) +(define_mode_attr vw [(SF "w") (V1SF "w") (V2SF "v") (V4SF "v") + (DF "w") (V1DF "w") (V2DF "v") + (TF "w") (V1TF "w")]) + +(define_mode_attr sdx [(SF "s") (V1SF "s") (V2SF "s") (V4SF "s") + (DF "d") (V1DF "d") (V2DF "d") + (TF "x") (V1TF "x")]) ; Vector with doubled element size. (define_mode_attr vec_double [(V1QI "V1HI") (V2QI "V1HI") (V4QI "V2HI") (V8QI "V4HI") (V16QI "V8HI") @@ -1029,92 +1049,139 @@ ;; Vector floating point arithmetic instructions ;; -(define_insn "addv2df3" - [(set (match_operand:V2DF 0 "register_operand" "=v") - (plus:V2DF (match_operand:V2DF 1 "register_operand" "%v") - (match_operand:V2DF 2 "register_operand" "v")))] +; vfasb, vfadb, wfasb, wfadb, wfaxb +(define_insn "add3" + [(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" + "fab\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 "sub3" + [(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" + "fsb\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 "mul3" + [(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" + "fmb\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 "div3" + [(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" + "fdb\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 "sqrt2" + [(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" + "fsqb\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 "fma4" + [(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" + "fmab\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 "fms4" + [(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" + "fmsb\t%v0,%v1,%v2,%v3" + [(set_attr "op_type" "VRR")]) + +; vfnmasb, vfnmadb, wfnmasb, wfnmadb, wfnmaxb +(define_insn "neg_fma4" + [(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" + "fnmab\t%v0,%v1,%v2,%v3" + [(set_attr "op_type" "VRR")]) + +; vfnmssb, vfnmsdb, wfnmssb, wfnmsdb, wfnmsxb +(define_insn "neg_fms4" + [(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" + "fnmsb\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 "neg2" + [(set (match_operand:VFT 0 "register_operand" "=v") + (neg:VFT (match_operand:VFT 1 "register_operand" "v")))] "TARGET_VX" - "vflcdb\t%v0,%v1" + "flcb\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 "abs2" + [(set (match_operand:VFT 0 "register_operand" "=v") + (abs:VFT (match_operand:VFT 1 "register_operand" "v")))] "TARGET_VX" - "vflpdb\t%v0,%v1" + "flpb\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 "negabs2" + [(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" + "flnb\t%v0,%v1" + [(set_attr "op_type" "VRR")]) + +(define_expand "smax3" + [(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 "*smax3_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" + "fmaxb\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 "smin3" + [(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 "*smin3_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" + "fminb\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_cmpv2df_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_nocc" + [(set (match_operand: 0 "register_operand" "=v") + (VFCMP_HW_OP: (match_operand:VFT 1 "register_operand" "v") + (match_operand:VFT 2 "register_operand" "v")))] "TARGET_VX" - "vfcdb\t%v0,%v1,%v2" + "fcb\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" + [(set (match_operand: 0 "register_operand" "=v") + (gt: (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: (match_dup 2) (match_dup 1))) + (set (match_dup 0) (ior: (match_dup 0) (match_dup 3))) + (set (match_dup 0) (not: (match_dup 0)))] "TARGET_VX" { - operands[3] = gen_reg_rtx (V2DImode); + operands[3] = gen_reg_rtx (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" + [(set (match_operand: 0 "register_operand" "=v") + (gt: (match_operand:VFT 1 "register_operand" "v") + (match_operand:VFT 2 "register_operand" "v"))) + (set (match_dup 3) (gt: (match_dup 2) (match_dup 1))) + (set (match_dup 0) (ior: (match_dup 0) (match_dup 3)))] "TARGET_VX" { - operands[3] = gen_reg_rtx (V2DImode); + operands[3] = gen_reg_rtx (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" + [(set (match_operand: 0 "register_operand" "=v") + (ge: (match_operand:VFT 1 "register_operand" "v") + (match_operand:VFT 2 "register_operand" "v"))) + (set (match_dup 3) (gt: (match_dup 2) (match_dup 1))) + (set (match_dup 0) (ior: (match_dup 0) (match_dup 3)))] "TARGET_VX" { - operands[3] = gen_reg_rtx (V2DImode); + operands[3] = gen_reg_rtx (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" + [(set (match_operand: 0 "register_operand" "=v") + (ge: (match_operand:VFT 1 "register_operand" "v") + (match_operand:VFT 2 "register_operand" "v"))) + (set (match_dup 3) (gt: (match_dup 2) (match_dup 1))) + (set (match_dup 0) (ior: (match_dup 0) (match_dup 3))) + (set (match_dup 0) (not: (match_dup 0)))] "TARGET_VX" { - operands[3] = gen_reg_rtx (V2DImode); + operands[3] = gen_reg_rtx (mode); }) (define_insn "*vec_load_pair" @@ -1563,6 +1646,28 @@ "vupllf\t%0,%1" [(set_attr "op_type" "VRR")]) +;; vector load lengthened + +; vflls +(define_insn "*vec_extendv4sf" + [(set (match_operand:V2DF 0 "register_operand" "=v") + (float_extend:V2DF + (vec_select:V2SF + (match_operand:V4SF 1 "register_operand" "v") + (parallel [(const_int 0) (const_int 2)]))))] + "TARGET_VX" + "vldeb\t%v0,%v1" + [(set_attr "op_type" "VRR")]) + +(define_insn "*vec_extendv2df" + [(set (match_operand:V1TF 0 "register_operand" "=v") + (float_extend:V1TF + (vec_select:V1DF + (match_operand:V2DF 1 "register_operand" "v") + (parallel [(const_int 0)]))))] + "TARGET_VXE" + "wflld\t%v0,%v1" + [(set_attr "op_type" "VRR")]) ; reduc_smin ; reduc_smax diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 914b4b53fd8..bd0a9b01db3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-03-24 Andreas Krebbel + + * gcc.target/s390/vxe/negfma-1.c: New test. + 2017-03-24 Andreas Krebbel * gcc.target/s390/arch12/aghsghmgh-1.c: New test. diff --git a/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c b/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c new file mode 100644 index 00000000000..4c976b02495 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vxe/negfma-1.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mzarch -march=arch12" } */ + +typedef float v4sf __attribute__((vector_size(16))); +typedef double v2df __attribute__((vector_size(16))); +typedef long double v1tf __attribute__((vector_size(16))); + +v4sf +neg_vfnmasb (v4sf a, v4sf b, v4sf c) +{ + return -(a * b + c); +} +/* { dg-final { scan-assembler-times "vfnmasb\t%v24,%v24,%v26,%v28" 1 } } */ + +v2df +neg_vfnmadb (v2df a, v2df b, v2df c) +{ + return -(a * b + c); +} +/* { dg-final { scan-assembler-times "vfnmadb\t%v24,%v24,%v26,%v28" 1 } } */ + +v1tf +neg_wfnmaxb (v1tf a, v1tf b, v1tf c) +{ + return -(a * b + c); +} +/* { dg-final { scan-assembler-times "wfnmaxb\t%v24,%v24,%v26,%v28" 1 } } */ + + +v4sf +neg_vfnmssb (v4sf a, v4sf b, v4sf c) +{ + return -(a * b - c); +} +/* { dg-final { scan-assembler-times "vfnmssb\t%v24,%v24,%v26,%v28" 1 } } */ + +v2df +neg_vfnmsdb (v2df a, v2df b, v2df c) +{ + return -(a * b - c); +} +/* { dg-final { scan-assembler-times "vfnmsdb\t%v24,%v24,%v26,%v28" 1 } } */ + +v1tf +neg_wfnmsxb (v1tf a, v1tf b, v1tf c) +{ + return -(a * b - c); +} +/* { dg-final { scan-assembler-times "wfnmsxb\t%v24,%v24,%v26,%v28" 1 } } */ -- 2.30.2