Hi Michael,

I have the diff below for the binops in my tree locally.
Maybe something like this works for you? Untested but compiles and
the expander helpers would need to be fortified obviously.

Regards
 Robin

--

gcc/ChangeLog:

        * config/riscv/autovec.md (<optab><mode>3): New binops expander.
        * config/riscv/riscv-protos.h (emit_nonvlmax_binop): Define.
        * config/riscv/riscv-v.cc (emit_pred_binop): New function.
        (emit_nonvlmax_binop): New function.
        * config/riscv/vector-iterators.md: New iterator.
---
 gcc/config/riscv/autovec.md          | 12 ++++
 gcc/config/riscv/riscv-protos.h      |  1 +
 gcc/config/riscv/riscv-v.cc          | 89 ++++++++++++++++++++--------
 gcc/config/riscv/vector-iterators.md | 20 +++++++
 4 files changed, 97 insertions(+), 25 deletions(-)

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index b5d46ff57ab..c21d241f426 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -47,3 +47,15 @@ (define_expand "len_store_<mode>"
                                  operands[1], operands[2], <VM>mode);
   DONE;
 })
+
+(define_expand "<optab><mode>3"
+  [(set (match_operand:VI 0 "register_operand")
+       (any_int_binop:VI (match_operand:VI 1 "register_operand")
+                         (match_operand:VI 2 "register_operand")))]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_nonvlmax_binop (code_for_pred (<ANY_INT_BINOP>, 
<MODE>mode),
+                                    operands[0], operands[1], operands[2],
+                                    gen_reg_rtx (Pmode), <VM>mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f6ea6846736..5cca543c773 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -163,6 +163,7 @@ void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
 void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode);
 enum vlmul_type get_vlmul (machine_mode);
 unsigned int get_ratio (machine_mode);
 int get_ta (rtx);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 5e69427ac54..98ebc052340 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -52,7 +52,7 @@ namespace riscv_vector {
 template <int MAX_OPERANDS> class insn_expander
 {
 public:
-  insn_expander () : m_opno (0) {}
+  insn_expander () : m_opno (0), has_dest(false) {}
   void add_output_operand (rtx x, machine_mode mode)
   {
     create_output_operand (&m_ops[m_opno++], x, mode);
@@ -83,6 +83,44 @@ public:
     add_input_operand (gen_int_mode (type, Pmode), Pmode);
   }
 
+  void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode)
+  {
+    dest_mode = GET_MODE (dest);
+    has_dest = true;
+
+    add_output_operand (dest, dest_mode);
+
+    if (mask)
+      add_input_operand (mask, GET_MODE (mask));
+    else
+      add_all_one_mask_operand (mask_mode);
+
+    add_vundef_operand (dest_mode);
+  }
+
+  void set_len_and_policy (rtx len, bool vlmax_p)
+    {
+      gcc_assert (has_dest);
+      gcc_assert (len || vlmax_p);
+
+      if (len)
+       add_input_operand (len, Pmode);
+      else
+       {
+         rtx vlmax = gen_reg_rtx (Pmode);
+         emit_vlmax_vsetvl (dest_mode, vlmax);
+         add_input_operand (vlmax, Pmode);
+       }
+
+      if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
+       add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy 
());
+
+      if (vlmax_p)
+       add_avl_type_operand (avl_type::VLMAX);
+      else
+       add_avl_type_operand (avl_type::NONVLMAX);
+    }
+
   void expand (enum insn_code icode, bool temporary_volatile_p = false)
   {
     if (temporary_volatile_p)
@@ -96,6 +134,8 @@ public:
 
 private:
   int m_opno;
+  bool has_dest;
+  machine_mode dest_mode;
   expand_operand m_ops[MAX_OPERANDS];
 };
 
@@ -183,37 +223,29 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx 
src, rtx len,
              machine_mode mask_mode, bool vlmax_p)
 {
   insn_expander<8> e;
-  machine_mode mode = GET_MODE (dest);
+  e.set_dest_and_mask (mask, dest, mask_mode);
 
-  e.add_output_operand (dest, mode);
-
-  if (mask)
-    e.add_input_operand (mask, GET_MODE (mask));
-  else
-    e.add_all_one_mask_operand (mask_mode);
+  e.add_input_operand (src, GET_MODE (src));
 
-  e.add_vundef_operand (mode);
+  e.set_len_and_policy (len, vlmax_p);
 
-  e.add_input_operand (src, GET_MODE (src));
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+}
 
-  if (len)
-    e.add_input_operand (len, Pmode);
-  else
-    {
-      rtx vlmax = gen_reg_rtx (Pmode);
-      emit_vlmax_vsetvl (mode, vlmax);
-      e.add_input_operand (vlmax, Pmode);
-    }
+/* Emit an RVV unmask && vl mov from SRC to DEST.  */
+static void
+emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
+                rtx len, machine_mode mask_mode, bool vlmax_p)
+{
+  insn_expander<9> e;
+  e.set_dest_and_mask (mask, dest, mask_mode);
 
-  if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
-    e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy 
());
+  e.add_input_operand (src1, GET_MODE (src1));
+  e.add_input_operand (src2, GET_MODE (src2));
 
-  if (vlmax_p)
-    e.add_avl_type_operand (avl_type::VLMAX);
-  else
-    e.add_avl_type_operand (avl_type::NONVLMAX);
+  e.set_len_and_policy (len, vlmax_p);
 
-  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P 
(src2));
 }
 
 void
@@ -236,6 +268,13 @@ emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx 
len,
   emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
 }
 
+void
+emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+                    machine_mode mask_mode)
+{
+  emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, false);
+}
+
 static void
 expand_const_vector (rtx target, rtx src, machine_mode mask_mode)
 {
diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index a8e856161d3..7cf21751d2f 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -934,6 +934,26 @@ (define_code_iterator any_int_binop [plus minus and ior 
xor ashift ashiftrt lshi
   smax umax smin umin mult div udiv mod umod
 ])
 
+(define_code_attr ANY_INT_BINOP [
+    (plus "PLUS")
+    (minus "MINUS")
+    (and "AND")
+    (ior "IOR")
+    (xor "XOR")
+    (ashift "ASHIFT")
+    (ashiftrt "ASHIFTRT")
+    (lshiftrt "LSHIFTRT")
+    (smax "SMAX")
+    (umax "UMAX")
+    (smin "SMIN")
+    (umin "UMIN")
+    (mult "MULT")
+    (div "DIV")
+    (udiv "UDIV")
+    (mod "MOD")
+    (umod "UMOD")
+])
+
 (define_code_iterator any_int_unop [neg not])
 
 (define_code_iterator any_commutative_binop [plus and ior xor
-- 
2.40.0

Reply via email to