I'm just including this patch for demonstration purposes. It is not ready and needs some work.
From: Stefan Schulze Frielinghaus <[email protected]> This patch adds insn pattern for instruction VMAL which matches PLUS(MULT(a, b), c) over integer vector modes and TI mode. The 8 and 16 byte element modes become available with VXE3/z17. In order to ensure that the pattern is selected, RTX costing has to be tweaked. First of all constant vectors never end up as immediates. Costing for loading those via a single instruction (vzero, vone, vgm, vgbm, vrepi) is set to COSTS_N_INSNS(1) and otherwise they have to be loaded from constant pool and are therefore slightly penalized reflected by costs COSTS_N_INSNS(2). Costs for multiply-and-add are the same as for multiply only. --- gcc/config/s390/s390.cc | 89 +++-- gcc/config/s390/vector.md | 11 + gcc/testsuite/gcc.target/s390/vector/vmal-1.c | 85 +++++ gcc/testsuite/gcc.target/s390/vector/vmal-2.c | 338 ++++++++++++++++++ 4 files changed, 498 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/vector/vmal-1.c create mode 100644 gcc/testsuite/gcc.target/s390/vector/vmal-2.c diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 2e799797991..b640620cda7 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -3944,6 +3944,21 @@ s390_insn_cost (rtx_insn *insn, bool speed) return pattern_cost (PATTERN (insn), speed); } +/* Returns true if the constant value OP is a legitimate vector operand + during and after reload. + This function accepts all constants which can be loaded directly + into an VR. */ + +static bool +legitimate_reload_vector_constant_p (rtx op) +{ + return TARGET_VX && (satisfies_constraint_j00 (op) + || satisfies_constraint_jm1 (op) + || satisfies_constraint_jzz (op) + || satisfies_constraint_jxx (op) + || satisfies_constraint_jyy (op)); +} + /* Compute a (partial) cost for rtx X. Return true if the complete cost has been computed, and false if subexpressions should be scanned. In either case, *TOTAL contains the cost result. The @@ -3956,6 +3971,9 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, int *total, bool speed ATTRIBUTE_UNUSED) { + /* TODO: come up with proper vector cost model. + VML and VMAL have the same costs. */ + constexpr int vml_vmal_costs = COSTS_N_INSNS (5); int code = GET_CODE (x); switch (code) { @@ -3968,6 +3986,16 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, case MEM: *total = 0; return true; + + case CONST_VECTOR: + /* Constant vectors never end up as immediates. Penalize vectors which + cannot be loaded by a single instruction (vzero, vone, vgm, vgbm, + vrepi) and therefore go through the constant pool. */ + *total = COSTS_N_INSNS (1); + if (!legitimate_reload_vector_constant_p (x)) + *total += COSTS_N_INSNS (1); + return true; + case SET: { rtx dst = SET_DEST (x); @@ -4139,12 +4167,43 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, case XOR: case NEG: case NOT: - case PLUS: case MINUS: *total = COSTS_N_INSNS (1); return false; + case PLUS: + /* Check for VECTOR MULTIPLY AND ADD. */ + if (TARGET_VX + && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT || mode == TImode) + /* VMALG/Q become available with z17. */ + && (GET_MODE_UNIT_SIZE (mode) < 8 || TARGET_VXE3) + && GET_CODE (XEXP (x, 0)) == MULT) + { + *total = vml_vmal_costs; + *total += rtx_cost (XEXP (x, 1), mode, PLUS, 1, speed); + *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, MULT, 0, speed); + *total += rtx_cost (XEXP (XEXP (x, 0), 1), mode, MULT, 1, speed); + return true; + } + *total = COSTS_N_INSNS (1); + return false; + case MULT: + if (TARGET_VX + && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT || mode == TImode) + /* VMLG/Q become available with z17. */ + && (GET_MODE_UNIT_SIZE (mode) < 8 || TARGET_VXE3)) + { + /* During expand_mult we may emit a synthetic multiplication + depending on the costs. For example, for mode V16QI and + multiplicand 123 the sequence VREPI+VML competes with + VESL+VS+VESL+VS. The downside of the synthetic multiplication is + that on RTL level it is hard to reconstruct the fact that the + sequence was a multiplication which may prohibit the combination + with a PLUS into a VMAL. */ + *total = vml_vmal_costs; + return false; + } switch (mode) { case E_SImode: @@ -4487,15 +4546,10 @@ legitimate_pic_operand_p (rtx op) static bool s390_legitimate_constant_p (machine_mode mode, rtx op) { - if (TARGET_VX && GET_CODE (op) == CONST_VECTOR) - { - if (!satisfies_constraint_j00 (op) - && !satisfies_constraint_jm1 (op) - && !satisfies_constraint_jzz (op) - && !satisfies_constraint_jxx (op) - && !satisfies_constraint_jyy (op)) - return 0; - } + if (TARGET_VX + && GET_CODE (op) == CONST_VECTOR + && !legitimate_reload_vector_constant_p (op)) + return 0; if (mode == HFmode) return satisfies_constraint_j00 (op); @@ -4678,21 +4732,6 @@ legitimate_reload_fp_constant_p (rtx op) return false; } -/* Returns true if the constant value OP is a legitimate vector operand - during and after reload. - This function accepts all constants which can be loaded directly - into an VR. */ - -static bool -legitimate_reload_vector_constant_p (rtx op) -{ - return TARGET_VX && (satisfies_constraint_j00 (op) - || satisfies_constraint_jm1 (op) - || satisfies_constraint_jzz (op) - || satisfies_constraint_jxx (op) - || satisfies_constraint_jyy (op)); -} - /* Given an rtx OP being reloaded into a reg required to be in class RCLASS, return the class of reg to actually use. */ diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index acca6c4ea34..559b42fb72c 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -2020,6 +2020,17 @@ operands[5] = s390_expand_merge_perm_const (<vec_double>mode, true); }) +; vmalb, vmalhw, vmalf, vmalg, vmalq +(define_insn "*vmal<mode>" + [(set (match_operand:VIT_VXE3 0 "register_operand" "=v") + (plus:VIT_VXE3 (mult:VIT_VXE3 + (match_operand:VIT_VXE3 1 "register_operand" "v") + (match_operand:VIT_VXE3 2 "general_operand" "v")) + (match_operand:VIT_VXE3 3 "general_operand" "v")))] + "TARGET_VX && (<MODE>mode != V2DImode || TARGET_VXE3)" + "vmal<bhfgq><w>\t%v0,%v1,%v2,%v3" + [(set_attr "op_type" "VRR")]) + ; vec_widen_ushiftl_hi ; vec_widen_ushiftl_lo ; vec_widen_sshiftl_hi diff --git a/gcc/testsuite/gcc.target/s390/vector/vmal-1.c b/gcc/testsuite/gcc.target/s390/vector/vmal-1.c new file mode 100644 index 00000000000..a2a25850f49 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vmal-1.c @@ -0,0 +1,85 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z13" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +/* Basic tests for VMAL where all operands are in registers (except for the + scalar TI mode test). VMALG/Q become available with TARGET_VXE3/z17. */ + +typedef signed char v16qi __attribute__ ((vector_size (16))); +typedef short v8hi __attribute__ ((vector_size (16))); +typedef int v4si __attribute__ ((vector_size (16))); +typedef long v2di __attribute__ ((vector_size (16))); +typedef __int128 v1ti __attribute__ ((vector_size (16))); + +/* +** test_v16qi: +** vmalb %v24,%v26,%v28,%v24 +** br %r14 +*/ + +v16qi test_v16qi (v16qi a, v16qi b, v16qi c) +{ + return a + b * c; +} + +/* +** test_v8hi: +** vmalhw %v24,%v26,%v28,%v24 +** br %r14 +*/ + +v8hi test_v8hi (v8hi a, v8hi b, v8hi c) +{ + return a + b * c; +} + +/* +** test_v4si: +** vmalf %v24,%v26,%v28,%v24 +** br %r14 +*/ + +v4si test_v4si (v4si a, v4si b, v4si c) +{ + return a + b * c; +} + +/* +** test_v2di: +** vmalg %v24,%v26,%v28,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v2di test_v2di (v2di a, v2di b, v2di c) +{ + return a + b * c; +} + +/* +** test_v1ti: +** vmalq %v24,%v26,%v28,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v1ti test_v1ti (v1ti a, v1ti b, v1ti c) +{ + return a + b * c; +} + +/* +** test_ti: +** vl .* +** vl .* +** vl .* +** vmalq .* +** vst .* +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +__int128 test_ti (__int128 a, __int128 b, __int128 c) +{ + return a + b * c; +} diff --git a/gcc/testsuite/gcc.target/s390/vector/vmal-2.c b/gcc/testsuite/gcc.target/s390/vector/vmal-2.c new file mode 100644 index 00000000000..ccc1696e9fb --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vmal-2.c @@ -0,0 +1,338 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z13" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +/* Tests for VMAL with a constant multiplicand. */ + +typedef signed char v16qi __attribute__ ((vector_size (16))); +typedef short v8hi __attribute__ ((vector_size (16))); +typedef int v4si __attribute__ ((vector_size (16))); +typedef long v2di __attribute__ ((vector_size (16))); +typedef unsigned long uv2di __attribute__ ((vector_size (16))); +typedef __int128 v1ti __attribute__ ((vector_size (16))); + +#define CST_VEC (uv2di){0xBADC0FFEE0DDF00D, 0xBADC0FFEE0DDF00D} + +/* +** test_v16qi_plus_vrepi: +** vrepi (%v[0-9]+),123,0 +** vmalb %v24,%v26,\1,%v24 +** br %r14 +*/ + +v16qi test_v16qi_plus_vrepi (v16qi a, v16qi b) +{ + return a + b * 123; +} + +/* +** test_v16qi_plus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalb %v24,%v26,\1,%v24 +** br %r14 +*/ + +v16qi test_v16qi_plus_constpool (v16qi a, v16qi b) +{ + return a + b * (v16qi)CST_VEC; +} + +/* +** test_v16qi_minus_vrepi: +** vrepi (%v[0-9]+),-123,0 +** vmalb %v24,%v26,\1,%v24 +** br %r14 +*/ + +v16qi test_v16qi_minus_vrepi (v16qi a, v16qi b) +{ + return a - b * 123; +} + +/* +** test_v16qi_minus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalb %v24,%v26,\1,%v24 +** br %r14 +*/ + +v16qi test_v16qi_minus_constpool (v16qi a, v16qi b) +{ + return a - b * (v16qi)CST_VEC; +} + +/* +** test_v8hi_plus_vrepi: +** vrepi (%v[0-9]+),1234,1 +** vmalhw %v24,%v26,\1,%v24 +** br %r14 +*/ + +v8hi test_v8hi_plus_vrepi (v8hi a, v8hi b) +{ + return a + b * 1234; +} + +/* +** test_v8hi_plus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalhw %v24,%v26,\1,%v24 +** br %r14 +*/ + +v8hi test_v8hi_plus_constpool (v8hi a, v8hi b) +{ + return a + b * (v8hi)CST_VEC; +} + +/* +** test_v8hi_minus_vrepi: +** vrepi (%v[0-9]+),-1234,1 +** vmalhw %v24,%v26,\1,%v24 +** br %r14 +*/ + +v8hi test_v8hi_minus_vrepi (v8hi a, v8hi b) +{ + return a - b * 1234; +} + +/* +** test_v8hi_minus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalhw %v24,%v26,\1,%v24 +** br %r14 +*/ + +v8hi test_v8hi_minus_constpool (v8hi a, v8hi b) +{ + return a - b * (v8hi)CST_VEC; +} + +/* +** test_v4si_plus_vrepi: +** vrepi (%v[0-9]+),1234,2 +** vmalf %v24,%v26,\1,%v24 +** br %r14 +*/ + +v4si test_v4si_plus_vrepi (v4si a, v4si b) +{ + return a + b * 1234; +} + +/* +** test_v4si_plus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalf %v24,%v26,\1,%v24 +** br %r14 +*/ + +v4si test_v4si_plus_constpool (v4si a, v4si b) +{ + return a + b * (v4si)CST_VEC; +} + +/* +** test_v4si_minus_vrepi: +** vrepi (%v[0-9]+),-1234,2 +** vmalf %v24,%v26,\1,%v24 +** br %r14 +*/ + +v4si test_v4si_minus_vrepi (v4si a, v4si b) +{ + return a - b * 1234; +} + +/* +** test_v4si_minus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalf %v24,%v26,\1,%v24 +** br %r14 +*/ + +v4si test_v4si_minus_constpool (v4si a, v4si b) +{ + return a - b * (v4si)CST_VEC; +} + +/* +** test_v2di_plus_vrepi: +** vrepi (%v[0-9]+),1234,3 +** vmalg %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v2di test_v2di_plus_vrepi (v2di a, v2di b) +{ + return a + b * 1234; +} + +/* +** test_v2di_plus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalg %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v2di test_v2di_plus_constpool (v2di a, v2di b) +{ + return a + b * (v2di)CST_VEC; +} + +/* +** test_v2di_minus_vrepi: +** vrepi (%v[0-9]+),-1234,3 +** vmalg %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v2di test_v2di_minus_vrepi (v2di a, v2di b) +{ + return a - b * 1234; +} + +/* +** test_v2di_minus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalg %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v2di test_v2di_minus_constpool (v2di a, v2di b) +{ + return a - b * (v2di)CST_VEC; +} + +/* +** test_v1ti_plus_vrepi: +** vrepi (%v[0-9]+),-86,0 +** vmalq %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v1ti test_v1ti_plus_vrepi (v1ti a, v1ti b) +{ + return a + b * ((__int128)0xaaaaaaaaaaaaaaaa << 64 | (__int128)0xaaaaaaaaaaaaaaaa); +} + +/* +** test_v1ti_plus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalq %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v1ti test_v1ti_plus_constpool (v1ti a, v1ti b) +{ + return a + b * ((__int128)0xBADC0FFEE0DDF00D << 64 | (__int128)0xBADC0FFEE0DDF00D); +} + +/* +** test_v1ti_minus_vrepi: +** vrepi (%v[0-9]+),-86,0 +** vmalq %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v1ti test_v1ti_minus_vrepi (v1ti a, v1ti b) +{ + return a - b * ((__int128)0x5555555555555555 << 64 | (__int128)0x5555555555555556); +} + +/* +** test_v1ti_minus_constpool: +** larl .* +** vl (%v[0-9]+),.* +** vmalq %v24,%v26,\1,%v24 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +v1ti test_v1ti_minus_constpool (v1ti a, v1ti b) +{ + return a - b * ((__int128)0xBADC0FFEE0DDF00D << 64 | (__int128)0xBADC0FFEE0DDF00D); +} + +/* +** test_int128_plus_vrepi: +** (?:vl|vrepi) .* +** (?:vl|vrepi) .* +** (?:vl|vrepi) .* +** vmalq (%v[0-9]+),.* +** vst \1,0\(%r2\),3 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +__int128 test_int128_plus_vrepi (__int128 a, __int128 b) +{ + return a + b * ((__int128)0xaaaaaaaaaaaaaaaa << 64 | (__int128)0xaaaaaaaaaaaaaaaa); +} + +/* +** test_int128_plus_constpool: +** larl .* +** vl .* +** vl .* +** vl .* +** vmalq (%v[0-9]+),.* +** vst \1,0\(%r2\),3 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +__int128 test_int128_plus_constpool (__int128 a, __int128 b) +{ + return a + b * ((__int128)0xBADC0FFEE0DDF00D << 64 | (__int128)0xBADC0FFEE0DDF00D); +} + +/* +** test_int128_minus_vrepi: +** (?:vl|vrepi) .* +** (?:vl|vrepi) .* +** (?:vl|vrepi) .* +** vmalq (%v[0-9]+),.* +** vst \1,0\(%r2\),3 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +__int128 test_int128_minus_vrepi (__int128 a, __int128 b) +{ + return a - b * ((__int128)0x5555555555555555 << 64 | (__int128)0x5555555555555556); +} + +/* +** test_int128_minus_constpool: +** larl .* +** vl .* +** vl .* +** vl .* +** vmalq (%v[0-9]+),.* +** vst \1,0\(%r2\),3 +** br %r14 +*/ + +__attribute__ ((target ("arch=z17"))) +__int128 test_int128_minus_constpool (__int128 a, __int128 b) +{ + return a - b * ((__int128)0xBADC0FFEE0DDF00D << 64 | (__int128)0xBADC0FFEE0DDF00D); +} -- 2.55.0
