public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "juzhe.zhong@rivai.ai" <juzhe.zhong@rivai.ai>
To: Kito.cheng <kito.cheng@sifive.com>,
	 gcc-patches <gcc-patches@gcc.gnu.org>,
	 palmer <palmer@dabbelt.com>,  kito.cheng <kito.cheng@gmail.com>,
	 jeffreyalaw <jeffreyalaw@gmail.com>,
	 "Robin Dapp" <rdapp.gcc@gmail.com>,  pan2.li <pan2.li@intel.com>
Cc: Kito.cheng <kito.cheng@sifive.com>
Subject: Re: [PATCH] RISC-V: Basic VLS code gen for RISC-V
Date: Tue, 30 May 2023 14:32:34 +0800	[thread overview]
Message-ID: <9FD4D8ADEB8D8E67+20230530143233786291327@rivai.ai> (raw)
In-Reply-To: <20230530060621.31449-1-kito.cheng@sifive.com>

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


>> /* Return true if MODE is true VLS mode.  */
>> bool
>> vls_mode_p (machine_mode mode)
>> {
>>   switch (mode)
>>     {
>>     case E_V4SImode:
>>     case E_V2DImode:
>>     case E_V8HImode:
>>     case E_V16QImode:
>>       return true;
>>     default:
>>       return false;
>>     }
>> }
To be consistent, you should put these into riscv-vector-switching.def.
It can make the function easier extend,change it like this:
change name into riscv_v_ext_vls_mode_p 
bool
riscv_v_ext_vls_mode_p (machine_mode mode)
{
#define VLS_ENTRY(MODE, REQUIREMENT, ...)                                          \
  case MODE##mode:                                                             \
    return REQUIREMENT;
  switch (mode)
    {
#include "riscv-vector-switch.def"
    default:
      return false;
    }
  return false;
}
Then in riscv-vector-switch.def
VLS_ENTRY (V4SI...
VLS_ENTRY (V2DI..
...
In the future, we extend more VLS modes in riscv-vector-switch.def

>>(define_insn_and_split "<optab><mode>3"
>>  [(set (match_operand:VLS 0 "register_operand" "=vr")
>>	(any_int_binop_no_shift:VLS
>>	  (match_operand:VLS 1 "register_operand" "vr")
>>	  (match_operand:VLS 2 "register_operand" "vr")))]
>>  "TARGET_VECTOR"
>>  "#"
>>  "reload_completed"
>>  [(const_int 0)]
>>+{
>>  machine_mode vla_mode = riscv_vector::minimal_vla_mode (<MODE>mode);
>>  riscv_vector::vls_insn_expander (
>>    code_for_pred (<CODE>, vla_mode), riscv_vector::RVV_BINOP,
>>    operands, <MODE>mode, vla_mode);
>>  DONE;
>>})
This pattern can work for current VLS modes so far since they are within 0~31, if we add more VLSmodes such as V32QImode, V64QImode,
it can't work . I am ok with this, but I should remind you early.

>> # VLS test
>>gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vls/*.\[cS\]]] \
>>	"" $CFLAGS
>>Add tests with -march=rv64gcv_zvl256b to see whether your testcase can generate LMUL = mf2 vsetvliand -march=rv64gcv_zvl2048 make sure your testcase will not go into the VLS modes (2048 * 1 / 8 > 128) 
For VSETVL part, I didn't see you define attribute sew/vlmul ...ratio for VLS modes.I wonder how these VLS modes emit correct VSETVL?For example in vector.md:
(define_attr "sew" ""
  (cond [(eq_attr "mode" "VNx1QI,VNx2QI,VNx4QI,VNx8QI,VNx16QI,VNx32QI,VNx64QI,\
        VNx1BI,VNx2BI,VNx4BI,VNx8BI,VNx16BI,VNx32BI,VNx64BI,\
        VNx128QI,VNx128BI,VNx2x64QI,VNx2x32QI,VNx3x32QI,VNx4x32QI,\
        VNx2x16QI,VNx3x16QI,VNx4x16QI,VNx5x16QI,VNx6x16QI,VNx7x16QI,VNx8x16QI,\
        VNx2x8QI,VNx3x8QI,VNx4x8QI,VNx5x8QI,VNx6x8QI,VNx7x8QI,VNx8x8QI,\
        VNx2x4QI,VNx3x4QI,VNx4x4QI,VNx5x4QI,VNx6x4QI,VNx7x4QI,VNx8x4QI,\
        VNx2x2QI,VNx3x2QI,VNx4x2QI,VNx5x2QI,VNx6x2QI,VNx7x2QI,VNx8x2QI,\
        VNx2x1QI,VNx3x1QI,VNx4x1QI,VNx5x1QI,VNx6x1QI,VNx7x1QI,VNx8x1QI")
   (const_int 8)
   (eq_attr "mode" "VNx1HI,VNx2HI,VNx4HI,VNx8HI,VNx16HI,VNx32HI,VNx64HI,\
        VNx2x32HI,VNx2x16HI,VNx3x16HI,VNx4x16HI,\
        VNx2x8HI,VNx3x8HI,VNx4x8HI,VNx5x8HI,VNx6x8HI,VNx7x8HI,VNx8x8HI,\
        VNx2x4HI,VNx3x4HI,VNx4x4HI,VNx5x4HI,VNx6x4HI,VNx7x4HI,VNx8x4HI,\
        VNx2x2HI,VNx3x2HI,VNx4x2HI,VNx5x2HI,VNx6x2HI,VNx7x2HI,VNx8x2HI,\
        VNx2x1HI,VNx3x1HI,VNx4x1HI,VNx5x1HI,VNx6x1HI,VNx7x1HI,VNx8x1HI")
   (const_int 16)
   (eq_attr "mode" "VNx1SI,VNx2SI,VNx4SI,VNx8SI,VNx16SI,VNx32SI,\
        VNx1SF,VNx2SF,VNx4SF,VNx8SF,VNx16SF,VNx32SF,\
        VNx2x16SI,VNx2x8SI,VNx3x8SI,VNx4x8SI,\
        VNx2x4SI,VNx3x4SI,VNx4x4SI,VNx5x4SI,VNx6x4SI,VNx7x4SI,VNx8x4SI,\
        VNx2x2SI,VNx3x2SI,VNx4x2SI,VNx5x2SI,VNx6x2SI,VNx7x2SI,VNx8x2SI,\
        VNx2x1SI,VNx3x1SI,VNx4x1SI,VNx5x1SI,VNx6x1SI,VNx7x1SI,VNx8x1SI,\
        VNx2x16SF,VNx2x8SF,VNx3x8SF,VNx4x8SF,\
        VNx2x4SF,VNx3x4SF,VNx4x4SF,VNx5x4SF,VNx6x4SF,VNx7x4SF,VNx8x4SF,\
        VNx2x2SF,VNx3x2SF,VNx4x2SF,VNx5x2SF,VNx6x2SF,VNx7x2SF,VNx8x2SF,\
        VNx2x1SF,VNx3x1SF,VNx4x1SF,VNx5x1SF,VNx6x1SF,VNx7x1SF,VNx8x1SF")
   (const_int 32)
   (eq_attr "mode" "VNx1DI,VNx2DI,VNx4DI,VNx8DI,VNx16DI,\
        VNx1DF,VNx2DF,VNx4DF,VNx8DF,VNx16DF,\
        VNx2x8DI,VNx2x4DI,VNx3x4DI,VNx4x4DI,\
        VNx2x2DI,VNx3x2DI,VNx4x2DI,VNx5x2DI,VNx6x2DI,VNx7x2DI,VNx8x2DI,\
        VNx2x1DI,VNx3x1DI,VNx4x1DI,VNx5x1DI,VNx6x1DI,VNx7x1DI,VNx8x1DI,\
        VNx2x8DF,VNx2x4DF,VNx3x4DF,VNx4x4DF,\
        VNx2x2DF,VNx3x2DF,VNx4x2DF,VNx5x2DF,VNx6x2DF,VNx7x2DF,VNx8x2DF,\
        VNx2x1DF,VNx3x1DF,VNx4x1DF,VNx5x1DF,VNx6x1DF,VNx7x1DF,VNx8x1DF")
   (const_int 64)]
  (const_int INVALID_ATTRIBUTE)))




juzhe.zhong@rivai.ai
 
From: Kito Cheng
Date: 2023-05-30 14:06
To: gcc-patches; palmer; kito.cheng; juzhe.zhong; jeffreyalaw; rdapp.gcc; pan2.li
CC: Kito Cheng
Subject: [PATCH] RISC-V: Basic VLS code gen for RISC-V
GNU vector extensions is widly used around this world, and this patch
enable that with RISC-V vector extensions, this can help people
leverage existing code base with RVV, and also can write vector programs in a
familiar way.
 
The idea of VLS code gen support is emulate VLS operation by VLA operation with
specific length.
 
Key design point is we defer the mode conversion (From VLS to VLA mode) after
register allocation, it come with several advantages:
- VLS pattern is much friendly for most optimization pass like combine.
- Register allocator can spill/restore exact size of VLS type instead of
  whole register.
 
This is compatible with VLA vectorization.
 
Only support move and binary part of operation patterns.
 
gcc/ChangeLog:
 
* config/riscv/riscv-modes.def: Introduce VLS modes.
* config/riscv/riscv-protos.h (riscv_vector::minimal_vls_mode): New.
(riscv_vector::vls_insn_expander): New.
(riscv_vector::vls_mode_p): New.
* config/riscv/riscv-v.cc (riscv_vector::minimal_vls_mode): New.
(riscv_vector::vls_mode_p): New.
(riscv_vector::vls_insn_expander): New.
(riscv_vector::update_vls_mode): New.
* config/riscv/riscv.cc (riscv_v_ext_mode_p): New.
(riscv_v_adjust_nunits): Handle VLS type.
(riscv_hard_regno_nregs): Ditto.
(riscv_hard_regno_mode_ok): Ditto.
(riscv_regmode_natural_size): Ditto.
* config/riscv/vector-iterators.md (VLS): New.
(VM): Handle VLS type.
(vel): Ditto.
* config/riscv/vector.md: Include vector-vls.md.
* config/riscv/vector-vls.md: New file.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/rvv.exp: Add vls folder.
* gcc.target/riscv/rvv/vls/binop-template.h: New test.
* gcc.target/riscv/rvv/vls/binop-v.c: New test.
* gcc.target/riscv/rvv/vls/binop-zve32x.c: New test.
* gcc.target/riscv/rvv/vls/binop-zve64x.c: New test.
* gcc.target/riscv/rvv/vls/move-template.h: New test.
* gcc.target/riscv/rvv/vls/move-v.c: New test.
* gcc.target/riscv/rvv/vls/move-zve32x.c: New test.
* gcc.target/riscv/rvv/vls/move-zve64x.c: New test.
* gcc.target/riscv/rvv/vls/load-store-template.h: New test.
* gcc.target/riscv/rvv/vls/load-store-v.c: New test.
* gcc.target/riscv/rvv/vls/load-store-zve32x.c: New test.
* gcc.target/riscv/rvv/vls/load-store-zve64x.c: New test.
* gcc.target/riscv/rvv/vls/vls-types.h: New test.
---
gcc/config/riscv/riscv-modes.def              |  3 +
gcc/config/riscv/riscv-protos.h               |  4 ++
gcc/config/riscv/riscv-v.cc                   | 67 +++++++++++++++++++
gcc/config/riscv/riscv.cc                     | 27 +++++++-
gcc/config/riscv/vector-iterators.md          |  6 ++
gcc/config/riscv/vector-vls.md                | 64 ++++++++++++++++++
gcc/config/riscv/vector.md                    |  2 +
gcc/testsuite/gcc.target/riscv/rvv/rvv.exp    |  4 ++
.../gcc.target/riscv/rvv/vls/binop-template.h | 18 +++++
.../gcc.target/riscv/rvv/vls/binop-v.c        | 18 +++++
.../gcc.target/riscv/rvv/vls/binop-zve32x.c   | 18 +++++
.../gcc.target/riscv/rvv/vls/binop-zve64x.c   | 18 +++++
.../riscv/rvv/vls/load-store-template.h       |  8 +++
.../gcc.target/riscv/rvv/vls/load-store-v.c   | 17 +++++
.../riscv/rvv/vls/load-store-zve32x.c         | 17 +++++
.../riscv/rvv/vls/load-store-zve64x.c         | 17 +++++
.../gcc.target/riscv/rvv/vls/move-template.h  | 13 ++++
.../gcc.target/riscv/rvv/vls/move-v.c         | 10 +++
.../gcc.target/riscv/rvv/vls/move-zve32x.c    | 10 +++
.../gcc.target/riscv/rvv/vls/move-zve64x.c    | 10 +++
.../gcc.target/riscv/rvv/vls/vls-types.h      | 42 ++++++++++++
21 files changed, 391 insertions(+), 2 deletions(-)
create mode 100644 gcc/config/riscv/vector-vls.md
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h
 
diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def
index 19a4f9fb3db..f897e560667 100644
--- a/gcc/config/riscv/riscv-modes.def
+++ b/gcc/config/riscv/riscv-modes.def
@@ -318,6 +318,9 @@ RVV_TUPLE_PARTIAL_MODES (6)
RVV_TUPLE_PARTIAL_MODES (7)
RVV_TUPLE_PARTIAL_MODES (8)
+/* VLS modes.  */
+VECTOR_MODES (INT, 16);       /* V16QI V8HI V4SI V2DI */
+
/* TODO: According to RISC-V 'V' ISA spec, the maximun vector length can
    be 65536 for a single vector register which means the vector mode in
    GCC can be maximum = 65536 * 8 bits (LMUL=8).
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 0462f96c8d5..56f714bbfb5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -261,6 +261,10 @@ enum frm_field_enum
opt_machine_mode vectorize_related_mode (machine_mode, scalar_mode,
poly_uint64);
unsigned int autovectorize_vector_modes (vec<machine_mode> *, bool);
+machine_mode minimal_vla_mode (machine_mode);
+void
+vls_insn_expander (unsigned, int, rtx *, machine_mode, machine_mode);
+bool vls_mode_p (machine_mode);
}
/* We classify builtin types into two classes:
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index a5715bb466c..f9fb8cd9be4 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -1697,4 +1697,71 @@ expand_vcond (rtx *ops)
     gen_vcond_mask (data_mode, data_mode, ops[0], ops[1], ops[2], mask));
}
+/* Return the minimal containable VLA mode for MODE.  */
+
+machine_mode
+minimal_vla_mode (machine_mode mode)
+{
+  gcc_assert (GET_MODE_NUNITS (mode).is_constant ());
+  unsigned type_size = GET_MODE_NUNITS (mode).to_constant ();
+  poly_uint64 nunits = type_size * poly_uint64 (1, 1);
+  opt_machine_mode vla_mode = get_vector_mode (GET_MODE_INNER (mode), nunits);
+  return vla_mode.else_void ();
+}
+
+/* Return true if MODE is true VLS mode.  */
+
+bool
+vls_mode_p (machine_mode mode)
+{
+  switch (mode)
+    {
+    case E_V4SImode:
+    case E_V2DImode:
+    case E_V8HImode:
+    case E_V16QImode:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Convert all OPERANDS to VLA_MODE.  */
+
+static void
+update_vls_mode (machine_mode vla_mode, unsigned n_operands, rtx *operands)
+{
+  unsigned i;
+  for (i = 0; i < n_operands; ++i)
+    {
+      switch (GET_CODE (operands[i]))
+ {
+ case REG:
+   operands[i] = gen_rtx_REG (vla_mode, REGNO (operands[i]));
+   break;
+ case MEM:
+   operands[i] = change_address (operands[i], vla_mode, NULL_RTX);
+   break;
+ default:
+   gcc_unreachable ();
+ }
+    }
+}
+
+/* Expand VLS operation to VLA pattern.  */
+
+void
+vls_insn_expander (unsigned icode, int op_num, rtx *operands,
+    machine_mode vls_mode, machine_mode vla_mode)
+{
+  update_vls_mode (vla_mode, /* n_operands */ op_num, operands);
+
+  poly_uint16 nunit = GET_MODE_NUNITS (vls_mode);
+
+  gcc_assert (nunit.is_constant ());
+
+  riscv_vector::emit_nonvlmax_insn (icode, op_num, operands,
+     GEN_INT (nunit.to_constant ()));
+}
+
} // namespace riscv_vector
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3954fc07a8b..2e14f2e0d53 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1034,7 +1034,8 @@ riscv_v_ext_tuple_mode_p (machine_mode mode)
static bool
riscv_v_ext_mode_p (machine_mode mode)
{
-  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode);
+  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode)
+ || riscv_vector::vls_mode_p (mode);
}
/* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
@@ -1043,7 +1044,7 @@ riscv_v_ext_mode_p (machine_mode mode)
poly_int64
riscv_v_adjust_nunits (machine_mode mode, int scale)
{
-  if (riscv_v_ext_mode_p (mode))
+  if (riscv_v_ext_mode_p (mode) && !riscv_vector::vls_mode_p (mode))
     return riscv_vector_chunks * scale;
   return scale;
}
@@ -6059,6 +6060,22 @@ riscv_register_move_cost (machine_mode mode,
static unsigned int
riscv_hard_regno_nregs (unsigned int regno, machine_mode mode)
{
+  if (riscv_vector::vls_mode_p (mode))
+    {
+      if (TARGET_MIN_VLEN)
+ {
+   unsigned min_byte_per_vector_register = TARGET_MIN_VLEN / 8;
+   unsigned mode_size = GET_MODE_SIZE (mode).to_constant ();
+
+   if (min_byte_per_vector_register >= mode_size)
+     return 1;
+
+   return mode_size / min_byte_per_vector_register;
+ }
+      else
+ return 1;
+    }
+
   if (riscv_v_ext_vector_mode_p (mode))
     {
       /* Handle fractional LMUL, it only occupy part of vector register but
@@ -6148,6 +6165,10 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
but for mask vector register, register numbers can be any number. */
       int lmul = 1;
       machine_mode rvv_mode = mode;
+
+      if (riscv_vector::vls_mode_p (mode))
+ rvv_mode = riscv_vector::minimal_vla_mode (mode);
+
       if (riscv_v_ext_tuple_mode_p (rvv_mode))
rvv_mode = riscv_vector::get_subpart_mode (rvv_mode);
       poly_int64 size = GET_MODE_SIZE (rvv_mode);
@@ -7223,6 +7244,8 @@ riscv_vector_alignment (const_tree type)
poly_uint64
riscv_regmode_natural_size (machine_mode mode)
{
+  if (riscv_vector::vls_mode_p (mode))
+    return GET_MODE_SIZE (mode);
   /* The natural size for RVV data modes is one RVV data vector,
      and similarly for predicates.  We can't independently modify
      anything smaller than that.  */
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 70fb5b80b1b..650f2651c7d 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -84,6 +84,10 @@ (define_c_enum "unspec" [
   UNSPEC_MODIFY_VL
])
+(define_mode_iterator VLS [
+  V2DI V4SI V8HI V16QI
+])
+
(define_mode_iterator V [
   (VNx1QI "TARGET_MIN_VLEN < 128") VNx2QI VNx4QI VNx8QI VNx16QI VNx32QI (VNx64QI "TARGET_MIN_VLEN > 32") (VNx128QI "TARGET_MIN_VLEN >= 128")
   (VNx1HI "TARGET_MIN_VLEN < 128") VNx2HI VNx4HI VNx8HI VNx16HI (VNx32HI "TARGET_MIN_VLEN > 32") (VNx64HI "TARGET_MIN_VLEN >= 128")
@@ -976,6 +980,7 @@ (define_mode_attr VM [
   (VNx2x4DF "VNx4BI") (VNx3x4DF "VNx4BI") (VNx4x4DF "VNx4BI")
   (VNx2x2DF "VNx2BI") (VNx3x2DF "VNx2BI") (VNx4x2DF "VNx2BI") (VNx5x2DF "VNx2BI") (VNx6x2DF "VNx2BI") (VNx7x2DF "VNx2BI") (VNx8x2DF "VNx2BI")
   (VNx2x1DF "VNx1BI") (VNx3x1DF "VNx1BI") (VNx4x1DF "VNx1BI") (VNx5x1DF "VNx1BI") (VNx6x1DF "VNx1BI") (VNx7x1DF "VNx1BI") (VNx8x1DF "VNx1BI")
+  (V2DI "V2BI") (V4SI "V4BI") (V8HI "V8BI") (V16QI "V16BI")
])
(define_mode_attr vm [
@@ -1003,6 +1008,7 @@ (define_mode_attr vel [
   (VNx1DI "di") (VNx2DI "di") (VNx4DI "di") (VNx8DI "di") (VNx16DI "di")
   (VNx1SF "sf") (VNx2SF "sf") (VNx4SF "sf") (VNx8SF "sf") (VNx16SF "sf") (VNx32SF "sf")
   (VNx1DF "df") (VNx2DF "df") (VNx4DF "df") (VNx8DF "df") (VNx16DF "df")
+  (V2DI "di") (V4SI "si") (V8HI "hi") (V16QI "qi")
])
(define_mode_attr VSUBEL [
diff --git a/gcc/config/riscv/vector-vls.md b/gcc/config/riscv/vector-vls.md
new file mode 100644
index 00000000000..af7e7a6c726
--- /dev/null
+++ b/gcc/config/riscv/vector-vls.md
@@ -0,0 +1,64 @@
+;; Machine description for vector length specific type operation with
+;; RISC-V 'V' Extension for GNU compiler.
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_expand "mov<mode>"
+  [(set (match_operand:VLS 0 "nonimmediate_operand")
+ (match_operand:VLS 1 "vector_move_operand"))]
+  "TARGET_VECTOR"
+{
+  // TODO: Only allow register and memory now, we should allow legal
+  //       vector_const too.
+  if (MEM_P (operands[0]) && MEM_P (operands[1]))
+    operands[1] = force_reg (GET_MODE(operands[1]), operands[1]);
+})
+
+(define_insn_and_split "*mov<mode>"
+  [(set (match_operand:VLS 0 "nonimmediate_operand" "=vr,vr, m,vr")
+ (match_operand:VLS 1 "vector_move_operand"  " vr, m,vr,vi"))]
+  "TARGET_VECTOR &&
+   (register_operand (operands[0], <MODE>mode)
+    || register_operand (operands[1], <MODE>mode))"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  machine_mode vla_mode = riscv_vector::minimal_vla_mode (<MODE>mode);
+  riscv_vector::vls_insn_expander (
+    code_for_pred_mov (vla_mode), riscv_vector::RVV_UNOP, operands,
+    <MODE>mode, vla_mode);
+  DONE;
+})
+
+(define_insn_and_split "<optab><mode>3"
+  [(set (match_operand:VLS 0 "register_operand" "=vr")
+ (any_int_binop_no_shift:VLS
+   (match_operand:VLS 1 "register_operand" "vr")
+   (match_operand:VLS 2 "register_operand" "vr")))]
+  "TARGET_VECTOR"
+  "#"
+  "reload_completed"
+  [(const_int 0)]
+{
+  machine_mode vla_mode = riscv_vector::minimal_vla_mode (<MODE>mode);
+  riscv_vector::vls_insn_expander (
+    code_for_pred (<CODE>, vla_mode), riscv_vector::RVV_BINOP,
+    operands, <MODE>mode, vla_mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index cd696da5d89..e3fd0807b22 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -25,6 +25,7 @@
;; - Intrinsics (https://github.com/riscv/rvv-intrinsic-doc)
;; - Auto-vectorization (autovec.md)
;; - Combine optimization (TBD)
+;; - VLS patterns (vector-vls.md)
(include "vector-iterators.md")
@@ -8407,3 +8408,4 @@ (define_split
)
(include "autovec.md")
+(include "vector-vls.md")
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
index bf03570b9cc..f6c56a63ada 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -77,5 +77,9 @@ foreach op $AUTOVEC_TEST_OPTS {
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/vls-vlmax/*.\[cS\]]] \
"-std=c99 -O3 -ftree-vectorize --param riscv-autovec-preference=fixed-vlmax" $CFLAGS
+# VLS test
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vls/*.\[cS\]]] \
+ "" $CFLAGS
+
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h
new file mode 100644
index 00000000000..0114c124646
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-template.h
@@ -0,0 +1,18 @@
+#include "vls-types.h"
+#define __BINOP(NAME, OP, VLS_TYPE, SCALAR_TYPE) \
+void binop_##NAME##VLS_TYPE \
+  (VLS_TYPE *src1, VLS_TYPE *src2, VLS_TYPE *dst) \
+{ \
+    *dst = *src1 OP *src2; \
+}
+
+#define BINOP(VLS_TYPE, SCALAR_TYPE) \
+__BINOP (ADD, +, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (MUL, *, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (DIV, /, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (MOD, %, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (AND, &, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (IOR, |, VLS_TYPE, SCALAR_TYPE) \
+__BINOP (XOR, ^, VLS_TYPE, SCALAR_TYPE)
+
+FOR_EACH_VLS_TYPE(BINOP)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c
new file mode 100644
index 00000000000..78c1a19cfbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-v.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */
+
+#include "binop-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */
+/* { dg-final { scan-assembler-times {vadd\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vmul\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vdiv\.vv} 4} } */
+/* { dg-final { scan-assembler-times {vdivu\.vv} 4 } } */
+/* { dg-final { scan-assembler-times {vrem\.vv} 4} } */
+/* { dg-final { scan-assembler-times {vremu\.vv} 4 } } */
+/* { dg-final { scan-assembler-times {vand\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vor\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {vxor\.vv} 8} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c
new file mode 100644
index 00000000000..bca56ba32a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve32x.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */
+
+#include "binop-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */
+/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */
+/* { dg-final { scan-assembler-times {vadd\.vv} 6} } */
+/* { dg-final { scan-assembler-times {vmul\.vv} 6} } */
+/* { dg-final { scan-assembler-times {vdiv\.vv} 3} } */
+/* { dg-final { scan-assembler-times {vdivu\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {vrem\.vv} 3} } */
+/* { dg-final { scan-assembler-times {vremu\.vv} 3 } } */
+/* { dg-final { scan-assembler-times {vand\.vv} 6} } */
+/* { dg-final { scan-assembler-times {vor\.vv} 6 } } */
+/* { dg-final { scan-assembler-times {vxor\.vv} 6} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c
new file mode 100644
index 00000000000..45dcad12a93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/binop-zve64x.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */
+
+#include "binop-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */
+/* { dg-final { scan-assembler-times {vadd\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vmul\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vdiv\.vv} 4} } */
+/* { dg-final { scan-assembler-times {vdivu\.vv} 4 } } */
+/* { dg-final { scan-assembler-times {vrem\.vv} 4} } */
+/* { dg-final { scan-assembler-times {vremu\.vv} 4 } } */
+/* { dg-final { scan-assembler-times {vand\.vv} 8} } */
+/* { dg-final { scan-assembler-times {vor\.vv} 8 } } */
+/* { dg-final { scan-assembler-times {vxor\.vv} 8} } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h
new file mode 100644
index 00000000000..9ea0c7cb5dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-template.h
@@ -0,0 +1,8 @@
+#include "vls-types.h"
+#define LOAD_STORE(VLS_TYPE, SCALAR_TYPE) \
+void load_store_##VLS_TYPE (VLS_TYPE *src, VLS_TYPE *dst) \
+{ \
+    *dst = *src; \
+}
+
+FOR_EACH_VLS_TYPE(LOAD_STORE)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c
new file mode 100644
index 00000000000..b8adcea70d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-v.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */
+
+#include "load-store-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */
+/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle64\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse64\.v} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c
new file mode 100644
index 00000000000..ef3426d00a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve32x.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */
+
+#include "load-store-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */
+/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */
+/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */
+/* { dg-final { scan-assembler-not {vle64\.v} } } */
+/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */
+/* { dg-final { scan-assembler-not {vse64\.v} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c
new file mode 100644
index 00000000000..e03220d89f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/load-store-zve64x.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */
+
+#include "load-store-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */
+/* { dg-final { scan-assembler-times {vle8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle32\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vle64\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse8\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse16\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse32\.v} 2 } } */
+/* { dg-final { scan-assembler-times {vse64\.v} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h
new file mode 100644
index 00000000000..e328a42204c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-template.h
@@ -0,0 +1,13 @@
+#include "vls-types.h"
+
+#define MOVE(VLS_TYPE, SCALAR_TYPE) \
+void move_##VLS_TYPE () \
+{ \
+    register VLS_TYPE src##VLS_TYPE __asm__ ("v0"); \
+    register VLS_TYPE dst##VLS_TYPE __asm__ ("v8"); \
+    __asm__ volatile ("#def" : "=vr"(src##VLS_TYPE)); \
+    dst##VLS_TYPE = src##VLS_TYPE; \
+    __asm__ volatile ("#use" : : "vr"(dst##VLS_TYPE)); \
+}
+
+FOR_EACH_VLS_TYPE(MOVE)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c
new file mode 100644
index 00000000000..91c89df098e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-v.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv64gcv -mabi=lp64" } */
+
+#include "move-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m1} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m1} } } */
+/* { dg-final { scan-assembler-times {vmv\.v\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c
new file mode 100644
index 00000000000..175986edf15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve32x.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve32x -mabi=ilp32" } */
+
+#include "move-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m4} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m4} } } */
+/* { dg-final { scan-assembler-not {vsetivli\s+zero,2,e64,m4} } } */
+/* { dg-final { scan-assembler-times {vmv\.v\.v} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c
new file mode 100644
index 00000000000..2e574b1f3ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/move-zve64x.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gc_zve64x -mabi=ilp32" } */
+
+#include "move-template.h"
+
+/* { dg-final { scan-assembler {vsetivli\s+zero,16,e8,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,8,e16,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,4,e32,m2} } } */
+/* { dg-final { scan-assembler {vsetivli\s+zero,2,e64,m2} } } */
+/* { dg-final { scan-assembler-times {vmv\.v\.v} 8 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h b/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h
new file mode 100644
index 00000000000..302823b583f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/vls/vls-types.h
@@ -0,0 +1,42 @@
+#ifndef __VLS_TYPE_H
+#define __VLS_TYPE_H
+#include <stdint-gcc.h>
+
+typedef  int8_t int8x16_t __attribute__ ((vector_size (16)));
+typedef int16_t int16x8_t __attribute__ ((vector_size (16)));
+typedef int32_t int32x4_t __attribute__ ((vector_size (16)));
+typedef int64_t int64x2_t __attribute__ ((vector_size (16)));
+
+typedef  uint8_t uint8x16_t __attribute__ ((vector_size (16)));
+typedef uint16_t uint16x8_t __attribute__ ((vector_size (16)));
+typedef uint32_t uint32x4_t __attribute__ ((vector_size (16)));
+typedef uint64_t uint64x2_t __attribute__ ((vector_size (16)));
+
+
+#if __riscv_v_elen == 32
+
+#define FOR_EACH_VLS_TYPE(FUNC) \
+    FUNC (int8x16_t, int8_t) \
+    FUNC (int16x8_t, int16_t) \
+    FUNC (int32x4_t, int32_t) \
+    FUNC (uint8x16_t, uint8_t) \
+    FUNC (uint16x8_t, uint16_t) \
+    FUNC (uint32x4_t, uint32_t)
+
+#elif __riscv_v_elen == 64
+
+#define FOR_EACH_VLS_TYPE(FUNC) \
+    FUNC (int8x16_t, int8_t) \
+    FUNC (int16x8_t, int16_t) \
+    FUNC (int32x4_t, int32_t) \
+    FUNC (int64x2_t, int64_t) \
+    FUNC (uint8x16_t, uint8_t) \
+    FUNC (uint16x8_t, uint16_t) \
+    FUNC (uint32x4_t, uint32_t) \
+    FUNC (uint64x2_t, uint64_t)
+
+#else
+#error "zve* or v extension is required."
+#endif
+
+#endif
-- 
2.40.1
 
 

  reply	other threads:[~2023-05-30  6:32 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-30  6:06 Kito Cheng
2023-05-30  6:32 ` juzhe.zhong [this message]
2023-05-30  6:51   ` Kito Cheng
2023-05-30  6:59     ` juzhe.zhong
2023-05-30  7:13 ` Richard Biener
2023-05-30  7:45   ` juzhe.zhong
2023-05-30  9:05     ` Robin Dapp
2023-05-30  9:11       ` Kito Cheng
2023-05-30  9:16         ` Kito Cheng
2023-05-30  9:16       ` juzhe.zhong
2023-05-30  9:29         ` Richard Biener
2023-05-30  9:37           ` juzhe.zhong
2023-05-30  9:44           ` juzhe.zhong
2023-05-30 15:45             ` Kito Cheng
2023-05-30 23:19               ` 钟居哲
     [not found]             ` <DC99791C4B2B4D40+106F137E-2B0D-4732-A7C5-8EE0242F9F5A@rivai.ai>
2023-06-12 23:34               ` Jeff Law
     [not found]               ` <529320C359BE5467+690CDE73-D54E-48E2-81C4-B742060D7F28@rivai.ai>
2023-06-13 16:10                 ` Jeff Law
2023-05-30  7:27 ` Robin Dapp
2023-05-30  7:40   ` juzhe.zhong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9FD4D8ADEB8D8E67+20230530143233786291327@rivai.ai \
    --to=juzhe.zhong@rivai.ai \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jeffreyalaw@gmail.com \
    --cc=kito.cheng@gmail.com \
    --cc=kito.cheng@sifive.com \
    --cc=palmer@dabbelt.com \
    --cc=pan2.li@intel.com \
    --cc=rdapp.gcc@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).