Changes from v1:

 - Rebase against Juzhe's vec_series patch.
 - Get rid of redundant scalar mode setting.


This patch adds basic binary integer operations support.  It is based
on Michael Collison's work and makes use of the existing helpers in
riscv-c.cc.  It introduces emit_nonvlmax_binop which, in turn, uses
emit_pred_binop.  Setting the destination as well as the mask and the
length are factored out into separate functions.

gcc/ChangeLog:

        * config/riscv/autovec.md (<optab><mode>3): Add integer binops.
        * config/riscv/riscv-protos.h (emit_nonvlmax_binop): Declare.
        * config/riscv/riscv-v.cc (emit_pred_op): New function.
        (set_expander_dest_and_mask): New function.
        (emit_pred_binop): New function.
        (emit_nonvlmax_binop): New function.

Co-authored-by: Michael Collison <colli...@rivosinc.com>
---
 gcc/config/riscv/autovec.md     |  37 ++++++++
 gcc/config/riscv/riscv-protos.h |   2 +
 gcc/config/riscv/riscv-v.cc     | 148 ++++++++++++++++++--------------
 3 files changed, 123 insertions(+), 64 deletions(-)

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 99dc4f046b0..e249f4be704 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -82,3 +82,40 @@ (define_expand "@vec_series<mode>"
     DONE;
   }
 )
+
+;; ========================================================================
+;; == Vector operations
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Binary operations
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vadd.vv/vsub.vv/...
+;; - vadd.vi/vsub.vi/...
+;; -------------------------------------------------------------------------
+
+(define_expand "<optab><mode>3"
+  [(set (match_operand:VI 0 "register_operand")
+    (any_int_binop:VI
+     (match_operand:VI 1 "<binop_rhs1_predicate>")
+     (match_operand:VI 2 "<binop_rhs2_predicate>")))]
+  "TARGET_VECTOR"
+{
+  if (!register_operand (operands[2], <MODE>mode))
+    {
+      rtx cst;
+      gcc_assert (const_vec_duplicate_p(operands[2], &cst));
+      riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
+                                        (<CODE>, <MODE>mode),
+                                        operands[0], operands[1], cst,
+                                        NULL, <VM>mode,
+                                        <VEL>mode);
+    }
+  else
+    riscv_vector::emit_nonvlmax_binop (code_for_pred
+                                      (<CODE>, <MODE>mode),
+                                      operands[0], operands[1], operands[2],
+                                      NULL, <VM>mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index e8a728ae226..4d0589e502c 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -169,6 +169,8 @@ 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,
+                         machine_mode = VOIDmode);
 enum vlmul_type get_vlmul (machine_mode);
 unsigned int get_ratio (machine_mode);
 unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 381e6601a17..8f46226d571 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -53,7 +53,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);
@@ -84,6 +84,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)
@@ -97,6 +135,8 @@ public:
 
 private:
   int m_opno;
+  bool has_dest;
+  machine_mode dest_mode;
   expand_operand m_ops[MAX_OPERANDS];
 };
 
@@ -195,37 +235,41 @@ 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);
+  e.add_input_operand (src, GET_MODE (src));
 
-  if (mask)
-    e.add_input_operand (mask, GET_MODE (mask));
-  else
-    e.add_all_one_mask_operand (mask_mode);
+  e.set_len_and_policy (len, vlmax_p);
 
-  e.add_vundef_operand (mode);
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+}
 
-  e.add_input_operand (src, GET_MODE (src));
+/* Emit an RVV binop.  If one of SRC1 and SRC2 is a scalar operand, its mode is
+   specified using SCALAR_MODE.  */
+static void
+emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
+                rtx len, machine_mode mask_mode, machine_mode scalar_mode,
+                bool vlmax_p)
+{
+  insn_expander<9> e;
+  e.set_dest_and_mask (mask, dest, mask_mode);
 
-  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);
-    }
+  gcc_assert (VECTOR_MODE_P (GET_MODE (src1))
+             || VECTOR_MODE_P (GET_MODE (src2)));
 
-  if (GET_MODE_CLASS (mode) != MODE_VECTOR_BOOL)
-    e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy 
());
+  if (VECTOR_MODE_P (GET_MODE (src1)))
+    e.add_input_operand (src1, GET_MODE (src1));
+  else
+    e.add_input_operand (src1, scalar_mode);
 
