This finally removes the Y constraint from the vector patterns while folding some of them using a code iterator.
gcc/ChangeLog: * config/s390/subst.md (SUBST mode iterator): Add ashiftrt. (DSI_VI): New mode iterator. ("addr_style_op_subst"): Use DSI_VI instead of DSI. * config/s390/vector.md ("vec_set<mode>"): Move expander before the insn definition. ("*vec_set<mode>"): Change predicate and add alternative to support only either register or const_int operands as element selector. ("*vec_set<mode>_plus"): New pattern to support reg + const_int operands. ("vec_extract<mode>"): New expander. ("*vec_extract<mode>"): New insn definition supporting reg and const_int element selectors. ("*vec_extract<mode>_plus"): New insn definition supporting reg+const_int element selectors. ("rotl<mode>3", "ashl<mode>3", "ashr<mode>3"): Merge into the following expander+insn definition. ("<vec_shifts_name><mode>3"): New expander. ("*<vec_shifts_name><mode>3<addr_style_op>"): New insn definition. --- gcc/config/s390/subst.md | 15 ++--- gcc/config/s390/vector.md | 138 +++++++++++++++++++++++++++------------------- 2 files changed, 89 insertions(+), 64 deletions(-) diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md index 1e2b1ba..08704c2 100644 --- a/gcc/config/s390/subst.md +++ b/gcc/config/s390/subst.md @@ -19,20 +19,21 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. -(define_code_iterator SUBST [ashift lshiftrt rotate]) +(define_code_iterator SUBST [ashift lshiftrt rotate ashiftrt]) +(define_mode_iterator DSI_VI [SI DI V2QI V4QI V8QI V16QI V2HI V4HI V8HI V2SI V4SI V2DI]) ; This expands an register/immediate operand to a register+immediate ; operand to draw advantage of the address style operand format ; providing a addition for free. (define_subst "addr_style_op_subst" - [(set (match_operand:DSI 0 "" "") - (SUBST:DSI (match_operand:DSI 1 "" "") - (match_operand:SI 2 "" "")))] + [(set (match_operand:DSI_VI 0 "" "") + (SUBST:DSI_VI (match_operand:DSI_VI 1 "" "") + (match_operand:SI 2 "" "")))] "" [(set (match_dup 0) - (SUBST:DSI (match_dup 1) - (plus:SI (match_operand:SI 2 "register_operand" "a") - (match_operand 3 "const_int_operand" "n"))))]) + (SUBST:DSI_VI (match_dup 1) + (plus:SI (match_operand:SI 2 "register_operand" "a") + (match_operand 3 "const_int_operand" "n"))))]) ; Use this in the insn name. (define_subst_attr "addr_style_op" "addr_style_op_subst" "" "_plus") diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index cc3287c..a1b208c 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -307,44 +307,81 @@ ; vec_store_lanes? +; vec_set is supposed to *modify* an existing vector so operand 0 is +; duplicated as input operand. +(define_expand "vec_set<mode>" + [(set (match_operand:V 0 "register_operand" "") + (unspec:V [(match_operand:<non_vec> 1 "general_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand" "") + (match_dup 0)] + UNSPEC_VEC_SET))] + "TARGET_VX") + ; FIXME: Support also vector mode operands for 1 ; FIXME: A target memory operand seems to be useful otherwise we end ; up with vl vlvgg vst. Shouldn't the middle-end be able to handle ; that itself? (define_insn "*vec_set<mode>" - [(set (match_operand:V 0 "register_operand" "=v, v,v") - (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y, I,I") - (match_operand:V 3 "register_operand" "0, 0,0")] + [(set (match_operand:V 0 "register_operand" "=v,v,v,v") + (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,d,QR,K") + (match_operand:SI 2 "nonmemory_operand" "a,n,I,I") + (match_operand:V 3 "register_operand" "0,0,0,0")] UNSPEC_VEC_SET))] - "TARGET_VX" + "TARGET_VX + && (!CONST_INT_P (operands[2]) + || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))" "@ - vlvg<bhfgq>\t%v0,%1,%Y2 + vlvg<bhfgq>\t%v0,%1,0(%2) + vlvg<bhfgq>\t%v0,%1,%2 vle<bhfgq>\t%v0,%1,%2 vlei<bhfgq>\t%v0,%1,%2" - [(set_attr "op_type" "VRS,VRX,VRI")]) + [(set_attr "op_type" "VRS,VRS,VRX,VRI")]) + +(define_insn "*vec_set<mode>_plus" + [(set (match_operand:V 0 "register_operand" "=v") + (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d") + (plus:SI (match_operand:SI 2 "register_operand" "a") + (match_operand:SI 4 "const_int_operand" "n")) + (match_operand:V 3 "register_operand" "0")] + UNSPEC_VEC_SET))] + "TARGET_VX" + "vlvg<bhfgq>\t%v0,%1,%4(%2)" + [(set_attr "op_type" "VRS")]) -; vec_set is supposed to *modify* an existing vector so operand 0 is -; duplicated as input operand. -(define_expand "vec_set<mode>" - [(set (match_operand:V 0 "register_operand" "") - (unspec:V [(match_operand:<non_vec> 1 "general_operand" "") - (match_operand:SI 2 "shift_count_or_setmem_operand" "") - (match_dup 0)] - UNSPEC_VEC_SET))] - "TARGET_VX") ; FIXME: Support also vector mode operands for 0 ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :( ; This is used via RTL standard name as well as for expanding the builtin -(define_insn "vec_extract<mode>" - [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR") - (unspec:<non_vec> [(match_operand:V 1 "register_operand" " v, v") - (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")] +(define_expand "vec_extract<mode>" + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "") + (unspec:<non_vec> [(match_operand:V 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand" "")] UNSPEC_VEC_EXTRACT))] + "TARGET_VX") + +(define_insn "*vec_extract<mode>" + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,d,QR") + (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v,v, v") + (match_operand:SI 2 "nonmemory_operand" "a,n, I")] + UNSPEC_VEC_EXTRACT))] + "TARGET_VX + && (!CONST_INT_P (operands[2]) + || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))" + "@ + vlgv<bhfgq>\t%0,%v1,0(%2) + vlgv<bhfgq>\t%0,%v1,%2 + vste<bhfgq>\t%v1,%0,%2" + [(set_attr "op_type" "VRS,VRS,VRX")]) + +(define_insn "*vec_extract<mode>_plus" + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,QR") + (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v, v") + (plus:SI (match_operand:SI 2 "nonmemory_operand" "a, I") + (match_operand:SI 3 "const_int_operand" "n, I"))] + UNSPEC_VEC_EXTRACT))] "TARGET_VX" "@ - vlgv<bhfgq>\t%0,%v1,%Y2 + vlgv<bhfgq>\t%0,%v1,%3(%2) vste<bhfgq>\t%v1,%0,%2" [(set_attr "op_type" "VRS,VRX")]) @@ -667,17 +704,6 @@ [(set_attr "op_type" "VRR")]) -; Vector rotate instructions - -; Each vector element rotated by a scalar -; verllb, verllh, verllf, verllg -(define_insn "rotl<mode>3" - [(set (match_operand:VI 0 "register_operand" "=v") - (rotate:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] - "TARGET_VX" - "verll<bhfgq>\t%v0,%v1,%Y2" - [(set_attr "op_type" "VRS")]) ; Each vector element rotated by the corresponding vector element ; verllvb, verllvh, verllvf, verllvg @@ -690,35 +716,33 @@ [(set_attr "op_type" "VRR")]) -; Shift each element by scalar value +; Vector rotate and shift by scalar instructions -; veslb, veslh, veslf, veslg -(define_insn "ashl<mode>3" - [(set (match_operand:VI 0 "register_operand" "=v") - (ashift:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] - "TARGET_VX" - "vesl<bhfgq>\t%v0,%v1,%Y2" - [(set_attr "op_type" "VRS")]) +(define_code_iterator VEC_SHIFTS [ashift ashiftrt lshiftrt rotate]) +(define_code_attr vec_shifts_name [(ashift "ashl") (ashiftrt "ashr") + (lshiftrt "lshr") (rotate "rotl")]) +(define_code_attr vec_shifts_mnem [(ashift "vesl") (ashiftrt "vesra") + (lshiftrt "vesrl") (rotate "verll")]) -; vesrab, vesrah, vesraf, vesrag -(define_insn "ashr<mode>3" - [(set (match_operand:VI 0 "register_operand" "=v") - (ashiftrt:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] - "TARGET_VX" - "vesra<bhfgq>\t%v0,%v1,%Y2" - [(set_attr "op_type" "VRS")]) +; Each vector element rotated by a scalar +(define_expand "<vec_shifts_name><mode>3" + [(set (match_operand:VI 0 "register_operand" "") + (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand" "")))] + "TARGET_VX") +; verllb, verllh, verllf, verllg +; veslb, veslh, veslf, veslg +; vesrab, vesrah, vesraf, vesrag ; vesrlb, vesrlh, vesrlf, vesrlg -(define_insn "lshr<mode>3" - [(set (match_operand:VI 0 "register_operand" "=v") - (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] - "TARGET_VX" - "vesrl<bhfgq>\t%v0,%v1,%Y2" - [(set_attr "op_type" "VRS")]) - +(define_insn "*<vec_shifts_name><mode>3<addr_style_op>" + [(set (match_operand:VI 0 "register_operand" "=v,v") + (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v,v") + (match_operand:SI 2 "nonmemory_operand" "a,n")))] + "TARGET_VX" + "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2" + [(set_attr "enabled" "*,<addr_style_op_enabled>") + (set_attr "op_type" "VRS")]) ; Shift each element by corresponding vector element -- 1.9.1