From 6e5b5de88b7764a779cee87591186a01cab96f50 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Tue, 19 May 2015 17:30:25 +0000 Subject: [PATCH] S/390 Add vector scalar instruction support. With this patch GCC makes use of the vector instruction which are available in single element mode. By using these instructions scalar double operations can use 32 registers. gcc/ * config/s390/s390-modes.def: Add new modes CCVEQ, CCVFH, and CCVFHE. * config/s390/s390.c (s390_match_ccmode_set): Handle new modes. (s390_select_ccmode): Likewise. (s390_canonicalize_comparison): Swap operands if necessary. (s390_expand_vec_compare_scalar): Expand DFmode compare using single element vector instructions. (s390_emit_compare): Call s390_expand_vec_compare_scalar. (s390_branch_condition_mask): Generate CC masks for the new modes. * config/s390/s390.md (v0, vf, vd): New mode attributes. (VFCMP, asm_fcmp, insn_cmp): New mode iterator and attributes. (*vec_cmpdf_cconly, *fixuns_truncdfdi2_z13) (*fix_trunc2_bfp, *floatunsdidf2_z13) (*floatuns2, *extendsfdf2_z13) (*extend2): New insn definition. (fix_trunc2_bfp, loatuns2) (extend2): Turn into expander. (floatdi2, truncdfsf2, add3, sub3, mul3) (div3, *neg2, *abs2, *negabs2) (sqrt2): Add vector instruction. gcc/testsuite/ * gcc.target/s390/vector/vec-scalar-cmp-1.c: New test. From-SVN: r223397 --- gcc/ChangeLog | 23 ++ gcc/config/s390/s390-modes.def | 10 + gcc/config/s390/s390.c | 130 +++++++- gcc/config/s390/s390.md | 304 +++++++++++++----- gcc/testsuite/ChangeLog | 4 + .../gcc.target/s390/vector/vec-scalar-cmp-1.c | 49 +++ 6 files changed, 429 insertions(+), 91 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf7fe8fd8b6..f646147446b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2015-05-19 Andreas Krebbel + + * config/s390/s390-modes.def: Add new modes CCVEQ, CCVFH, and + CCVFHE. + * config/s390/s390.c (s390_match_ccmode_set): Handle new modes. + (s390_select_ccmode): Likewise. + (s390_canonicalize_comparison): Swap operands if necessary. + (s390_expand_vec_compare_scalar): Expand DFmode compare using + single element vector instructions. + (s390_emit_compare): Call s390_expand_vec_compare_scalar. + (s390_branch_condition_mask): Generate CC masks for the new modes. + * config/s390/s390.md (v0, vf, vd): New mode attributes. + (VFCMP, asm_fcmp, insn_cmp): New mode iterator and attributes. + (*vec_cmpdf_cconly, *fixuns_truncdfdi2_z13) + (*fix_trunc2_bfp, *floatunsdidf2_z13) + (*floatuns2, *extendsfdf2_z13) + (*extend2): New insn definition. + (fix_trunc2_bfp, loatuns2) + (extend2): Turn into expander. + (floatdi2, truncdfsf2, add3, sub3, mul3) + (div3, *neg2, *abs2, *negabs2) + (sqrt2): Add vector instruction. + 2015-05-19 Andreas Krebbel * config/s390/constraints.md (j00, jm1, jxx, jyy, v): New diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def index a40559effe9..26c0a8165a2 100644 --- a/gcc/config/s390/s390-modes.def +++ b/gcc/config/s390/s390-modes.def @@ -84,7 +84,12 @@ Requested mode -> Destination CC register mode CCS, CCU, CCT, CCSR, CCUR -> CCZ CCA -> CCAP, CCAN +Vector comparison modes +CCVEQ EQ - - NE (VCEQ) + +CCVFH GT - - UNLE (VFCH) +CCVFHE GE - - UNLT (VFCHE) *** Comments *** CCAP, CCAN @@ -182,6 +187,11 @@ CC_MODE (CCT2); CC_MODE (CCT3); CC_MODE (CCRAW); +CC_MODE (CCVEQ); +CC_MODE (CCVFH); +CC_MODE (CCVFHE); + + /* Vector modes. */ VECTOR_MODES (INT, 2); /* V2QI */ diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 3ff9526ebcd..68a92a92946 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -681,6 +681,9 @@ s390_match_ccmode_set (rtx set, machine_mode req_mode) case CCT1mode: case CCT2mode: case CCT3mode: + case CCVEQmode: + case CCVFHmode: + case CCVFHEmode: if (req_mode != set_mode) return 0; break; @@ -781,6 +784,29 @@ s390_tm_ccmode (rtx op1, rtx op2, bool mixed) machine_mode s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1) { + if (TARGET_VX + && register_operand (op0, DFmode) + && register_operand (op1, DFmode)) + { + /* LT, LE, UNGT, UNGE require swapping OP0 and OP1. Either + s390_emit_compare or s390_canonicalize_comparison will take + care of it. */ + switch (code) + { + case EQ: + case NE: + return CCVEQmode; + case GT: + case UNLE: + return CCVFHmode; + case GE: + case UNLT: + return CCVFHEmode; + default: + ; + } + } + switch (code) { case EQ: @@ -1058,8 +1084,73 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1, rtx tem = *op0; *op0 = *op1; *op1 = tem; *code = (int)swap_condition ((enum rtx_code)*code); } + + /* Using the scalar variants of vector instructions for 64 bit FP + comparisons might require swapping the operands. */ + if (TARGET_VX + && register_operand (*op0, DFmode) + && register_operand (*op1, DFmode) + && (*code == LT || *code == LE || *code == UNGT || *code == UNGE)) + { + rtx tmp; + + switch (*code) + { + case LT: *code = GT; break; + case LE: *code = GE; break; + case UNGT: *code = UNLE; break; + case UNGE: *code = UNLT; break; + default: ; + } + tmp = *op0; *op0 = *op1; *op1 = tmp; + } } +/* Helper function for s390_emit_compare. If possible emit a 64 bit + FP compare using the single element variant of vector instructions. + Replace CODE with the comparison code to be used in the CC reg + compare and return the condition code register RTX in CC. */ + +static bool +s390_expand_vec_compare_scalar (enum rtx_code *code, rtx cmp1, rtx cmp2, + rtx *cc) +{ + machine_mode cmp_mode; + bool swap_p = false; + + switch (*code) + { + case EQ: cmp_mode = CCVEQmode; break; + case NE: cmp_mode = CCVEQmode; break; + case GT: cmp_mode = CCVFHmode; break; + case GE: cmp_mode = CCVFHEmode; break; + case UNLE: cmp_mode = CCVFHmode; break; + case UNLT: cmp_mode = CCVFHEmode; break; + case LT: cmp_mode = CCVFHmode; *code = GT; swap_p = true; break; + case LE: cmp_mode = CCVFHEmode; *code = GE; swap_p = true; break; + case UNGE: cmp_mode = CCVFHmode; *code = UNLE; swap_p = true; break; + case UNGT: cmp_mode = CCVFHEmode; *code = UNLT; swap_p = true; break; + default: return false; + } + + if (swap_p) + { + rtx tmp = cmp2; + cmp2 = cmp1; + cmp1 = tmp; + } + *cc = gen_rtx_REG (cmp_mode, CC_REGNUM); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, + gen_rtx_SET (*cc, + gen_rtx_COMPARE (cmp_mode, cmp1, + cmp2)), + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_SCRATCH (V2DImode))))); + return true; +} + + /* Emit a compare instruction suitable to implement the comparison OP0 CODE OP1. Return the correct condition RTL to be placed in the IF_THEN_ELSE of the conditional branch testing the result. */ @@ -1070,10 +1161,18 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1) machine_mode mode = s390_select_ccmode (code, op0, op1); rtx cc; - /* Do not output a redundant compare instruction if a compare_and_swap - pattern already computed the result and the machine modes are compatible. */ - if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) + if (TARGET_VX + && register_operand (op0, DFmode) + && register_operand (op1, DFmode) + && s390_expand_vec_compare_scalar (&code, op0, op1, &cc)) + { + /* Work has been done by s390_expand_vec_compare_scalar already. */ + } + else if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) { + /* Do not output a redundant compare instruction if a + compare_and_swap pattern already computed the result and the + machine modes are compatible. */ gcc_assert (s390_cc_modes_compatible (GET_MODE (op0), mode) == GET_MODE (op0)); cc = op0; @@ -1308,6 +1407,31 @@ s390_branch_condition_mask (rtx code) } break; + /* Vector comparison modes. */ + + case CCVEQmode: + switch (GET_CODE (code)) + { + case EQ: return CC0; + case NE: return CC3; + default: return -1; + } + /* FP vector compare modes. */ + + case CCVFHmode: + switch (GET_CODE (code)) + { + case GT: return CC0; + case UNLE: return CC3; + default: return -1; + } + case CCVFHEmode: + switch (GET_CODE (code)) + { + case GE: return CC0; + case UNLT: return CC3; + default: return -1; + } case CCRAWmode: switch (GET_CODE (code)) { diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index ef087c2e730..e1188ba4f21 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -524,6 +524,14 @@ ;; first and the second operand match for bfp modes. (define_mode_attr f0 [(TF "0") (DF "0") (SF "0") (TD "f") (DD "f") (DD "f")]) +;; This attribute is used to merge the scalar vector instructions into +;; the FP patterns. For non-supported modes (all but DF) it expands +;; to constraints which are supposed to be matched by an earlier +;; variant. +(define_mode_attr v0 [(TF "0") (DF "v") (SF "0") (TD "0") (DD "0") (DD "0") (TI "0") (DI "v") (SI "0")]) +(define_mode_attr vf [(TF "f") (DF "v") (SF "f") (TD "f") (DD "f") (DD "f") (TI "f") (DI "v") (SI "f")]) +(define_mode_attr vd [(TF "d") (DF "v") (SF "d") (TD "d") (DD "d") (DD "d") (TI "d") (DI "v") (SI "d")]) + ;; This attribute is used in the operand list of the instruction to have an ;; additional operand for the dfp instructions. (define_mode_attr op1 [(TF "") (DF "") (SF "") @@ -635,6 +643,17 @@ ;; Allow return and simple_return to be defined from a single template. (define_code_iterator ANY_RETURN [return simple_return]) + + +; Condition code modes generated by vector fp comparisons. These will +; be used also in single element mode. +(define_mode_iterator VFCMP [CCVEQ CCVFH CCVFHE]) +; Used with VFCMP to expand part of the mnemonic +; For fp we have a mismatch: eq in the insn name - e in asm +(define_mode_attr asm_fcmp [(CCVEQ "e") (CCVFH "h") (CCVFHE "he")]) +(define_mode_attr insn_cmp [(CCVEQ "eq") (CCVFH "h") (CCVFHE "he")]) + + (include "vector.md") ;; @@ -1144,6 +1163,15 @@ [(set_attr "op_type" "RRE,RXE") (set_attr "type" "fsimp")]) +; wfcedbs, wfchdbs, wfchedbs +(define_insn "*vec_cmpdf_cconly" + [(set (reg:VFCMP CC_REGNUM) + (compare:VFCMP (match_operand:DF 0 "register_operand" "v") + (match_operand:DF 1 "register_operand" "v"))) + (clobber (match_scratch:V2DI 2 "=v"))] + "TARGET_Z13 && TARGET_HARD_FLOAT" + "wfcdbs\t%v2,%v0,%v1" + [(set_attr "op_type" "VRR")]) ; Compare and Branch instructions @@ -4360,14 +4388,27 @@ ; fixuns_trunc(tf|df|sf|td|dd)(di|si)2 instruction patterns. +(define_insn "*fixuns_truncdfdi2_z13" + [(set (match_operand:DI 0 "register_operand" "=d,v") + (unsigned_fix:DI (match_operand:DF 1 "register_operand" "f,v"))) + (unspec:DI [(match_operand:DI 2 "immediate_operand" "K,K")] UNSPEC_ROUND) + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z13 && TARGET_HARD_FLOAT" + "@ + clgdbr\t%0,%h2,%1,0 + wclgdb\t%v0,%v1,0,%h2" + [(set_attr "op_type" "RRF,VRR") + (set_attr "type" "ftoi")]) + ; clfebr, clfdbr, clfxbr, clgebr, clgdbr, clgxbr ; clfdtr, clfxtr, clgdtr, clgxtr (define_insn "*fixuns_trunc2_z196" - [(set (match_operand:GPR 0 "register_operand" "=r") - (unsigned_fix:GPR (match_operand:FP 1 "register_operand" "f"))) - (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND) + [(set (match_operand:GPR 0 "register_operand" "=d") + (unsigned_fix:GPR (match_operand:FP 1 "register_operand" "f"))) + (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND) (clobber (reg:CC CC_REGNUM))] - "TARGET_Z196" + "TARGET_Z196 && TARGET_HARD_FLOAT + && (!TARGET_Z13 || mode != DImode || mode != DFmode)" "clr\t%0,%h2,%1,0" [(set_attr "op_type" "RRF") (set_attr "type" "ftoi")]) @@ -4382,18 +4423,37 @@ DONE; }) +(define_insn "*fix_truncdfdi2_bfp_z13" + [(set (match_operand:DI 0 "register_operand" "=d,v") + (fix:DI (match_operand:DF 1 "register_operand" "f,v"))) + (unspec:DI [(match_operand:DI 2 "immediate_operand" "K,K")] UNSPEC_ROUND) + (clobber (reg:CC CC_REGNUM))] + "TARGET_Z13 && TARGET_HARD_FLOAT" + "@ + cgdbr\t%0,%h2,%1 + wcgdb\t%v0,%v1,0,%h2" + [(set_attr "op_type" "RRE,VRR") + (set_attr "type" "ftoi")]) + ; cgxbr, cgdbr, cgebr, cfxbr, cfdbr, cfebr -(define_insn "fix_trunc2_bfp" - [(set (match_operand:GPR 0 "register_operand" "=d") - (fix:GPR (match_operand:BFP 1 "register_operand" "f"))) - (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND) +(define_insn "*fix_trunc2_bfp" + [(set (match_operand:GPR 0 "register_operand" "=d") + (fix:GPR (match_operand:BFP 1 "register_operand" "f"))) + (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND) (clobber (reg:CC CC_REGNUM))] - "TARGET_HARD_FLOAT" + "TARGET_HARD_FLOAT + && (!TARGET_VX || mode != DImode || mode != DFmode)" "cbr\t%0,%h2,%1" [(set_attr "op_type" "RRE") (set_attr "type" "ftoi")]) - +(define_expand "fix_trunc2_bfp" + [(parallel + [(set (match_operand:GPR 0 "register_operand" "=d") + (fix:GPR (match_operand:BFP 1 "register_operand" "f"))) + (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND) + (clobber (reg:CC CC_REGNUM))])] + "TARGET_HARD_FLOAT") ; ; fix_trunc(td|dd)di2 instruction pattern(s). ; @@ -4440,12 +4500,15 @@ ; cxgbr, cdgbr, cegbr, cxgtr, cdgtr (define_insn "floatdi2" - [(set (match_operand:FP 0 "register_operand" "=f") - (float:FP (match_operand:DI 1 "register_operand" "d")))] + [(set (match_operand:FP 0 "register_operand" "=f,") + (float:FP (match_operand:DI 1 "register_operand" "d,")))] "TARGET_ZARCH && TARGET_HARD_FLOAT" - "cgr\t%0,%1" - [(set_attr "op_type" "RRE") - (set_attr "type" "itof" )]) + "@ + cgr\t%0,%1 + wcdgb\t%v0,%v1,0,0" + [(set_attr "op_type" "RRE,VRR") + (set_attr "type" "itof" ) + (set_attr "cpu_facility" "*,vec")]) ; cxfbr, cdfbr, cefbr (define_insn "floatsi2" @@ -4469,27 +4532,47 @@ ; floatuns(si|di)(tf|df|sf|td|dd)2 instruction pattern(s). ; +(define_insn "*floatunsdidf2_z13" + [(set (match_operand:DF 0 "register_operand" "=f,v") + (unsigned_float:DF (match_operand:DI 1 "register_operand" "d,v")))] + "TARGET_Z13 && TARGET_HARD_FLOAT" + "@ + cdlgbr\t%0,0,%1,0 + wcdlgb\t%v0,%v1,0,0" + [(set_attr "op_type" "RRE,VRR") + (set_attr "type" "itofdf")]) + ; cxlgbr, cdlgbr, celgbr, cxlgtr, cdlgtr ; cxlfbr, cdlfbr, celfbr, cxlftr, cdlftr -(define_insn "floatuns2" - [(set (match_operand:FP 0 "register_operand" "=f") - (unsigned_float:FP (match_operand:GPR 1 "register_operand" "d")))] - "TARGET_Z196 && TARGET_HARD_FLOAT" +(define_insn "*floatuns2" + [(set (match_operand:FP 0 "register_operand" "=f") + (unsigned_float:FP (match_operand:GPR 1 "register_operand" "d")))] + "TARGET_Z196 && TARGET_HARD_FLOAT + && (!TARGET_VX || mode != DFmode || mode != DImode)" "clr\t%0,0,%1,0" [(set_attr "op_type" "RRE") - (set_attr "type" "itof" )]) + (set_attr "type" "itof")]) + +(define_expand "floatuns2" + [(set (match_operand:FP 0 "register_operand" "") + (unsigned_float:FP (match_operand:GPR 1 "register_operand" "")))] + "TARGET_Z196 && TARGET_HARD_FLOAT") ; ; truncdfsf2 instruction pattern(s). ; (define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] + [(set (match_operand:SF 0 "register_operand" "=f,v") + (float_truncate:SF (match_operand:DF 1 "register_operand" "f,v")))] "TARGET_HARD_FLOAT" - "ledbr\t%0,%1" - [(set_attr "op_type" "RRE") - (set_attr "type" "ftruncdf")]) + "@ + ledbr\t%0,%1 + wledb\t%v0,%v1,0,0" ; IEEE inexact exception not suppressed + ; According to BFP rounding mode + [(set_attr "op_type" "RRE,VRR") + (set_attr "type" "ftruncdf") + (set_attr "cpu_facility" "*,vec")]) ; ; trunctf(df|sf)2 instruction pattern(s). @@ -4542,17 +4625,35 @@ ; extend(sf|df)(df|tf)2 instruction pattern(s). ; +(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")))] + "TARGET_Z13 && TARGET_HARD_FLOAT" + "@ + ldebr\t%0,%1 + ldeb\t%0,%1 + wldeb\t%v0,%v1" + [(set_attr "op_type" "RRE,RXE,VRR") + (set_attr "type" "fsimpdf, floaddf,fsimpdf")]) + ; ldebr, ldeb, lxdbr, lxdb, lxebr, lxeb -(define_insn "extend2" - [(set (match_operand:BFP 0 "register_operand" "=f,f") +(define_insn "*extend2" + [(set (match_operand:BFP 0 "register_operand" "=f,f") (float_extend:BFP (match_operand:DSF 1 "nonimmediate_operand" "f,R")))] "TARGET_HARD_FLOAT - && GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode)" + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode) + && (!TARGET_VX || mode != DFmode || mode != SFmode)" "@ lbr\t%0,%1 lb\t%0,%1" - [(set_attr "op_type" "RRE,RXE") - (set_attr "type" "fsimp, fload")]) + [(set_attr "op_type" "RRE,RXE") + (set_attr "type" "fsimp, fload")]) + +(define_expand "extend2" + [(set (match_operand:BFP 0 "register_operand" "") + (float_extend:BFP (match_operand:DSF 1 "nonimmediate_operand" "")))] + "TARGET_HARD_FLOAT + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (mode)") ; ; extendddtd2 and extendsddd2 instruction pattern(s). @@ -5156,17 +5257,20 @@ ; ; 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") - (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%,0") - (match_operand:FP 2 "general_operand" " f,"))) + [(set (match_operand:FP 0 "register_operand" "=f, f,") + (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%, 0,") + (match_operand:FP 2 "general_operand" "f,,"))) (clobber (reg:CC CC_REGNUM))] "TARGET_HARD_FLOAT" "@ ar\t%0,%2 - ab\t%0,%2" - [(set_attr "op_type" ",RXE") - (set_attr "type" "fsimp")]) + ab\t%0,%2 + wfadb\t%v0,%v1,%v2" + [(set_attr "op_type" ",RXE,VRR") + (set_attr "type" "fsimp") + (set_attr "cpu_facility" "*,*,vec")]) ; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr (define_insn "*add3_cc" @@ -5579,16 +5683,18 @@ ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr (define_insn "sub3" - [(set (match_operand:FP 0 "register_operand" "=f, f") - (minus:FP (match_operand:FP 1 "register_operand" ",0") - (match_operand:FP 2 "general_operand" "f,"))) + [(set (match_operand:FP 0 "register_operand" "=f, f,") + (minus:FP (match_operand:FP 1 "register_operand" ", 0,") + (match_operand:FP 2 "general_operand" "f,,"))) (clobber (reg:CC CC_REGNUM))] "TARGET_HARD_FLOAT" "@ sr\t%0,%2 - sb\t%0,%2" - [(set_attr "op_type" ",RXE") - (set_attr "type" "fsimp")]) + sb\t%0,%2 + wfsdb\t%v0,%v1,%v2" + [(set_attr "op_type" ",RXE,VRR") + (set_attr "type" "fsimp") + (set_attr "cpu_facility" "*,*,vec")]) ; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr (define_insn "*sub3_cc" @@ -5994,41 +6100,47 @@ ; mxbr, mdbr, meebr, mxb, mxb, meeb, mdtr, mxtr (define_insn "mul3" - [(set (match_operand:FP 0 "register_operand" "=f,f") - (mult:FP (match_operand:FP 1 "nonimmediate_operand" "%,0") - (match_operand:FP 2 "general_operand" "f,")))] + [(set (match_operand:FP 0 "register_operand" "=f, f,") + (mult:FP (match_operand:FP 1 "nonimmediate_operand" "%, 0,") + (match_operand:FP 2 "general_operand" "f,,")))] "TARGET_HARD_FLOAT" "@ mr\t%0,%2 - mb\t%0,%2" - [(set_attr "op_type" ",RXE") - (set_attr "type" "fmul")]) + mb\t%0,%2 + wfmdb\t%v0,%v1,%v2" + [(set_attr "op_type" ",RXE,VRR") + (set_attr "type" "fmul") + (set_attr "cpu_facility" "*,*,vec")]) ; madbr, maebr, maxb, madb, maeb (define_insn "fma4" - [(set (match_operand:DSF 0 "register_operand" "=f,f") - (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f") - (match_operand:DSF 2 "nonimmediate_operand" "f,R") - (match_operand:DSF 3 "register_operand" "0,0")))] + [(set (match_operand:DSF 0 "register_operand" "=f,f,") + (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,") + (match_operand:DSF 2 "nonimmediate_operand" "f,R,") + (match_operand:DSF 3 "register_operand" "0,0,")))] "TARGET_HARD_FLOAT" "@ mabr\t%0,%1,%2 - mab\t%0,%1,%2" - [(set_attr "op_type" "RRE,RXE") - (set_attr "type" "fmadd")]) + mab\t%0,%1,%2 + wfmadb\t%v0,%v1,%v2,%v3" + [(set_attr "op_type" "RRE,RXE,VRR") + (set_attr "type" "fmadd") + (set_attr "cpu_facility" "*,*,vec")]) ; msxbr, msdbr, msebr, msxb, msdb, mseb (define_insn "fms4" - [(set (match_operand:DSF 0 "register_operand" "=f,f") - (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f") - (match_operand:DSF 2 "nonimmediate_operand" "f,R") - (neg:DSF (match_operand:DSF 3 "register_operand" "0,0"))))] + [(set (match_operand:DSF 0 "register_operand" "=f,f,") + (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f,") + (match_operand:DSF 2 "nonimmediate_operand" "f,R,") + (neg:DSF (match_operand:DSF 3 "register_operand" "0,0,"))))] "TARGET_HARD_FLOAT" "@ msbr\t%0,%1,%2 - msb\t%0,%1,%2" - [(set_attr "op_type" "RRE,RXE") - (set_attr "type" "fmadd")]) + msb\t%0,%1,%2 + wfmsdb\t%v0,%v1,%v2,%v3" + [(set_attr "op_type" "RRE,RXE,VRR") + (set_attr "type" "fmadd") + (set_attr "cpu_facility" "*,*,vec")]) ;; ;;- Divide and modulo instructions. @@ -6454,15 +6566,17 @@ ; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr (define_insn "div3" - [(set (match_operand:FP 0 "register_operand" "=f,f") - (div:FP (match_operand:FP 1 "register_operand" ",0") - (match_operand:FP 2 "general_operand" "f,")))] + [(set (match_operand:FP 0 "register_operand" "=f, f,") + (div:FP (match_operand:FP 1 "register_operand" ", 0,") + (match_operand:FP 2 "general_operand" "f,,")))] "TARGET_HARD_FLOAT" "@ dr\t%0,%2 - db\t%0,%2" - [(set_attr "op_type" ",RXE") - (set_attr "type" "fdiv")]) + db\t%0,%2 + wfddb\t%v0,%v1,%v2" + [(set_attr "op_type" ",RXE,VRR") + (set_attr "type" "fdiv") + (set_attr "cpu_facility" "*,*,vec")]) ;; @@ -7671,14 +7785,18 @@ (set_attr "type" "fsimp")]) ; lcxbr, lcdbr, lcebr +; FIXME: wflcdb does not clobber cc (define_insn "*neg2" - [(set (match_operand:BFP 0 "register_operand" "=f") - (neg:BFP (match_operand:BFP 1 "register_operand" "f"))) + [(set (match_operand:BFP 0 "register_operand" "=f,") + (neg:BFP (match_operand:BFP 1 "register_operand" "f,"))) (clobber (reg:CC CC_REGNUM))] "TARGET_HARD_FLOAT" - "lcbr\t%0,%1" - [(set_attr "op_type" "RRE") - (set_attr "type" "fsimp")]) + "@ + lcbr\t%0,%1 + wflcdb\t%0,%1" + [(set_attr "op_type" "RRE,VRR") + (set_attr "cpu_facility" "*,vec") + (set_attr "type" "fsimp,*")]) ;; @@ -7789,14 +7907,18 @@ (set_attr "type" "fsimp")]) ; lpxbr, lpdbr, lpebr +; FIXME: wflpdb does not clobber cc (define_insn "*abs2" - [(set (match_operand:BFP 0 "register_operand" "=f") - (abs:BFP (match_operand:BFP 1 "register_operand" "f"))) + [(set (match_operand:BFP 0 "register_operand" "=f,") + (abs:BFP (match_operand:BFP 1 "register_operand" "f,"))) (clobber (reg:CC CC_REGNUM))] "TARGET_HARD_FLOAT" - "lpbr\t%0,%1" - [(set_attr "op_type" "RRE") - (set_attr "type" "fsimp")]) + "@ + lpbr\t%0,%1 + wflpdb\t%0,%1" + [(set_attr "op_type" "RRE,VRR") + (set_attr "cpu_facility" "*,vec") + (set_attr "type" "fsimp,*")]) ;; @@ -7900,14 +8022,18 @@ (set_attr "type" "fsimp")]) ; lnxbr, lndbr, lnebr +; FIXME: wflndb does not clobber cc (define_insn "*negabs2" - [(set (match_operand:BFP 0 "register_operand" "=f") - (neg:BFP (abs:BFP (match_operand:BFP 1 "register_operand" "f")))) + [(set (match_operand:BFP 0 "register_operand" "=f,") + (neg:BFP (abs:BFP (match_operand:BFP 1 "register_operand" "f,")))) (clobber (reg:CC CC_REGNUM))] "TARGET_HARD_FLOAT" - "lnbr\t%0,%1" - [(set_attr "op_type" "RRE") - (set_attr "type" "fsimp")]) + "@ + lnbr\t%0,%1 + wflndb\t%0,%1" + [(set_attr "op_type" "RRE,VRR") + (set_attr "cpu_facility" "*,vec") + (set_attr "type" "fsimp,*")]) ;; ;;- Square root instructions. @@ -7919,14 +8045,16 @@ ; sqxbr, sqdbr, sqebr, sqdb, sqeb (define_insn "sqrt2" - [(set (match_operand:BFP 0 "register_operand" "=f,f") - (sqrt:BFP (match_operand:BFP 1 "general_operand" "f,")))] + [(set (match_operand:BFP 0 "register_operand" "=f, f,") + (sqrt:BFP (match_operand:BFP 1 "general_operand" "f,,")))] "TARGET_HARD_FLOAT" "@ sqbr\t%0,%1 - sqb\t%0,%1" - [(set_attr "op_type" "RRE,RXE") - (set_attr "type" "fsqrt")]) + sqb\t%0,%1 + wfsqdb\t%v0,%v1" + [(set_attr "op_type" "RRE,RXE,VRR") + (set_attr "type" "fsqrt") + (set_attr "cpu_facility" "*,*,vec")]) ;; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b851f115b56..7e0fd9d7338 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-05-19 Andreas Krebbel + + * gcc.target/s390/vector/vec-scalar-cmp-1.c: New test. + 2015-05-19 Andreas Krebbel * gcc.target/s390/s390.exp diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c new file mode 100644 index 00000000000..b79120f20f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vec-scalar-cmp-1.c @@ -0,0 +1,49 @@ +/* Check that we use the scalar variants of vector compares. */ + +/* { dg-do compile { target { s390*-*-* } } } */ +/* { dg-options "-O3 -mzarch -march=z13" } */ + +/* { dg-final { scan-assembler-times "wfcedbs\t%v\[0-9\]*,%v0,%v2" 2 } } */ +/* { dg-final { scan-assembler-times "wfchdbs\t%v\[0-9\]*,%v0,%v2" 1 } } */ +/* { dg-final { scan-assembler-times "wfchedbs\t%v\[0-9\]*,%v2,%v0" 1 } } */ +/* { dg-final { scan-assembler-times "wfchdbs\t%v\[0-9\]*,%v2,%v0" 1 } } */ +/* { dg-final { scan-assembler-times "wfchedbs\t%v\[0-9\]*,%v2,%v0" 1 } } */ +/* { dg-final { scan-assembler-times "locrne" 5 } } */ +/* { dg-final { scan-assembler-times "locrno" 1 } } */ + + +int +eq (double a, double b) +{ + return a == b; +} + +int +ne (double a, double b) +{ + return a != b; +} + +int +gt (double a, double b) +{ + return a > b; +} + +int +ge (double a, double b) +{ + return a >= b; +} + +int +lt (double a, double b) +{ + return a < b; +} + +int +le (double a, double b) +{ + return a <= b; +} -- 2.30.2