public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "juzhe.zhong@rivai.ai" <juzhe.zhong@rivai.ai>
To: "Richard Biener" <richard.guenther@gmail.com>,
	 Kito.cheng <kito.cheng@sifive.com>
Cc: 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>
Subject: Re: Re: [PATCH] RISC-V: Basic VLS code gen for RISC-V
Date: Tue, 30 May 2023 15:45:31 +0800	[thread overview]
Message-ID: <87B2E2DEA59DF7D1+20230530154530505119343@rivai.ai> (raw)
In-Reply-To: <CAFiYyc0E3Rc-wz7UZsA_2CWX1FNizQdSYge53QuDYbR8ZbhamA@mail.gmail.com>

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

Hi, Richi.

>> but ideally the user would be able to specify -mrvv-size=32 for an
>> implementation with 32 byte vectors and then vector lowering would make use
>> of vectors up to 32 bytes?

Actually, we don't want to specify -mrvv-size = 32 to enable vectorization on GNU vectors.
You can take a look this example:
https://godbolt.org/z/3jYqoM84h 

GCC need to specify the mrvv size to enable GNU vectors and the codegen only can run on CPU with vector-length = 128bit.
However, LLVM doesn't need to specify the vector length, and the codegen can run on any CPU with RVV  vector-length >= 128 bits.

This is what this patch want to do.

Thanks.


juzhe.zhong@rivai.ai
 
From: Richard Biener
Date: 2023-05-30 15:13
To: Kito Cheng
CC: gcc-patches; palmer; kito.cheng; juzhe.zhong; jeffreyalaw; rdapp.gcc; pan2.li
Subject: Re: [PATCH] RISC-V: Basic VLS code gen for RISC-V
On Tue, May 30, 2023 at 8:07 AM Kito Cheng via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> 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.
 
In the patch you added fixed 16 bytes vector modes, correct?  I've
never looked at
how ARM deals with the GNU vector extensions but I suppose they get mapped
to NEON and not SVE so basically behave the same way here.
 
But I do wonder about the efficiency for RVV where there doesn't exist a
complementary fixed-length ISA.  Shouldn't vector lowering
(tree-vect-generic.cc)
be enhanced to support lowering fixed-length vectors to variable length ones
with (variable) fixed length instead?  From your patch I second-guess the RVV
specification requires 16 byte vectors to be available (or will your
patch split the
insns?) but ideally the user would be able to specify -mrvv-size=32 for an
implementation with 32 byte vectors and then vector lowering would make use
of vectors up to 32 bytes?
 
Also vector lowering will split smaller vectors not equal to the fixed size to
scalars unless you add all fixed length modes smaller than 16 bytes as well.
 
> 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  7:45 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
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 [this message]
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=87B2E2DEA59DF7D1+20230530154530505119343@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 \
    --cc=richard.guenther@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).