public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/riscv/heads/gcc-13-with-riscv-opts)] RISC-V: Fix using wrong mode to get reduction insn vlmax
@ 2023-09-18 18:27 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-09-18 18:27 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:22676b7a182dabf92be3273248b69b70c9111258

commit 22676b7a182dabf92be3273248b69b70c9111258
Author: Lehua Ding <lehua.ding@rivai.ai>
Date:   Fri Sep 15 19:13:42 2023 +0800

    RISC-V: Fix using wrong mode to get reduction insn vlmax
    
    This patch fix using wrong mode when emit vlmax reduction insn. We should
    use src operand instead dest operand (which always LMUL=m1) to get the vlmax
    length. This patch alse remove dest_mode and mask_mode from insn_expander
    constructor, which can be geted by insn_flags.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-protos.h (enum insn_flags): Change name.
            (enum insn_type): Ditto.
            * config/riscv/riscv-v.cc (get_mask_mode_from_insn_flags): Removed.
            (emit_vlmax_insn): Adjust.
            (emit_nonvlmax_insn): Adjust.
            (emit_vlmax_insn_lra): Adjust.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/rvv/vsetvl/wredsum_vlmax.c: New test.
    
    (cherry picked from commit dd6e5d29cbdbed25e4e52e5f06b1bfa835aab215)

Diff:
---
 gcc/config/riscv/riscv-protos.h                    | 12 +--
 gcc/config/riscv/riscv-v.cc                        | 87 ++++++++++------------
 .../gcc.target/riscv/rvv/vsetvl/wredsum_vlmax.c    | 15 ++++
 3 files changed, 60 insertions(+), 54 deletions(-)

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index bb94a7e0441..5a2d218d67b 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -244,8 +244,8 @@ enum insn_flags : unsigned int
   /* Means INSN need two operands to do the operation.  */
   TERNARY_OP_P = 1 << 13,
 
-  /* flags for get mask mode from the index number. default from dest operand.  */
-  MASK_MODE_FROM_OP1_P = 1 << 14,
+  /* flags for get vtype mode from the index number. default from dest operand.  */
+  VTYPE_MODE_FROM_OP1_P = 1 << 14,
 
   /* flags for the floating-point rounding mode.  */
   /* Means INSN has FRM operand and the value is FRM_DYN.  */
@@ -321,7 +321,7 @@ enum insn_type : unsigned int
 
   /* For vcpop.m, no merge operand, no tail and mask policy operands.  */
   CPOP_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | UNARY_OP_P
-	    | MASK_MODE_FROM_OP1_P,
+	    | VTYPE_MODE_FROM_OP1_P,
 
   /* For mask instrunctions, no tail and mask policy operands.  */
   UNARY_MASK_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
@@ -336,10 +336,10 @@ enum insn_type : unsigned int
   = HAS_DEST_P | HAS_MERGE_P | TDEFAULT_POLICY_P | BINARY_OP_P,
 
   /* For vreduce, no mask policy operand. */
-  REDUCE_OP = __NORMAL_OP_TA | BINARY_OP_P | MASK_MODE_FROM_OP1_P,
-  REDUCE_OP_FRM_DYN = REDUCE_OP | FRM_DYN_P | MASK_MODE_FROM_OP1_P,
+  REDUCE_OP = __NORMAL_OP_TA | BINARY_OP_P | VTYPE_MODE_FROM_OP1_P,
+  REDUCE_OP_FRM_DYN = REDUCE_OP | FRM_DYN_P | VTYPE_MODE_FROM_OP1_P,
   REDUCE_OP_M_FRM_DYN
-  = __MASK_OP_TA | BINARY_OP_P | FRM_DYN_P | MASK_MODE_FROM_OP1_P,
+  = __MASK_OP_TA | BINARY_OP_P | FRM_DYN_P | VTYPE_MODE_FROM_OP1_P,
 
   /* For vmv.s.x/vfmv.s.f.  */
   SCALAR_MOVE_OP = HAS_DEST_P | HAS_MASK_P | USE_ONE_TRUE_MASK_P | HAS_MERGE_P
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 7e9fd9ec741..a9287e5d671 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -84,10 +84,9 @@ template <int MAX_OPERANDS> class insn_expander
 public:
   insn_expander () = delete;
 
