public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
@ 2023-05-19 11:32 Robin Dapp
  2023-05-19 11:54 ` 钟居哲
  0 siblings, 1 reply; 9+ messages in thread
From: Robin Dapp @ 2023-05-19 11:32 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng, juzhe.zhong, palmer, Michael Collison,
	jeffreyalaw
  Cc: rdapp.gcc

Hi,

this patch implements autovec expanders of abs<mode>2, vneg<mode>2 and
vnot<mode>2 for integers.  I also tried to refactor the helper code
in riscv-v.cc a bit.  Guess it's not enough to warrant a separate patch
though.

Regards
 Robin 

gcc/ChangeLog:

	* config/riscv/autovec.md (<optab><mode>2): Fix typo.
	(abs<mode>2): New expander.
	* config/riscv/riscv-protos.h (emit_len_masked_op): Declare.
	(emit_len_cmp): Declare.
	(enum tail_policy): Add undefined.
	(enum mask_policy): Add undefined.
	* config/riscv/riscv-v.cc (const_vlmax_p): Fix typo.
	(emit_pred_op): Swap mask and dest.
	(emit_pred_binop): Dito.
	(emit_pred_cmp_op): Dito.
	(emit_vlmax_reg_op): Dito.
	(emit_len_masked_op): New function.
	(emit_len_cmp): New function.
	(emit_index_op): Use helper function.
	(get_prefer_tail_policy): Rename.
	(get_preferred_tail_policy): To this.
	(get_prefer_mask_policy): Rename.
	(get_preferred_mask_policy): To this.
	(slide1_sew64_helper): Dito.
	* config/riscv/riscv-vector-builtins.cc (get_tail_policy_for_pred):
	Dito.
	(get_mask_policy_for_pred): Dito.
	* config/riscv/riscv-vsetvl.cc (get_default_ta): Dito.
	(get_default_ma): Dito.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/unop/abs-run.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/abs-template.h: New test.
	* gcc.target/riscv/rvv/autovec/unop/vneg-run.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vneg-template.h: New test.
	* gcc.target/riscv/rvv/autovec/unop/vnot-run.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c: New test.
	* gcc.target/riscv/rvv/autovec/unop/vnot-template.h: New test.
---
 gcc/config/riscv/autovec.md                   |  51 +++++-
 gcc/config/riscv/riscv-protos.h               |   8 +-
 gcc/config/riscv/riscv-v.cc                   | 146 ++++++++++++++----
 gcc/config/riscv/riscv-vector-builtins.cc     |   4 +-
 gcc/config/riscv/riscv-vsetvl.cc              |   8 +-
 .../riscv/rvv/autovec/unop/abs-run.c          |  29 ++++
 .../riscv/rvv/autovec/unop/abs-rv32gcv.c      |   7 +
 .../riscv/rvv/autovec/unop/abs-rv64gcv.c      |   7 +
 .../riscv/rvv/autovec/unop/abs-template.h     |  26 ++++
 .../riscv/rvv/autovec/unop/vneg-run.c         |  29 ++++
 .../riscv/rvv/autovec/unop/vneg-rv32gcv.c     |   6 +
 .../riscv/rvv/autovec/unop/vneg-rv64gcv.c     |   6 +
 .../riscv/rvv/autovec/unop/vneg-template.h    |  17 ++
 .../riscv/rvv/autovec/unop/vnot-run.c         |  33 ++++
 .../riscv/rvv/autovec/unop/vnot-rv32gcv.c     |   6 +
 .../riscv/rvv/autovec/unop/vnot-rv64gcv.c     |   6 +
 .../riscv/rvv/autovec/unop/vnot-template.h    |  21 +++
 gcc/testsuite/gcc.target/riscv/rvv/rvv.exp    |   2 +
 18 files changed, 377 insertions(+), 35 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index ce0b46537ad..8060a5cdf90 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -161,7 +161,7 @@ (define_expand "<optab><mode>3"
 })
 
 ;; -------------------------------------------------------------------------
-;; ---- [INT] Binary shifts by scalar.
+;; ---- [INT] Binary shifts by vector.
 ;; -------------------------------------------------------------------------
 ;; Includes:
 ;; - vsll.vv/vsra.vv/vsrl.vv
@@ -180,3 +180,52 @@ (define_expand "v<optab><mode>3"
 				NULL_RTX, <VM>mode);
   DONE;
 })
+
+;; =========================================================================
+;; == Unary arithmetic
+;; =========================================================================
+
+;; -------------------------------------------------------------------------------
+;; ---- [INT] Unary operations
+;; -------------------------------------------------------------------------------
+;; Includes:
+;; - vneg.v/vnot.v
+;; -------------------------------------------------------------------------------
+(define_expand "<optab><mode>2"
+  [(set (match_operand:VI 0 "register_operand")
+    (any_int_unop:VI
+     (match_operand:VI 1 "register_operand")))]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_len_op (code_for_pred (<CODE>, <MODE>mode),
+			     operands[0], operands[1], NULL_RTX, <VM>mode);
+  DONE;
+})
+
+;; -------------------------------------------------------------------------------
+;; - ABS expansion to vmslt and vneg
+;; -------------------------------------------------------------------------------
+
+(define_expand "abs<mode>2"
+  [(set (match_operand:VI 0 "register_operand")
+    (match_operand:VI 1 "register_operand"))]
+  "TARGET_VECTOR"
+{
+  // Create a zero constant.
+  rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0));
+
+  // Compare the source vector against it.
+  rtx ltcmp = gen_rtx_LT (<VM>mode, operands[1], zero);
+
+  // Mask out all non-negative elements.
+  rtx mask = gen_reg_rtx (<VM>mode);
+  riscv_vector::emit_len_cmp (code_for_pred_ltge (<MODE>mode),
+			      mask, ltcmp, operands[1], zero,
+			      NULL_RTX, <VM>mode);
+
+  // Emit a masked vneg, negating only the negative elements.
+  riscv_vector::emit_masked_len_op (code_for_pred (NEG, <MODE>mode),
+				    mask, operands[0], operands[1],
+				    NULL_RTX, <VM>mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 12634d0ac1a..7c588086fa0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -171,6 +171,8 @@ void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
 		     machine_mode = VOIDmode);
+void emit_masked_len_op (unsigned, rtx, rtx, rtx, rtx, machine_mode);
+void emit_len_cmp (unsigned, rtx, rtx, rtx, rtx, rtx, machine_mode);
 enum vlmul_type get_vlmul (machine_mode);
 unsigned int get_ratio (machine_mode);
 unsigned int get_nf (machine_mode);
@@ -181,6 +183,7 @@ int get_avl_type (rtx);
 unsigned int calculate_ratio (unsigned int, enum vlmul_type);
 enum tail_policy
 {
+  TAIL_UNDEFINED = -1,
   TAIL_UNDISTURBED = 0,
   TAIL_AGNOSTIC = 1,
   TAIL_ANY = 2,
@@ -188,12 +191,13 @@ enum tail_policy
 
 enum mask_policy
 {
+  MASK_UNDEFINED = -1,
   MASK_UNDISTURBED = 0,
   MASK_AGNOSTIC = 1,
   MASK_ANY = 2,
 };
-enum tail_policy get_prefer_tail_policy ();
-enum mask_policy get_prefer_mask_policy ();
+enum tail_policy get_preferred_tail_policy ();
+enum mask_policy get_preferred_mask_policy ();
 rtx get_avl_type_rtx (enum avl_type);
 opt_machine_mode get_vector_mode (scalar_mode, poly_uint64);
 opt_machine_mode get_tuple_mode (machine_mode, unsigned int);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index d65e7300303..64ad3970267 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -54,11 +54,11 @@ namespace riscv_vector {
 static bool
 const_vlmax_p (machine_mode mode)
 {
-  poly_uint64 nuints = GET_MODE_NUNITS (mode);
+  poly_uint64 nunits = GET_MODE_NUNITS (mode);
 
-  return nuints.is_constant ()
+  return nunits.is_constant ()
     /* The vsetivli can only hold register 0~31.  */
-    ? (IN_RANGE (nuints.to_constant (), 0, 31))
+    ? (IN_RANGE (nunits.to_constant (), 0, 31))
     /* Only allowed in VLS-VLMAX mode.  */
     : false;
 }
@@ -66,38 +66,68 @@ const_vlmax_p (machine_mode mode)
 template <int MAX_OPERANDS> class insn_expander
 {
 public:
-  insn_expander () : m_opno (0), has_dest(false) {}
+  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);
     gcc_assert (m_opno <= MAX_OPERANDS);
   }
+
+  void add_source_operand (rtx x, machine_mode mode)
+    {
+      add_src (x);
+      add_input_operand (x, mode);
+    }
+
   void add_input_operand (rtx x, machine_mode mode)
   {
     create_input_operand (&m_ops[m_opno++], x, mode);
     gcc_assert (m_opno <= MAX_OPERANDS);
   }
+
   void add_all_one_mask_operand (machine_mode mode)
   {
     add_input_operand (CONSTM1_RTX (mode), mode);
   }
+
   void add_vundef_operand (machine_mode mode)
   {
     add_input_operand (RVV_VUNDEF (mode), mode);
   }
-  void add_policy_operand (enum tail_policy vta, enum mask_policy vma)
+
+  void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED,
+			    enum mask_policy vma = MASK_UNDEFINED)
   {
-    rtx tail_policy_rtx = gen_int_mode (vta, Pmode);
-    rtx mask_policy_rtx = gen_int_mode (vma, Pmode);
-    add_input_operand (tail_policy_rtx, Pmode);
-    add_input_operand (mask_policy_rtx, Pmode);
+    /* If no policies were specified, use the default ones.  */
+    if (vta == TAIL_UNDEFINED)
+      vta = get_preferred_tail_policy ();
+    if (vma == MASK_UNDEFINED)
+      vma = get_preferred_mask_policy ();
+
+    /* RVV Spec 3.4.3.
+       Mask destination tail elements are always treated as tail-agnostic,
+       regardless of the setting of vta.  */
+    if (!is_mask_destination_instruction ())
+      {
+	rtx tail_policy_rtx = gen_int_mode (vta, Pmode);
+	add_input_operand (tail_policy_rtx, Pmode);
+      }
+
+    /* RVV Spec 15.1.
+       Vector mask logical instructions are always unmasked.  */
+    if (!is_mask_logical_instruction ())
+      {
+	rtx mask_policy_rtx = gen_int_mode (vma, Pmode);
+	add_input_operand (mask_policy_rtx, Pmode);
+      }
   }
   void add_avl_type_operand (avl_type type)
   {
     add_input_operand (gen_int_mode (type, Pmode), Pmode);
   }
 
-  void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode)
+  void set_dest_and_mask (rtx dest, rtx mask, machine_mode mask_mode)
   {
     dest_mode = GET_MODE (dest);
     has_dest = true;
@@ -133,8 +163,7 @@ public:
 
       add_input_operand (len, Pmode);
 
-      if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
-	add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
+      add_policy_operands ();
 
       add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
     }
@@ -150,9 +179,36 @@ public:
       expand_insn (icode, m_opno, m_ops);
   }
 
+  bool is_mask_destination_instruction ()
+    {
+      gcc_assert (has_dest);
+      return (GET_MODE_CLASS (dest_mode) == MODE_VECTOR_BOOL);
+    }
+
+  bool is_mask_logical_instruction ()
+    {
+      if (!is_mask_destination_instruction ())
+	return false;
+
+      if (!srcs.length ())
+	return false;
+
+      for (rtx src : srcs)
+	if (GET_MODE_CLASS (GET_MODE (src)) != MODE_VECTOR_BOOL)
+	  return false;
+
+      return true;
+    }
+
+  void add_src (rtx src)
+    {
+      srcs.quick_push (src);
+    }
+
 private:
   int m_opno;
   bool has_dest;
+  auto_vec<rtx, 3> srcs;
   machine_mode dest_mode;
   expand_operand m_ops[MAX_OPERANDS];
 };
@@ -252,9 +308,9 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
 	      machine_mode mask_mode, bool force_vlmax = false)
 {
   insn_expander<8> e;
-  e.set_dest_and_mask (mask, dest, mask_mode);
+  e.set_dest_and_mask (dest, mask, mask_mode);
 
-  e.add_input_operand (src, GET_MODE (src));
+  e.add_source_operand (src, GET_MODE (src));
 
   e.set_len_and_policy (len, force_vlmax);
 
@@ -269,20 +325,40 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
 		 machine_mode scalar_mode = VOIDmode)
 {
   insn_expander<9> e;
-  e.set_dest_and_mask (mask, dest, mask_mode);
+  e.set_dest_and_mask (dest, mask, mask_mode);
 
   gcc_assert (VECTOR_MODE_P (GET_MODE (src1))
 	      || VECTOR_MODE_P (GET_MODE (src2)));
 
   if (VECTOR_MODE_P (GET_MODE (src1)))
-    e.add_input_operand (src1, GET_MODE (src1));
+    e.add_source_operand (src1, GET_MODE (src1));
   else
-    e.add_input_operand (src1, scalar_mode);
+    e.add_source_operand (src1, scalar_mode);
 
   if (VECTOR_MODE_P (GET_MODE (src2)))
-    e.add_input_operand (src2, GET_MODE (src2));
+    e.add_source_operand (src2, GET_MODE (src2));
   else
-    e.add_input_operand (src2, scalar_mode);
+    e.add_source_operand (src2, scalar_mode);
+
+  e.set_len_and_policy (len);
+
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
+}
+
+/* Emit an RVV comparison.  */
+static void
+emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp,
+	       rtx src1, rtx src2,
+	       rtx len, machine_mode mask_mode)
+{
+  insn_expander<9> e;
+
+  e.set_dest_and_mask (dest, mask, mask_mode);
+
+  e.add_input_operand (cmp, GET_MODE (cmp));
+
+  e.add_source_operand (src1, GET_MODE (src1));
+  e.add_source_operand (src2, GET_MODE (src2));
 
   e.set_len_and_policy (len);
 
@@ -332,6 +408,8 @@ emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
 		/* Force VLMAX */ true);
 }
 
+/* Emit a binary operation with sources SRC1 and SRC2 and a given length
+   LEN.  */
 void
 emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
 		machine_mode mask_mode, machine_mode scalar_mode)
@@ -340,13 +418,29 @@ emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
 		   mask_mode, scalar_mode);
 }
 
+/* Emit a masked operation with a given length LEN.  */
+void
+emit_masked_len_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
+		    machine_mode mask_mode)
+{
+  emit_pred_op (icode, mask, dest, src, len, mask_mode);
+}
+
+/* Emit an unmasked comparison whose result is stored in the mask DEST.  */
+void
+emit_len_cmp (unsigned icode, rtx dest, rtx op, rtx src1, rtx src2,
+	      rtx len, machine_mode mask_mode)
+{
+  emit_pred_cmp (icode, NULL_RTX, dest, op, src1, src2, len, mask_mode);
+}
+
 /* Emit vid.v instruction.  */
 
 static void
 emit_index_op (rtx dest, machine_mode mask_mode)
 {
   insn_expander<7> e;
-  e.set_dest_and_mask (NULL, dest, mask_mode);
+  e.set_dest_and_mask (dest, NULL, mask_mode);
 
   e.set_len_and_policy (NULL, true);
 
@@ -621,9 +715,9 @@ get_ma (rtx ma)
   return INTVAL (ma);
 }
 
-/* Get prefer tail policy.  */
+/* Get preferred tail policy.  */
 enum tail_policy
-get_prefer_tail_policy ()
+get_preferred_tail_policy ()
 {
   /* TODO: By default, we choose to use TAIL_ANY which allows
      compiler pick up either agnostic or undisturbed. Maybe we
@@ -632,9 +726,9 @@ get_prefer_tail_policy ()
   return TAIL_ANY;
 }
 
-/* Get prefer mask policy.  */
+/* Get preferred mask policy.  */
 enum mask_policy
-get_prefer_mask_policy ()
+get_preferred_mask_policy ()
 {
   /* TODO: By default, we choose to use MASK_ANY which allows
      compiler pick up either agnostic or undisturbed. Maybe we
@@ -935,8 +1029,8 @@ slide1_sew64_helper (int unspec, machine_mode mode, machine_mode demote_mode,
     }
 
   rtx temp = gen_reg_rtx (demote_mode);
-  rtx ta = gen_int_mode (get_prefer_tail_policy (), Pmode);
-  rtx ma = gen_int_mode (get_prefer_mask_policy (), Pmode);
+  rtx ta = gen_int_mode (get_preferred_tail_policy (), Pmode);
+  rtx ma = gen_int_mode (get_preferred_mask_policy (), Pmode);
   rtx merge = RVV_VUNDEF (demote_mode);
   /* Handle vslide1<ud>_tu.  */
   if (register_operand (ops[2], mode)
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index dd714bfcee2..0487827e65e 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -2743,7 +2743,7 @@ get_tail_policy_for_pred (enum predication_type_index pred)
 {
   if (pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu)
     return gen_int_mode (TAIL_UNDISTURBED, Pmode);
-  return gen_int_mode (get_prefer_tail_policy (), Pmode);
+  return gen_int_mode (get_preferred_tail_policy (), Pmode);
 }
 
 /* Get MASK policy for predication. If predication indicates MU, return the MU.
@@ -2753,7 +2753,7 @@ get_mask_policy_for_pred (enum predication_type_index pred)
 {
   if (pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu)
     return gen_int_mode (MASK_UNDISTURBED, Pmode);
-  return gen_int_mode (get_prefer_mask_policy (), Pmode);
+  return gen_int_mode (get_preferred_mask_policy (), Pmode);
 }
 
 tree
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 9847d649d1d..0ecd0bfa2ea 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -566,8 +566,8 @@ get_default_ta ()
 {
   /* For the instruction that doesn't require TA, we still need a default value
      to emit vsetvl. We pick up the default value according to prefer policy. */
-  return (bool) (get_prefer_tail_policy () & 0x1
-		 || (get_prefer_tail_policy () >> 1 & 0x1));
+  return (bool) (get_preferred_tail_policy () & 0x1
+		 || (get_preferred_tail_policy () >> 1 & 0x1));
 }
 
 /* Get default mask policy.  */
@@ -576,8 +576,8 @@ get_default_ma ()
 {
   /* For the instruction that doesn't require MA, we still need a default value
      to emit vsetvl. We pick up the default value according to prefer policy. */
-  return (bool) (get_prefer_mask_policy () & 0x1
-		 || (get_prefer_mask_policy () >> 1 & 0x1));
+  return (bool) (get_preferred_mask_policy () & 0x1
+		 || (get_preferred_mask_policy () >> 1 & 0x1));
 }
 
 /* Helper function to get TA operand.  */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
new file mode 100644
index 00000000000..d6aaa785055
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE)				\
+  TYPE a##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = i - 127;             		\
+  }                             		\
+  vabs_##TYPE (a##TYPE, a##TYPE, SZ);	        \
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == abs (i - 127));       \
+
+#define RUN_ALL()	                        \
+ RUN(int8_t)	                                \
+ RUN(int16_t)	                                \
+ RUN(int32_t)	                                \
+ RUN(int64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
new file mode 100644
index 00000000000..cbe0ba0b0ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
new file mode 100644
index 00000000000..c0c52176a42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
new file mode 100644
index 00000000000..a54238c8ff2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) 				\
+  __attribute__((noipa))				\
+  void vabs_##TYPE (TYPE *dst, TYPE *a, int n)	\
+  {							\
+    for (int i = 0; i < n; i++)				\
+      dst[i] = abs (a[i]);				\
+  }
+
+#define TEST_TYPE2(TYPE) 				\
+  __attribute__((noipa))				\
+  void vabs_##TYPE (TYPE *dst, TYPE *a, int n)	\
+  {							\
+    for (int i = 0; i < n; i++)				\
+      dst[i] = llabs (a[i]);				\
+  }
+
+#define TEST_ALL()	\
+ TEST_TYPE(int8_t)	\
+ TEST_TYPE(int16_t)	\
+ TEST_TYPE(int32_t)	\
+ TEST_TYPE2(int64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
new file mode 100644
index 00000000000..abeb50f21ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE)				\
+  TYPE a##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = i - 127;             		\
+  }                             		\
+  vneg_##TYPE (a##TYPE, a##TYPE, SZ);	\
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == -(i - 127));
+
+#define RUN_ALL()	                        \
+ RUN(int8_t)	                                \
+ RUN(int16_t)	                                \
+ RUN(int32_t)	                                \
+ RUN(int64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
new file mode 100644
index 00000000000..69d9ebb0953
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
new file mode 100644
index 00000000000..d2c2e17c13e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
new file mode 100644
index 00000000000..72701fceb8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
@@ -0,0 +1,17 @@
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) 				\
+  __attribute__((noipa))				\
+  void vneg_##TYPE (TYPE *dst, TYPE *a, int n)		\
+  {							\
+    for (int i = 0; i < n; i++)				\
+      dst[i] =  -a[i];					\
+  }
+
+#define TEST_ALL()	\
+ TEST_TYPE(int8_t)	\
+ TEST_TYPE(int16_t)	\
+ TEST_TYPE(int32_t)	\
+ TEST_TYPE(int64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
new file mode 100644
index 00000000000..1c6836742cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE)				\
+  TYPE a##TYPE[SZ];				\
+  for (int i = 0; i < SZ; i++)			\
+  {                             		\
+    a##TYPE[i] = i - 127;             		\
+  }                             		\
+  vnot_##TYPE (a##TYPE, a##TYPE, SZ);	        \
+  for (int i = 0; i < SZ; i++)			\
+    assert (a##TYPE[i] == (TYPE)~(i - 127));
+
+#define RUN_ALL()	                        \
+ RUN(int8_t)	                                \
+ RUN(int16_t)	                                \
+ RUN(int32_t)	                                \
+ RUN(int64_t)	                                \
+ RUN(uint8_t)	                                \
+ RUN(uint16_t)	                                \
+ RUN(uint32_t)	                                \
+ RUN(uint64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
new file mode 100644
index 00000000000..ecc4316bd4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
new file mode 100644
index 00000000000..67e28af2cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h
new file mode 100644
index 00000000000..19c78d6e49b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h
@@ -0,0 +1,21 @@
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) 				\
+  __attribute__((noipa))				\
+  void vnot_##TYPE (TYPE *dst, TYPE *a, int n)		\
+  {							\
+    for (int i = 0; i < n; i++)				\
+      dst[i] =  ~a[i];					\
+  }
+
+#define TEST_ALL()	\
+ TEST_TYPE(int8_t)	\
+ TEST_TYPE(uint8_t)	\
+ TEST_TYPE(int16_t)	\
+ TEST_TYPE(uint16_t)	\
+ TEST_TYPE(int32_t)	\
+ TEST_TYPE(uint32_t)	\
+ TEST_TYPE(int64_t)	\
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
index bc99cc0c3cf..54e35cb6c62 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -63,6 +63,8 @@ foreach op $AUTOVEC_TEST_OPTS {
     "" "$op"
   dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/binop/*.\[cS\]]] \
     "" "$op"
+  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \
+    "" "$op"
 }
 
 # VLS-VLMAX tests
-- 
2.40.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-19 11:32 [PATCH] RISC-V: Implement autovec abs, vneg, vnot Robin Dapp
@ 2023-05-19 11:54 ` 钟居哲
  2023-05-19 12:07   ` Robin Dapp
  0 siblings, 1 reply; 9+ messages in thread
From: 钟居哲 @ 2023-05-19 11:54 UTC (permalink / raw)
  To: rdapp.gcc, gcc-patches, kito.cheng, palmer, Michael Collison, Jeff Law
  Cc: rdapp.gcc

[-- Attachment #1: Type: text/plain, Size: 34385 bytes --]

>> +  TAIL_UNDEFINED = -1,
>> +  MASK_UNDEFINED = -1,
Why you add this ?

>> +  void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED,
>> +     enum mask_policy vma = MASK_UNDEFINED)
No, you should just specify this as TAIL_ANY or MASK_ANY as default value.

>>const_vlmax_p (machine_mode mode)
>>{
>>-  poly_uint64 nuints = GET_MODE_NUNITS (mode);
>>+  poly_uint64 nunits = GET_MODE_NUNITS (mode);
>>-  return nuints.is_constant ()
>>+  return nunits.is_constant ()
>>     /* The vsetivli can only hold register 0~31.  */
>>-    ? (IN_RANGE (nuints.to_constant (), 0, 31))
>>+    ? (IN_RANGE (nunits.to_constant (), 0, 31))
>>     /* Only allowed in VLS-VLMAX mode.  */
>>     : false;
>>}
Meaningless change ?

>>    /* For the instruction that doesn't require TA, we still need a default value
>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>    -  return (bool) (get_prefer_tail_policy () & 0x1
>>    - || (get_prefer_tail_policy () >> 1 & 0x1));
>>    +  return (bool) (get_preferred_tail_policy () & 0x1
>>    + || (get_preferred_tail_policy () >> 1 & 0x1));
>>    }
>>    /* Get default mask policy.  */
>>    @@ -576,8 +576,8 @@ get_default_ma ()
>>    {
>>       /* For the instruction that doesn't require MA, we still need a default value
>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>    -  return (bool) (get_prefer_mask_policy () & 0x1
>>    - || (get_prefer_mask_policy () >> 1 & 0x1));
>>    +  return (bool) (get_preferred_mask_policy () & 0x1
>>    + || (get_preferred_mask_policy () >> 1 & 0x1));
Why you change it ?

>>   +/* Emit an RVV comparison.  */
>>   +static void
>>   +emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp,
>>   +        rtx src1, rtx src2,
>>   +        rtx len, machine_mode mask_mode)
>>   +{
>>   +  insn_expander<9> e;
>>   +
>>   +  e.set_dest_and_mask (dest, mask, mask_mode);
>>   +
>>   +  e.add_input_operand (cmp, GET_MODE (cmp));
>>   +
>>   +  e.add_source_operand (src1, GET_MODE (src1));
>>   +  e.add_source_operand (src2, GET_MODE (src2));

You are using comparison helper which I added one in my downstream 
when I am working on comparison autovec patterns:

I think you can normalize my code with yours:

/* Emit an RVV comparison.  If one of SRC1 and SRC2 is a scalar operand, its
   data_mode is specified using SCALAR_MODE.  */
static void
emit_pred_comparison (unsigned icode, rtx_code rcode, rtx mask, rtx dest,
          rtx src1, rtx src2, rtx len, machine_mode mask_mode,
          machine_mode scalar_mode = VOIDmode)
{
  insn_expander<9> e;
  e.set_dest_and_mask (mask, dest, mask_mode);
  machine_mode data_mode = GET_MODE (src1);

  gcc_assert (VECTOR_MODE_P (GET_MODE (src1))
        || VECTOR_MODE_P (GET_MODE (src2)));

  if (!insn_operand_matches ((enum insn_code) icode, e.opno () + 1, src1))
    src1 = force_reg (data_mode, src1);
  if (!insn_operand_matches ((enum insn_code) icode, e.opno () + 2, src2))
    {
      if (VECTOR_MODE_P (GET_MODE (src2)))
  src2 = force_reg (data_mode, src2);
      else
  src2 = force_reg (scalar_mode, src2);
    }
  rtx comparison = gen_rtx_fmt_ee (rcode, mask_mode, src1, src2);
  if (!VECTOR_MODE_P (GET_MODE (src2)))
    comparison = gen_rtx_fmt_ee (rcode, mask_mode, src1,
         gen_rtx_VEC_DUPLICATE (data_mode, src2));
  e.add_fixed_operand (comparison);

  e.add_fixed_operand (src1);
  if (CONST_INT_P (src2))
    e.add_integer_operand (src2);
  else
    e.add_fixed_operand (src2);

  e.set_len_and_policy (len, true, false, true);

  e.expand ((enum insn_code) icode, false);
}

static void
emit_len_comparison (unsigned icode, rtx_code rcode, rtx dest, rtx src1,
         rtx src2, rtx len, machine_mode mask_mode,
         machine_mode scalar_mode)
{
  emit_pred_comparison (icode, rcode, NULL_RTX, dest, src1, src2, len,
      mask_mode, scalar_mode);
}

/* Expand an RVV integer comparison using the RVV equivalent of:

     (set TARGET (CODE OP0 OP1)).  */

void
expand_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1)
{
  machine_mode mask_mode = GET_MODE (target);
  machine_mode data_mode = GET_MODE (op0);
  insn_code icode;
  bool scalar_p = false;

  if (CONST_VECTOR_P (op1))
    {
      rtx elt;
      if (const_vec_duplicate_p (op1, &elt))
  op1 = elt;
      scalar_p = true;
    }

  switch (code)
    {
    case LE:
    case LEU:
    case GT:
    case GTU:
      if (scalar_p)
  icode = code_for_pred_cmp_scalar (data_mode);
      else
  icode = code_for_pred_cmp (data_mode);
      break;
    case EQ:
    case NE:
      if (scalar_p)
  icode = code_for_pred_eqne_scalar (data_mode);
      else
  icode = code_for_pred_cmp (data_mode);
      break;
    case LT:
    case LTU:
      if (scalar_p)
  icode = code_for_pred_cmp_scalar (data_mode);
      else
  icode = code_for_pred_ltge (data_mode);
      break;
    case GE:
    case GEU:
      if (scalar_p)
  icode = code_for_pred_ge_scalar (data_mode);
      else
  icode = code_for_pred_ltge (data_mode);
      break;
    default:
      break;
    }
  emit_len_comparison (icode, code, target, op0, op1, NULL, mask_mode,
           GET_MODE_INNER (data_mode));
}


This is how I use it:
(define_expand "vec_cmp<mode><vm>"
  [(set (match_operand:<VM> 0 "register_operand")
  (match_operator:<VM> 1 "comparison_operator"
    [(match_operand:VI 2 "register_operand")
     (match_operand:VI 3 "nonmemory_operand")]))]
  "TARGET_VECTOR"
  {
    riscv_vector::expand_vec_cmp_int (operands[0], GET_CODE (operands[1]),
              operands[2], operands[3]);
    DONE;
  }
)

I am almost done all comparison autovec patterns, soon will send them after testing.

Thanks.


juzhe.zhong@rivai.ai
 
From: Robin Dapp
Date: 2023-05-19 19:32
To: gcc-patches; Kito Cheng; juzhe.zhong@rivai.ai; palmer; Michael Collison; jeffreyalaw
CC: rdapp.gcc
Subject: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
Hi,
 
this patch implements autovec expanders of abs<mode>2, vneg<mode>2 and
vnot<mode>2 for integers.  I also tried to refactor the helper code
in riscv-v.cc a bit.  Guess it's not enough to warrant a separate patch
though.
 
Regards
Robin 
 
gcc/ChangeLog:
 
* config/riscv/autovec.md (<optab><mode>2): Fix typo.
(abs<mode>2): New expander.
* config/riscv/riscv-protos.h (emit_len_masked_op): Declare.
(emit_len_cmp): Declare.
(enum tail_policy): Add undefined.
(enum mask_policy): Add undefined.
* config/riscv/riscv-v.cc (const_vlmax_p): Fix typo.
(emit_pred_op): Swap mask and dest.
(emit_pred_binop): Dito.
(emit_pred_cmp_op): Dito.
(emit_vlmax_reg_op): Dito.
(emit_len_masked_op): New function.
(emit_len_cmp): New function.
(emit_index_op): Use helper function.
(get_prefer_tail_policy): Rename.
(get_preferred_tail_policy): To this.
(get_prefer_mask_policy): Rename.
(get_preferred_mask_policy): To this.
(slide1_sew64_helper): Dito.
* config/riscv/riscv-vector-builtins.cc (get_tail_policy_for_pred):
Dito.
(get_mask_policy_for_pred): Dito.
* config/riscv/riscv-vsetvl.cc (get_default_ta): Dito.
(get_default_ma): Dito.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/autovec/unop/abs-run.c: New test.
* gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/abs-template.h: New test.
* gcc.target/riscv/rvv/autovec/unop/vneg-run.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vneg-template.h: New test.
* gcc.target/riscv/rvv/autovec/unop/vnot-run.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c: New test.
* gcc.target/riscv/rvv/autovec/unop/vnot-template.h: New test.
---
gcc/config/riscv/autovec.md                   |  51 +++++-
gcc/config/riscv/riscv-protos.h               |   8 +-
gcc/config/riscv/riscv-v.cc                   | 146 ++++++++++++++----
gcc/config/riscv/riscv-vector-builtins.cc     |   4 +-
gcc/config/riscv/riscv-vsetvl.cc              |   8 +-
.../riscv/rvv/autovec/unop/abs-run.c          |  29 ++++
.../riscv/rvv/autovec/unop/abs-rv32gcv.c      |   7 +
.../riscv/rvv/autovec/unop/abs-rv64gcv.c      |   7 +
.../riscv/rvv/autovec/unop/abs-template.h     |  26 ++++
.../riscv/rvv/autovec/unop/vneg-run.c         |  29 ++++
.../riscv/rvv/autovec/unop/vneg-rv32gcv.c     |   6 +
.../riscv/rvv/autovec/unop/vneg-rv64gcv.c     |   6 +
.../riscv/rvv/autovec/unop/vneg-template.h    |  17 ++
.../riscv/rvv/autovec/unop/vnot-run.c         |  33 ++++
.../riscv/rvv/autovec/unop/vnot-rv32gcv.c     |   6 +
.../riscv/rvv/autovec/unop/vnot-rv64gcv.c     |   6 +
.../riscv/rvv/autovec/unop/vnot-template.h    |  21 +++
gcc/testsuite/gcc.target/riscv/rvv/rvv.exp    |   2 +
18 files changed, 377 insertions(+), 35 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h
 
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index ce0b46537ad..8060a5cdf90 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -161,7 +161,7 @@ (define_expand "<optab><mode>3"
})
;; -------------------------------------------------------------------------
-;; ---- [INT] Binary shifts by scalar.
+;; ---- [INT] Binary shifts by vector.
;; -------------------------------------------------------------------------
;; Includes:
;; - vsll.vv/vsra.vv/vsrl.vv
@@ -180,3 +180,52 @@ (define_expand "v<optab><mode>3"
NULL_RTX, <VM>mode);
   DONE;
})
+
+;; =========================================================================
+;; == Unary arithmetic
+;; =========================================================================
+
+;; -------------------------------------------------------------------------------
+;; ---- [INT] Unary operations
+;; -------------------------------------------------------------------------------
+;; Includes:
+;; - vneg.v/vnot.v
+;; -------------------------------------------------------------------------------
+(define_expand "<optab><mode>2"
+  [(set (match_operand:VI 0 "register_operand")
+    (any_int_unop:VI
+     (match_operand:VI 1 "register_operand")))]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_len_op (code_for_pred (<CODE>, <MODE>mode),
+      operands[0], operands[1], NULL_RTX, <VM>mode);
+  DONE;
+})
+
+;; -------------------------------------------------------------------------------
+;; - ABS expansion to vmslt and vneg
+;; -------------------------------------------------------------------------------
+
+(define_expand "abs<mode>2"
+  [(set (match_operand:VI 0 "register_operand")
+    (match_operand:VI 1 "register_operand"))]
+  "TARGET_VECTOR"
+{
+  // Create a zero constant.
+  rtx zero = gen_const_vec_duplicate (<MODE>mode, GEN_INT (0));
+
+  // Compare the source vector against it.
+  rtx ltcmp = gen_rtx_LT (<VM>mode, operands[1], zero);
+
+  // Mask out all non-negative elements.
+  rtx mask = gen_reg_rtx (<VM>mode);
+  riscv_vector::emit_len_cmp (code_for_pred_ltge (<MODE>mode),
+       mask, ltcmp, operands[1], zero,
+       NULL_RTX, <VM>mode);
+
+  // Emit a masked vneg, negating only the negative elements.
+  riscv_vector::emit_masked_len_op (code_for_pred (NEG, <MODE>mode),
+     mask, operands[0], operands[1],
+     NULL_RTX, <VM>mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 12634d0ac1a..7c588086fa0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -171,6 +171,8 @@ void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
     machine_mode = VOIDmode);
+void emit_masked_len_op (unsigned, rtx, rtx, rtx, rtx, machine_mode);
+void emit_len_cmp (unsigned, rtx, rtx, rtx, rtx, rtx, machine_mode);
enum vlmul_type get_vlmul (machine_mode);
unsigned int get_ratio (machine_mode);
unsigned int get_nf (machine_mode);
@@ -181,6 +183,7 @@ int get_avl_type (rtx);
unsigned int calculate_ratio (unsigned int, enum vlmul_type);
enum tail_policy
{
+  TAIL_UNDEFINED = -1,
   TAIL_UNDISTURBED = 0,
   TAIL_AGNOSTIC = 1,
   TAIL_ANY = 2,
@@ -188,12 +191,13 @@ enum tail_policy
enum mask_policy
{
+  MASK_UNDEFINED = -1,
   MASK_UNDISTURBED = 0,
   MASK_AGNOSTIC = 1,
   MASK_ANY = 2,
};
-enum tail_policy get_prefer_tail_policy ();
-enum mask_policy get_prefer_mask_policy ();
+enum tail_policy get_preferred_tail_policy ();
+enum mask_policy get_preferred_mask_policy ();
rtx get_avl_type_rtx (enum avl_type);
opt_machine_mode get_vector_mode (scalar_mode, poly_uint64);
opt_machine_mode get_tuple_mode (machine_mode, unsigned int);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index d65e7300303..64ad3970267 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -54,11 +54,11 @@ namespace riscv_vector {
static bool
const_vlmax_p (machine_mode mode)
{
-  poly_uint64 nuints = GET_MODE_NUNITS (mode);
+  poly_uint64 nunits = GET_MODE_NUNITS (mode);
-  return nuints.is_constant ()
+  return nunits.is_constant ()
     /* The vsetivli can only hold register 0~31.  */
-    ? (IN_RANGE (nuints.to_constant (), 0, 31))
+    ? (IN_RANGE (nunits.to_constant (), 0, 31))
     /* Only allowed in VLS-VLMAX mode.  */
     : false;
}
@@ -66,38 +66,68 @@ const_vlmax_p (machine_mode mode)
template <int MAX_OPERANDS> class insn_expander
{
public:
-  insn_expander () : m_opno (0), has_dest(false) {}
+  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);
     gcc_assert (m_opno <= MAX_OPERANDS);
   }
+
+  void add_source_operand (rtx x, machine_mode mode)
+    {
+      add_src (x);
+      add_input_operand (x, mode);
+    }
+
   void add_input_operand (rtx x, machine_mode mode)
   {
     create_input_operand (&m_ops[m_opno++], x, mode);
     gcc_assert (m_opno <= MAX_OPERANDS);
   }
+
   void add_all_one_mask_operand (machine_mode mode)
   {
     add_input_operand (CONSTM1_RTX (mode), mode);
   }
+
   void add_vundef_operand (machine_mode mode)
   {
     add_input_operand (RVV_VUNDEF (mode), mode);
   }
-  void add_policy_operand (enum tail_policy vta, enum mask_policy vma)
+
+  void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED,
+     enum mask_policy vma = MASK_UNDEFINED)
   {
-    rtx tail_policy_rtx = gen_int_mode (vta, Pmode);
-    rtx mask_policy_rtx = gen_int_mode (vma, Pmode);
-    add_input_operand (tail_policy_rtx, Pmode);
-    add_input_operand (mask_policy_rtx, Pmode);
+    /* If no policies were specified, use the default ones.  */
+    if (vta == TAIL_UNDEFINED)
+      vta = get_preferred_tail_policy ();
+    if (vma == MASK_UNDEFINED)
+      vma = get_preferred_mask_policy ();
+
+    /* RVV Spec 3.4.3.
+       Mask destination tail elements are always treated as tail-agnostic,
+       regardless of the setting of vta.  */
+    if (!is_mask_destination_instruction ())
+      {
+ rtx tail_policy_rtx = gen_int_mode (vta, Pmode);
+ add_input_operand (tail_policy_rtx, Pmode);
+      }
+
+    /* RVV Spec 15.1.
+       Vector mask logical instructions are always unmasked.  */
+    if (!is_mask_logical_instruction ())
+      {
+ rtx mask_policy_rtx = gen_int_mode (vma, Pmode);
+ add_input_operand (mask_policy_rtx, Pmode);
+      }
   }
   void add_avl_type_operand (avl_type type)
   {
     add_input_operand (gen_int_mode (type, Pmode), Pmode);
   }
-  void set_dest_and_mask (rtx mask, rtx dest, machine_mode mask_mode)
+  void set_dest_and_mask (rtx dest, rtx mask, machine_mode mask_mode)
   {
     dest_mode = GET_MODE (dest);
     has_dest = true;
@@ -133,8 +163,7 @@ public:
       add_input_operand (len, Pmode);
-      if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
- add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
+      add_policy_operands ();
       add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
     }
@@ -150,9 +179,36 @@ public:
       expand_insn (icode, m_opno, m_ops);
   }
+  bool is_mask_destination_instruction ()
+    {
+      gcc_assert (has_dest);
+      return (GET_MODE_CLASS (dest_mode) == MODE_VECTOR_BOOL);
+    }
+
+  bool is_mask_logical_instruction ()
+    {
+      if (!is_mask_destination_instruction ())
+ return false;
+
+      if (!srcs.length ())
+ return false;
+
+      for (rtx src : srcs)
+ if (GET_MODE_CLASS (GET_MODE (src)) != MODE_VECTOR_BOOL)
+   return false;
+
+      return true;
+    }
+
+  void add_src (rtx src)
+    {
+      srcs.quick_push (src);
+    }
+
private:
   int m_opno;
   bool has_dest;
+  auto_vec<rtx, 3> srcs;
   machine_mode dest_mode;
   expand_operand m_ops[MAX_OPERANDS];
};
@@ -252,9 +308,9 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
      machine_mode mask_mode, bool force_vlmax = false)
{
   insn_expander<8> e;
-  e.set_dest_and_mask (mask, dest, mask_mode);
+  e.set_dest_and_mask (dest, mask, mask_mode);
-  e.add_input_operand (src, GET_MODE (src));
+  e.add_source_operand (src, GET_MODE (src));
   e.set_len_and_policy (len, force_vlmax);
@@ -269,20 +325,40 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
machine_mode scalar_mode = VOIDmode)
{
   insn_expander<9> e;
-  e.set_dest_and_mask (mask, dest, mask_mode);
+  e.set_dest_and_mask (dest, mask, mask_mode);
   gcc_assert (VECTOR_MODE_P (GET_MODE (src1))
      || VECTOR_MODE_P (GET_MODE (src2)));
   if (VECTOR_MODE_P (GET_MODE (src1)))
-    e.add_input_operand (src1, GET_MODE (src1));
+    e.add_source_operand (src1, GET_MODE (src1));
   else
-    e.add_input_operand (src1, scalar_mode);
+    e.add_source_operand (src1, scalar_mode);
   if (VECTOR_MODE_P (GET_MODE (src2)))
-    e.add_input_operand (src2, GET_MODE (src2));
+    e.add_source_operand (src2, GET_MODE (src2));
   else
-    e.add_input_operand (src2, scalar_mode);
+    e.add_source_operand (src2, scalar_mode);
+
+  e.set_len_and_policy (len);
+
+  e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
+}
+
+/* Emit an RVV comparison.  */
+static void
+emit_pred_cmp (unsigned icode, rtx mask, rtx dest, rtx cmp,
+        rtx src1, rtx src2,
+        rtx len, machine_mode mask_mode)
+{
+  insn_expander<9> e;
+
+  e.set_dest_and_mask (dest, mask, mask_mode);
+
+  e.add_input_operand (cmp, GET_MODE (cmp));
+
+  e.add_source_operand (src1, GET_MODE (src1));
+  e.add_source_operand (src2, GET_MODE (src2));
   e.set_len_and_policy (len);
@@ -332,6 +408,8 @@ emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
/* Force VLMAX */ true);
}
+/* Emit a binary operation with sources SRC1 and SRC2 and a given length
+   LEN.  */
void
emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
machine_mode mask_mode, machine_mode scalar_mode)
@@ -340,13 +418,29 @@ emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
   mask_mode, scalar_mode);
}
+/* Emit a masked operation with a given length LEN.  */
+void
+emit_masked_len_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
+     machine_mode mask_mode)
+{
+  emit_pred_op (icode, mask, dest, src, len, mask_mode);
+}
+
+/* Emit an unmasked comparison whose result is stored in the mask DEST.  */
+void
+emit_len_cmp (unsigned icode, rtx dest, rtx op, rtx src1, rtx src2,
+       rtx len, machine_mode mask_mode)
+{
+  emit_pred_cmp (icode, NULL_RTX, dest, op, src1, src2, len, mask_mode);
+}
+
/* Emit vid.v instruction.  */
static void
emit_index_op (rtx dest, machine_mode mask_mode)
{
   insn_expander<7> e;
-  e.set_dest_and_mask (NULL, dest, mask_mode);
+  e.set_dest_and_mask (dest, NULL, mask_mode);
   e.set_len_and_policy (NULL, true);
@@ -621,9 +715,9 @@ get_ma (rtx ma)
   return INTVAL (ma);
}
-/* Get prefer tail policy.  */
+/* Get preferred tail policy.  */
enum tail_policy
-get_prefer_tail_policy ()
+get_preferred_tail_policy ()
{
   /* TODO: By default, we choose to use TAIL_ANY which allows
      compiler pick up either agnostic or undisturbed. Maybe we
@@ -632,9 +726,9 @@ get_prefer_tail_policy ()
   return TAIL_ANY;
}
-/* Get prefer mask policy.  */
+/* Get preferred mask policy.  */
enum mask_policy
-get_prefer_mask_policy ()
+get_preferred_mask_policy ()
{
   /* TODO: By default, we choose to use MASK_ANY which allows
      compiler pick up either agnostic or undisturbed. Maybe we
@@ -935,8 +1029,8 @@ slide1_sew64_helper (int unspec, machine_mode mode, machine_mode demote_mode,
     }
   rtx temp = gen_reg_rtx (demote_mode);
-  rtx ta = gen_int_mode (get_prefer_tail_policy (), Pmode);
-  rtx ma = gen_int_mode (get_prefer_mask_policy (), Pmode);
+  rtx ta = gen_int_mode (get_preferred_tail_policy (), Pmode);
+  rtx ma = gen_int_mode (get_preferred_mask_policy (), Pmode);
   rtx merge = RVV_VUNDEF (demote_mode);
   /* Handle vslide1<ud>_tu.  */
   if (register_operand (ops[2], mode)
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index dd714bfcee2..0487827e65e 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -2743,7 +2743,7 @@ get_tail_policy_for_pred (enum predication_type_index pred)
{
   if (pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu)
     return gen_int_mode (TAIL_UNDISTURBED, Pmode);
-  return gen_int_mode (get_prefer_tail_policy (), Pmode);
+  return gen_int_mode (get_preferred_tail_policy (), Pmode);
}
/* Get MASK policy for predication. If predication indicates MU, return the MU.
@@ -2753,7 +2753,7 @@ get_mask_policy_for_pred (enum predication_type_index pred)
{
   if (pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu)
     return gen_int_mode (MASK_UNDISTURBED, Pmode);
-  return gen_int_mode (get_prefer_mask_policy (), Pmode);
+  return gen_int_mode (get_preferred_mask_policy (), Pmode);
}
tree
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 9847d649d1d..0ecd0bfa2ea 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -566,8 +566,8 @@ get_default_ta ()
{
   /* For the instruction that doesn't require TA, we still need a default value
      to emit vsetvl. We pick up the default value according to prefer policy. */
-  return (bool) (get_prefer_tail_policy () & 0x1
- || (get_prefer_tail_policy () >> 1 & 0x1));
+  return (bool) (get_preferred_tail_policy () & 0x1
+ || (get_preferred_tail_policy () >> 1 & 0x1));
}
/* Get default mask policy.  */
@@ -576,8 +576,8 @@ get_default_ma ()
{
   /* For the instruction that doesn't require MA, we still need a default value
      to emit vsetvl. We pick up the default value according to prefer policy. */
-  return (bool) (get_prefer_mask_policy () & 0x1
- || (get_prefer_mask_policy () >> 1 & 0x1));
+  return (bool) (get_preferred_mask_policy () & 0x1
+ || (get_preferred_mask_policy () >> 1 & 0x1));
}
/* Helper function to get TA operand.  */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
new file mode 100644
index 00000000000..d6aaa785055
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-run.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE) \
+  TYPE a##TYPE[SZ]; \
+  for (int i = 0; i < SZ; i++) \
+  {                             \
+    a##TYPE[i] = i - 127;             \
+  }                             \
+  vabs_##TYPE (a##TYPE, a##TYPE, SZ);         \
+  for (int i = 0; i < SZ; i++) \
+    assert (a##TYPE[i] == abs (i - 127));       \
+
+#define RUN_ALL()                         \
+ RUN(int8_t)                                 \
+ RUN(int16_t)                                 \
+ RUN(int32_t)                                 \
+ RUN(int64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
new file mode 100644
index 00000000000..cbe0ba0b0ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv32gcv.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
new file mode 100644
index 00000000000..c0c52176a42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-rv64gcv.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "abs-template.h"
+
+/* { dg-final { scan-assembler-times {\tvmslt\.vi} 4 } } */
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
new file mode 100644
index 00000000000..a54238c8ff2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/abs-template.h
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) \
+  __attribute__((noipa)) \
+  void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \
+  { \
+    for (int i = 0; i < n; i++) \
+      dst[i] = abs (a[i]); \
+  }
+
+#define TEST_TYPE2(TYPE) \
+  __attribute__((noipa)) \
+  void vabs_##TYPE (TYPE *dst, TYPE *a, int n) \
+  { \
+    for (int i = 0; i < n; i++) \
+      dst[i] = llabs (a[i]); \
+  }
+
+#define TEST_ALL() \
+ TEST_TYPE(int8_t) \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE2(int64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
new file mode 100644
index 00000000000..abeb50f21ea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-run.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE) \
+  TYPE a##TYPE[SZ]; \
+  for (int i = 0; i < SZ; i++) \
+  {                             \
+    a##TYPE[i] = i - 127;             \
+  }                             \
+  vneg_##TYPE (a##TYPE, a##TYPE, SZ); \
+  for (int i = 0; i < SZ; i++) \
+    assert (a##TYPE[i] == -(i - 127));
+
+#define RUN_ALL()                         \
+ RUN(int8_t)                                 \
+ RUN(int16_t)                                 \
+ RUN(int32_t)                                 \
+ RUN(int64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
new file mode 100644
index 00000000000..69d9ebb0953
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv32gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
new file mode 100644
index 00000000000..d2c2e17c13e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-rv64gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vneg-template.h"
+
+/* { dg-final { scan-assembler-times {\tvneg\.v} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
new file mode 100644
index 00000000000..72701fceb8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vneg-template.h
@@ -0,0 +1,17 @@
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) \
+  __attribute__((noipa)) \
+  void vneg_##TYPE (TYPE *dst, TYPE *a, int n) \
+  { \
+    for (int i = 0; i < n; i++) \
+      dst[i] =  -a[i]; \
+  }
+
+#define TEST_ALL() \
+ TEST_TYPE(int8_t) \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(int64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
new file mode 100644
index 00000000000..1c6836742cf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-run.c
@@ -0,0 +1,33 @@
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+#include <assert.h>
+
+#define SZ 255
+
+#define RUN(TYPE) \
+  TYPE a##TYPE[SZ]; \
+  for (int i = 0; i < SZ; i++) \
+  {                             \
+    a##TYPE[i] = i - 127;             \
+  }                             \
+  vnot_##TYPE (a##TYPE, a##TYPE, SZ);         \
+  for (int i = 0; i < SZ; i++) \
+    assert (a##TYPE[i] == (TYPE)~(i - 127));
+
+#define RUN_ALL()                         \
+ RUN(int8_t)                                 \
+ RUN(int16_t)                                 \
+ RUN(int32_t)                                 \
+ RUN(int64_t)                                 \
+ RUN(uint8_t)                                 \
+ RUN(uint16_t)                                 \
+ RUN(uint32_t)                                 \
+ RUN(uint64_t)
+
+int main ()
+{
+  RUN_ALL()
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
new file mode 100644
index 00000000000..ecc4316bd4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv32gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv32gcv -mabi=ilp32d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
new file mode 100644
index 00000000000..67e28af2cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-rv64gcv.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */
+
+#include "vnot-template.h"
+
+/* { dg-final { scan-assembler-times {\tvnot\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h
new file mode 100644
index 00000000000..19c78d6e49b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/vnot-template.h
@@ -0,0 +1,21 @@
+#include <stdint-gcc.h>
+
+#define TEST_TYPE(TYPE) \
+  __attribute__((noipa)) \
+  void vnot_##TYPE (TYPE *dst, TYPE *a, int n) \
+  { \
+    for (int i = 0; i < n; i++) \
+      dst[i] =  ~a[i]; \
+  }
+
+#define TEST_ALL() \
+ TEST_TYPE(int8_t) \
+ TEST_TYPE(uint8_t) \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(uint16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(uint32_t) \
+ TEST_TYPE(int64_t) \
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
index bc99cc0c3cf..54e35cb6c62 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -63,6 +63,8 @@ foreach op $AUTOVEC_TEST_OPTS {
     "" "$op"
   dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/binop/*.\[cS\]]] \
     "" "$op"
+  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/unop/*.\[cS\]]] \
+    "" "$op"
}
# VLS-VLMAX tests
-- 
2.40.1
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-19 11:54 ` 钟居哲
@ 2023-05-19 12:07   ` Robin Dapp
  2023-05-19 12:11     ` 钟居哲
  2023-05-22  8:59     ` Robin Dapp
  0 siblings, 2 replies; 9+ messages in thread
From: Robin Dapp @ 2023-05-19 12:07 UTC (permalink / raw)
  To: 钟居哲,
	gcc-patches, kito.cheng, palmer, Michael Collison, Jeff Law
  Cc: rdapp.gcc

>>> +  TAIL_UNDEFINED = -1,
>>> +  MASK_UNDEFINED = -1,
> Why you add this ?
> 
>>> +  void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED,
>>> +     enum mask_policy vma = MASK_UNDEFINED)
> No, you should just specify this as TAIL_ANY or MASK_ANY as default value.

That's the value I intended for "unspecified" i.e. the caller
didn't specify and then set it to the default.  _ANY can work as
well I guess.

> 
>>>const_vlmax_p (machine_mode mode)
>>>{
>>>-  poly_uint64 nuints = GET_MODE_NUNITS (mode);
>>>+  poly_uint64 nunits = GET_MODE_NUNITS (mode);
>>>-  return nuints.is_constant ()
>>>+  return nunits.is_constant ()
>>>     /* The vsetivli can only hold register 0~31.  */
>>>-    ? (IN_RANGE (nuints.to_constant (), 0, 31))
>>>+    ? (IN_RANGE (nunits.to_constant (), 0, 31))
>>>     /* Only allowed in VLS-VLMAX mode.  */
>>>     : false;
>>>}
> Meaningless change ?

Typo.

> 
>>>    /* For the instruction that doesn't require TA, we still need a default value
>>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>>    -  return (bool) (get_prefer_tail_policy () & 0x1
>>>    - || (get_prefer_tail_policy () >> 1 & 0x1));
>>>    +  return (bool) (get_preferred_tail_policy () & 0x1
>>>    + || (get_preferred_tail_policy () >> 1 & 0x1));
>>>    }
>>>    /* Get default mask policy.  */
>>>    @@ -576,8 +576,8 @@ get_default_ma ()
>>>    {
>>>       /* For the instruction that doesn't require MA, we still need a default value
>>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>>    -  return (bool) (get_prefer_mask_policy () & 0x1
>>>    - || (get_prefer_mask_policy () >> 1 & 0x1));
>>>    +  return (bool) (get_preferred_mask_policy () & 0x1
>>>    + || (get_preferred_mask_policy () >> 1 & 0x1));
> Why you change it ?

Typo/grammar imho.

What about the rest of the changes? It's not all typos but I tried
to unify the mask/policy handling a bit. 

> You are using comparison helper which I added one in my downstream 
> when I am working on comparison autovec patterns:
> 
> I think you can normalize my code with yours:

I wasn't aware that I'm only using one of several helpers, just refactored
what iss upstream.  Yes your code looks reasonable and it surely works
with the patch without much rework. 

> I am almost done all comparison autovec patterns, soon will send them after testing.

Good, looking forward to it.

Regards
 Robin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-19 12:07   ` Robin Dapp
