This finally removes the Y constraint from the vector patterns while folding some of them using a code iterator.
gcc/ChangeLog: 2016-02-29 Andreas Krebbel <kreb...@linux.vnet.ibm.com> * config/s390/subst.md (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 | 13 ++--- gcc/config/s390/vector.md | 127 +++++++++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 59 deletions(-) diff --git a/gcc/config/s390/subst.md b/gcc/config/s390/subst.md index 3becf20..8a1b814 100644 --- a/gcc/config/s390/subst.md +++ b/gcc/config/s390/subst.md @@ -20,19 +20,20 @@ ;; <http://www.gnu.org/licenses/>. (define_code_iterator SUBST [rotate ashift lshiftrt 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..2b8e9bf 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -307,47 +307,82 @@ ; 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") + (unspec:V [(match_operand:<non_vec> 1 "general_operand" "d,QR,K") + (match_operand:SI 2 "nonmemory_operand" "an, I,I") + (match_operand:V 3 "register_operand" "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 vle<bhfgq>\t%v0,%1,%2 vlei<bhfgq>\t%v0,%1,%2" [(set_attr "op_type" "VRS,VRX,VRI")]) -; 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") +(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")]) + ; 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" + "TARGET_VX") + +(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 "nonmemory_operand" "an, 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,%Y2 vste<bhfgq>\t%v1,%0,%2" [(set_attr "op_type" "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,%3(%2) + vste<bhfgq>\t%v1,%0,%2" + [(set_attr "op_type" "VRS,VRX")]) + (define_expand "vec_init<V_HW:mode>" [(match_operand:V_HW 0 "register_operand" "") (match_operand:V_HW 1 "nonmemory_operand" "")] @@ -667,17 +702,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,36 +714,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")))] +(define_insn "*<vec_shifts_name><mode>3<addr_style_op>" + [(set (match_operand:VI 0 "register_operand" "=v") + (VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v") + (match_operand:SI 2 "nonmemory_operand" "an")))] "TARGET_VX" - "vesrl<bhfgq>\t%v0,%v1,%Y2" + "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) - ; Shift each element by corresponding vector element ; veslvb, veslvh, veslvf, veslvg -- 1.9.1