-  insn_expander (unsigned insn_flags, bool vlmax_p, machine_mode dest_mode,
-		  machine_mode mask_mode)
+  insn_expander (unsigned insn_flags, bool vlmax_p)
     : m_insn_flags (insn_flags), m_opno (0), m_vlmax_p (vlmax_p),
-      m_dest_mode (dest_mode), m_mask_mode (mask_mode), m_vl_op (NULL_RTX)
+      m_vl_op (NULL_RTX)
   {
     check_insn_flags ();
   }
@@ -150,13 +149,17 @@ public:
     create_input_operand (&m_ops[m_opno++], x, mode);
     gcc_assert (m_opno <= MAX_OPERANDS);
   }
-  void add_all_one_mask_operand ()
+  void add_all_one_mask_operand (machine_mode mask_mode)
   {
-    add_input_operand (CONSTM1_RTX (m_mask_mode), m_mask_mode);
+    add_input_operand (CONSTM1_RTX (mask_mode), mask_mode);
   }
-  void add_vundef_operand ()
+  void add_first_one_true_mask_operand (machine_mode mask_mode)
   {
-    add_input_operand (RVV_VUNDEF (m_dest_mode), m_dest_mode);
+    add_input_operand (gen_scalar_move_mask (mask_mode), mask_mode);
+  }
+  void add_vundef_operand (machine_mode dest_mode)
+  {
+    add_input_operand (RVV_VUNDEF (dest_mode), dest_mode);
   }
   void add_policy_operand ()
   {
@@ -194,9 +197,17 @@ public:
     add_input_operand (frm_rtx, Pmode);
   }
 
-  void add_oprand (rtx *ops, int opno)
+  /* Return the vtype mode based on insn_flags.
+     vtype mode mean the mode vsetvl insn set. */
+  machine_mode
+  get_vtype_mode (rtx *ops)
   {
-
+    machine_mode vtype_mode;
+    if (m_insn_flags & VTYPE_MODE_FROM_OP1_P)
+      vtype_mode = GET_MODE (ops[1]);
+    else
+      vtype_mode = GET_MODE (ops[0]);
+    return vtype_mode;
   }
 
   void emit_insn (enum insn_code icode, rtx *ops)
@@ -206,18 +217,22 @@ public:
     /* It's true if any operand is memory operand.  */
     bool any_mem_p = false;
 
+    machine_mode vtype_mode = get_vtype_mode (ops);
+    machine_mode mask_mode = get_mask_mode (vtype_mode);
+
     /* Add dest operand.  */
     if (m_insn_flags & HAS_DEST_P)
       {
-	any_mem_p |= MEM_P (ops[opno]);
-	add_output_operand (ops[opno++], m_dest_mode);
+	rtx op = ops[opno++];
+	any_mem_p |= MEM_P (op);
+	add_output_operand (op, GET_MODE (op));
       }
 
     /* Add mask operand.  */
     if (m_insn_flags & USE_ONE_TRUE_MASK_P)
-      add_input_operand (gen_scalar_move_mask (m_mask_mode), m_mask_mode);
+      add_first_one_true_mask_operand (mask_mode);
     else if (m_insn_flags & USE_ALL_TRUES_MASK_P)