-  if (vlmax_p)
-    e.add_avl_type_operand (avl_type::VLMAX);
+  if (VECTOR_MODE_P (GET_MODE (src2)))
+    e.add_input_operand (src2, GET_MODE (src2));
   else
-    e.add_avl_type_operand (avl_type::NONVLMAX);
+    e.add_input_operand (src2, scalar_mode);
 
-  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
+  e.set_len_and_policy (len, vlmax_p);
+
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P 
(src2));
 }
 
 void
@@ -248,49 +292,25 @@ emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx 
len,
   emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
 }
 
-/* Emit binary operations.  */
-
-static void
-emit_binop (unsigned icode, rtx *ops, machine_mode mask_mode,
-           machine_mode scalar_mode)
+void
+emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+                    machine_mode mask_mode, machine_mode scalar_mode)
 {
-  insn_expander<9> e;
-  machine_mode mode = GET_MODE (ops[0]);
-  e.add_output_operand (ops[0], mode);
-  e.add_all_one_mask_operand (mask_mode);
-  e.add_vundef_operand (mode);
-  if (VECTOR_MODE_P (GET_MODE (ops[1])))
-    e.add_input_operand (ops[1], GET_MODE (ops[1]));
-  else
-    e.add_input_operand (ops[1], scalar_mode);
-  if (VECTOR_MODE_P (GET_MODE (ops[2])))
-    e.add_input_operand (ops[2], GET_MODE (ops[2]));
-  else
-    e.add_input_operand (ops[2], scalar_mode);
-  rtx vlmax = gen_reg_rtx (Pmode);
-  emit_vlmax_vsetvl (mode, vlmax);
-  e.add_input_operand (vlmax, Pmode);
-  e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
-  e.add_avl_type_operand (avl_type::VLMAX);
-  e.expand ((enum insn_code) icode, false);
+  emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode,
+                  scalar_mode, len ? false : true);
 }
 
 /* Emit vid.v instruction.  */
 
 static void
-emit_index_op (rtx target, machine_mode mask_mode)
+emit_index_op (rtx dest, machine_mode mask_mode)
 {
   insn_expander<7> e;
-  machine_mode mode = GET_MODE (target);
-  e.add_output_operand (target, mode);
-  e.add_all_one_mask_operand (mask_mode);
-  e.add_vundef_operand (mode);
-  rtx vlmax = gen_reg_rtx (Pmode);
-  emit_vlmax_vsetvl (mode, vlmax);
-  e.add_input_operand (vlmax, Pmode);
-  e.add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
-  e.add_avl_type_operand (avl_type::VLMAX);
-  e.expand (code_for_pred_series (mode), false);
+  e.set_dest_and_mask (NULL, dest, mask_mode);
+
+  e.set_len_and_policy (NULL, true);
+
+  e.expand (code_for_pred_series (GET_MODE (dest)), false);
 }
 
 /* Expand series const vector.  */
@@ -324,15 +344,15 @@ expand_vec_series (rtx dest, rtx base, rtx step)
          /* Emit logical left shift operation.  */
          int shift = exact_log2 (INTVAL (step));
          rtx shift_amount = gen_int_mode (shift, Pmode);
-         rtx ops[3] = {step_adj, vid, shift_amount};
          insn_code icode = code_for_pred_scalar (ASHIFT, mode);
-         emit_binop (icode, ops, mask_mode, Pmode);
+         emit_nonvlmax_binop (icode, step_adj, vid, shift_amount,
+                              NULL, mask_mode, Pmode);
        }
       else
        {
-         rtx ops[3] = {step_adj, vid, step};
          insn_code icode = code_for_pred_scalar (MULT, mode);
-         emit_binop (icode, ops, mask_mode, inner_mode);
+         emit_nonvlmax_binop (icode, step_adj, vid, step,
+                              NULL, mask_mode, inner_mode);
        }
     }
 
@@ -346,9 +366,9 @@ expand_vec_series (rtx dest, rtx base, rtx step)
   else
     {
       rtx result = gen_reg_rtx (mode);
-      rtx ops[3] = {result, step_adj, base};
       insn_code icode = code_for_pred_scalar (PLUS, mode);
-      emit_binop (icode, ops, mask_mode, inner_mode);
+      emit_nonvlmax_binop (icode, result, step_adj, base,
+                          NULL, mask_mode, inner_mode);
       emit_move_insn (dest, result);
     }
 }
-- 
2.40.0

Reply via email to