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

Reply via email to