-      add_all_one_mask_operand ();
+      add_all_one_mask_operand (mask_mode);
     else if (m_insn_flags & HAS_MASK_P)
       {
 	machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
@@ -227,7 +242,8 @@ public:
 
     /* Add merge operand.  */
     if (m_insn_flags & USE_VUNDEF_MERGE_P)
-      add_vundef_operand ();
+      /* Same as dest operand.  */
+      add_vundef_operand (GET_MODE (ops[0]));
     else if (m_insn_flags & HAS_MERGE_P)
       {
 	machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
@@ -268,31 +284,30 @@ public:
 
     /* Add vl operand.  */
     rtx len = m_vl_op;
-    machine_mode mode = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
     if (m_vlmax_p)
       {
-	if (riscv_v_ext_vls_mode_p (mode))
+	if (riscv_v_ext_vls_mode_p (vtype_mode))
 	  {
 	    /* VLS modes always set VSETVL by
 	       "vsetvl zero, rs1/imm".  */
-	    poly_uint64 nunits = GET_MODE_NUNITS (mode);
+	    poly_uint64 nunits = GET_MODE_NUNITS (vtype_mode);
 	    len = gen_int_mode (nunits, Pmode);
 	    if (!satisfies_constraint_K (len))
 	      len = force_reg (Pmode, len);
 	    m_vlmax_p = false;
 	  }
-	else if (const_vlmax_p (mode))
+	else if (const_vlmax_p (vtype_mode))
 	  {
 	    /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
 	       the vsetvli to obtain the value of vlmax.  */
-	    poly_uint64 nunits = GET_MODE_NUNITS (mode);
+	    poly_uint64 nunits = GET_MODE_NUNITS (vtype_mode);
 	    len = gen_int_mode (nunits, Pmode);
 	    m_vlmax_p = false;
 	  }
 	else if (can_create_pseudo_p ())
 	  {
 	    len = gen_reg_rtx (Pmode);
-	    emit_vlmax_vsetvl (mode, len);
+	    emit_vlmax_vsetvl (vtype_mode, len);
 	  }
       }
 
@@ -325,38 +340,20 @@ public:
   }
 
 private:
-  int m_insn_flags;
+  unsigned m_insn_flags;
   int m_opno;
   bool m_vlmax_p;
-  machine_mode m_dest_mode;
-  machine_mode m_mask_mode;
   rtx m_vl_op;
   expand_operand m_ops[MAX_OPERANDS];
 };
 
-/* Return the mask mode based on insn_flags */
-static machine_mode
-get_mask_mode_from_insn_flags (unsigned insn_flags, rtx *ops)
-{
-  machine_mode mask_mode;
-  if (insn_flags & MASK_MODE_FROM_OP1_P)
-    mask_mode = get_mask_mode (GET_MODE (ops[1]));
-  else
-    mask_mode = get_mask_mode (GET_MODE (ops[0]));
-  return mask_mode;
-}
-
 /* Emit RVV insn which vl is VLMAX.
    This function can only be used before LRA pass or
    for VLS_AVL_IMM modes.  */
 void
 emit_vlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops)
 {
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
-
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true, dest_mode,
-					   mask_mode);
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true);
   e.emit_insn ((enum insn_code) icode, ops);
 }
 
@@ -364,10 +361,7 @@ emit_vlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops)
 void
 emit_nonvlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
 {
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, false, dest_mode,
-					   mask_mode);
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, false);
   e.set_vl (vl);
   e.emit_insn ((enum insn_code) icode, ops);
 }
@@ -379,10 +373,7 @@ emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
 {
   gcc_assert (!can_create_pseudo_p ());
 
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true, dest_mode,
-					   mask_mode);
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true);
   e.set_vl (vl);
   e.emit_insn ((enum insn_code) icode, ops);
 }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/wredsum_vlmax.c b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/wredsum_vlmax.c
new file mode 100644
index 00000000000..6b7c77326ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vsetvl/wredsum_vlmax.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b --param=riscv-autovec-preference=fixed-vlmax -O3" } */
+
+
+#include <stdint.h>
+
+int16_t foo (int8_t *restrict a)
+{
+    int16_t sum = 0;
+    for (int i = 0; i < 8; i += 1)
+      sum += a[i];
+    return sum;
+}
+
+/* { dg-final { scan-assembler-not {\tvsetivli\tzero,16} } } */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-09-18 18:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-18 18:27 [gcc(refs/vendors/riscv/heads/gcc-13-with-riscv-opts)] RISC-V: Fix using wrong mode to get reduction insn vlmax Jeff Law

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).