@ 2023-05-19 12:11     ` 钟居哲
  2023-05-22  8:59     ` Robin Dapp
  1 sibling, 0 replies; 9+ messages in thread
From: 钟居哲 @ 2023-05-19 12:11 UTC (permalink / raw)
  To: rdapp.gcc, gcc-patches, kito.cheng, palmer, Michael Collison, Jeff Law
  Cc: rdapp.gcc

[-- Attachment #1: Type: text/plain, Size: 2967 bytes --]

>> What about the rest of the changes? It's not all typos but I tried
>> to unify the mask/policy handling a bit.
Oh, I see.  You rename get_prefer into get_preferred.
This makes perfect sense to me.




juzhe.zhong@rivai.ai
 
From: Robin Dapp
Date: 2023-05-19 20:07
To: 钟居哲; gcc-patches; kito.cheng; palmer; Michael Collison; Jeff Law
CC: rdapp.gcc
Subject: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
>>> +  TAIL_UNDEFINED = -1,
>>> +  MASK_UNDEFINED = -1,
> Why you add this ?
> 
>>> +  void add_policy_operands (enum tail_policy vta = TAIL_UNDEFINED,
>>> +     enum mask_policy vma = MASK_UNDEFINED)
> No, you should just specify this as TAIL_ANY or MASK_ANY as default value.
 
That's the value I intended for "unspecified" i.e. the caller
didn't specify and then set it to the default.  _ANY can work as
well I guess.
 
> 
>>>const_vlmax_p (machine_mode mode)
>>>{
>>>-  poly_uint64 nuints = GET_MODE_NUNITS (mode);
>>>+  poly_uint64 nunits = GET_MODE_NUNITS (mode);
>>>-  return nuints.is_constant ()
>>>+  return nunits.is_constant ()
>>>     /* The vsetivli can only hold register 0~31.  */
>>>-    ? (IN_RANGE (nuints.to_constant (), 0, 31))
>>>+    ? (IN_RANGE (nunits.to_constant (), 0, 31))
>>>     /* Only allowed in VLS-VLMAX mode.  */
>>>     : false;
>>>}
> Meaningless change ?
 
Typo.
 
> 
>>>    /* For the instruction that doesn't require TA, we still need a default value
>>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>>    -  return (bool) (get_prefer_tail_policy () & 0x1
>>>    - || (get_prefer_tail_policy () >> 1 & 0x1));
>>>    +  return (bool) (get_preferred_tail_policy () & 0x1
>>>    + || (get_preferred_tail_policy () >> 1 & 0x1));
>>>    }
>>>    /* Get default mask policy.  */
>>>    @@ -576,8 +576,8 @@ get_default_ma ()
>>>    {
>>>       /* For the instruction that doesn't require MA, we still need a default value
>>>          to emit vsetvl. We pick up the default value according to prefer policy. */
>>>    -  return (bool) (get_prefer_mask_policy () & 0x1
>>>    - || (get_prefer_mask_policy () >> 1 & 0x1));
>>>    +  return (bool) (get_preferred_mask_policy () & 0x1
>>>    + || (get_preferred_mask_policy () >> 1 & 0x1));
> Why you change it ?
 
Typo/grammar imho.
 
What about the rest of the changes? It's not all typos but I tried
to unify the mask/policy handling a bit. 
 
> You are using comparison helper which I added one in my downstream 
> when I am working on comparison autovec patterns:
> 
> I think you can normalize my code with yours:
 
I wasn't aware that I'm only using one of several helpers, just refactored
what iss upstream.  Yes your code looks reasonable and it surely works
with the patch without much rework. 
 
> I am almost done all comparison autovec patterns, soon will send them after testing.
 
Good, looking forward to it.
 
Regards
Robin
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-19 12:07   ` Robin Dapp
  2023-05-19 12:11     ` 钟居哲
@ 2023-05-22  8:59     ` Robin Dapp
  2023-05-22  9:05       ` Kito Cheng
  1 sibling, 1 reply; 9+ messages in thread
From: Robin Dapp @ 2023-05-22  8:59 UTC (permalink / raw)
  To: 钟居哲,
	gcc-patches, kito.cheng, palmer, Michael Collison, Jeff Law
  Cc: rdapp.gcc

As discussed with Juzhe off-list, I will rebase this patch against
Juzhe's vec_cmp/vcond patch once that hits the trunk.

Regards
 Robin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-22  8:59     ` Robin Dapp
@ 2023-05-22  9:05       ` Kito Cheng
  2023-05-22  9:07         ` juzhe.zhong
  2023-05-22  9:07         ` Robin Dapp
  0 siblings, 2 replies; 9+ messages in thread
From: Kito Cheng @ 2023-05-22  9:05 UTC (permalink / raw)
  To: Robin Dapp
  Cc: 钟居哲,
	gcc-patches, palmer, Michael Collison, Jeff Law

So I expect you will also apply those refactor on Juzhe's new changes?
If so I would like to have a separated NFC refactor patch if possible.

e.g.
Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot

On Mon, May 22, 2023 at 4:59 PM Robin Dapp <rdapp.gcc@gmail.com> wrote:
>
> As discussed with Juzhe off-list, I will rebase this patch against
> Juzhe's vec_cmp/vcond patch once that hits the trunk.
>
> Regards
>  Robin

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-22  9:05       ` Kito Cheng
@ 2023-05-22  9:07         ` juzhe.zhong
  2023-05-22  9:07         ` Robin Dapp
  1 sibling, 0 replies; 9+ messages in thread
From: juzhe.zhong @ 2023-05-22  9:07 UTC (permalink / raw)
  To: kito.cheng, Robin Dapp; +Cc: gcc-patches, palmer, collison, jeffreyalaw

[-- Attachment #1: Type: text/plain, Size: 833 bytes --]

Yeah, I agree wit kito.
For example, I see you have rename "get_prefer_***" into "get_preferred_**"
I think this NFC patch should be  separated patch.

Thanks.


juzhe.zhong@rivai.ai
 
From: Kito Cheng
Date: 2023-05-22 17:05
To: Robin Dapp
CC: 钟居哲; gcc-patches; palmer; Michael Collison; Jeff Law
Subject: Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
So I expect you will also apply those refactor on Juzhe's new changes?
If so I would like to have a separated NFC refactor patch if possible.
 
e.g.
Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot
 
On Mon, May 22, 2023 at 4:59 PM Robin Dapp <rdapp.gcc@gmail.com> wrote:
>
> As discussed with Juzhe off-list, I will rebase this patch against
> Juzhe's vec_cmp/vcond patch once that hits the trunk.
>
> Regards
>  Robin
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-22  9:05       ` Kito Cheng
  2023-05-22  9:07         ` juzhe.zhong
@ 2023-05-22  9:07         ` Robin Dapp
  2023-05-22  9:22           ` Kito Cheng
  1 sibling, 1 reply; 9+ messages in thread
From: Robin Dapp @ 2023-05-22  9:07 UTC (permalink / raw)
  To: Kito Cheng
  Cc: rdapp.gcc, 钟居哲,
	gcc-patches, palmer, Michael Collison, Jeff Law

> So I expect you will also apply those refactor on Juzhe's new changes?
> If so I would like to have a separated NFC refactor patch if possible.

What's NFC? :)  Do you mean to just have the refactor part as a separate
patch?  If yes, I agree.

> e.g.
> Juzhe's vec_cmp/vcond -> NFC refactor patch -> abs, vneg, vnot


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] RISC-V: Implement autovec abs, vneg, vnot.
  2023-05-22  9:07         ` Robin Dapp
@ 2023-05-22  9:22           ` Kito Cheng
  0 siblings, 0 replies; 9+ messages in thread
From: Kito Cheng @ 2023-05-22  9:22 UTC (permalink / raw)
  To: Robin Dapp
  Cc: 钟居哲,
	gcc-patches, palmer, Michael Collison, Jeff Law

> > So I expect you will also apply those refactor on Juzhe's new changes?
> > If so I would like to have a separated NFC refactor patch if possible.
>
> What's NFC? :)  Do you mean to just have the refactor part as a separate
> patch?  If yes, I agree.

NFC: non-functional-change, that's a term used in LLVM, I just forgot
that's kind of rare term used here,

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-05-22  9:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-19 11:32 [PATCH] RISC-V: Implement autovec abs, vneg, vnot Robin Dapp
2023-05-19 11:54 ` 钟居哲
2023-05-19 12:07   ` Robin Dapp
2023-05-19 12:11     ` 钟居哲
2023-05-22  8:59     ` Robin Dapp
2023-05-22  9:05       ` Kito Cheng
2023-05-22  9:07         ` juzhe.zhong
2023-05-22  9:07         ` Robin Dapp
2023-05-22  9:22           ` Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).