diff mbox series

[v4] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV

Message ID 20240322065450.3853372-1-pan2.li@intel.com
State New
Headers show
Series [v4] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV | expand

Commit Message

Li, Pan2 March 22, 2024, 6:54 a.m. UTC
From: Pan Li <pan2.li@intel.com>

This patch would like to introduce one new gcc attribute for RVV.
This attribute is used to define fixed-length variants of one
existing sizeless RVV types.

This attribute is valid if and only if the mrvv-vector-bits=zvl, the only
one args should be the integer constant and its' value is terminated
by the LMUL and the vector register bits in zvl*b.  For example:

typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128)));

The above type define is valid when -march=rv64gc_zve64d_zvl64b
(aka 2(m2) * 64 = 128 for vin32m2_t), and will report error when
-march=rv64gcv_zvl128b similar to below.

"error: invalid RVV vector size '128', expected size is '256' based on
LMUL of type and '-mrvv-vector-bits=zvl'"

Meanwhile, a pre-define macro __riscv_v_fixed_vlen is introduced to
represent the fixed vlen in a RVV vector register.

For the vint*m*_t below operations are allowed.
* The sizeof.
* The global variable(s).
* The element of union and struct.
* The cast to other equalities.
* CMP: >, <, ==, !=, <=, >=
* ALU: +, -, *, /, %, &, |, ^, >>, <<, ~, -

The CMP will return vint*m*_t the same as aarch64 sve. For example:
typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128)));
fixed_vint32m1_t less_than (fixed_vint32m1_t a, fixed_vint32m1_t b)
{
  return a < b;
}

For the vfloat*m*_t below operations are allowed.
* The sizeof.
* The global variable(s).
* The element of union and struct.
* The cast to other equalities.
* CMP: >, <, ==, !=, <=, >=
* ALU: +, -, *, /, -

The CMP will return vfloat*m*_t the same as aarch64 sve. For example:
typedef vfloat32m1_t fixed_vfloat32m1_t __attribute__((riscv_rvv_vector_bits(128)));
fixed_vfloat32m1_t less_than (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
{
  return a < b;
}

For the vbool*_t types only below operations are allowed except
the CMP and ALU. The CMP and ALU operations on vbool*_t is not
well defined currently.
* The sizeof.
* The global variable(s).
* The element of union and struct.
* The cast to other equalities.

For the vint*x*m*_t tuple types are not suppored in this patch which is
compatible with clang.

This patch passed the below testsuites.
* The riscv fully regression tests.

gcc/ChangeLog:

	* config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Add pre-define
	macro __riscv_v_fixed_vlen when zvl.
	* config/riscv/riscv.cc (riscv_handle_rvv_vector_bits_attribute):
	New static func to take care of the RVV types decorated by
	the attributes.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c: New test.
	* gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h: New test.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/config/riscv/riscv-c.cc                   |   3 +
 gcc/config/riscv/riscv.cc                     |  87 +++++++++++++-
 .../riscv/rvv/base/riscv_rvv_vector_bits-1.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-10.c |  53 +++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits-11.c |  76 ++++++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits-12.c |  14 +++
 .../riscv/rvv/base/riscv_rvv_vector_bits-13.c |  10 ++
 .../riscv/rvv/base/riscv_rvv_vector_bits-14.c |  10 ++
 .../riscv/rvv/base/riscv_rvv_vector_bits-15.c |  10 ++
 .../riscv/rvv/base/riscv_rvv_vector_bits-16.c |  11 ++
 .../riscv/rvv/base/riscv_rvv_vector_bits-17.c |  10 ++
 .../riscv/rvv/base/riscv_rvv_vector_bits-18.c |  45 ++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits-2.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-3.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-4.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-5.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-6.c  |   6 +
 .../riscv/rvv/base/riscv_rvv_vector_bits-7.c  |  76 ++++++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits-8.c  |  75 ++++++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits-9.c  |  76 ++++++++++++
 .../riscv/rvv/base/riscv_rvv_vector_bits.h    | 108 ++++++++++++++++++
 21 files changed, 698 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h

Comments

Kito Cheng March 22, 2024, 10:05 a.m. UTC | #1
LGTM, thanks :)

On Fri, Mar 22, 2024 at 2:55 PM <pan2.li@intel.com> wrote:
>
> From: Pan Li <pan2.li@intel.com>
>
> This patch would like to introduce one new gcc attribute for RVV.
> This attribute is used to define fixed-length variants of one
> existing sizeless RVV types.
>
> This attribute is valid if and only if the mrvv-vector-bits=zvl, the only
> one args should be the integer constant and its' value is terminated
> by the LMUL and the vector register bits in zvl*b.  For example:
>
> typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128)));
>
> The above type define is valid when -march=rv64gc_zve64d_zvl64b
> (aka 2(m2) * 64 = 128 for vin32m2_t), and will report error when
> -march=rv64gcv_zvl128b similar to below.
>
> "error: invalid RVV vector size '128', expected size is '256' based on
> LMUL of type and '-mrvv-vector-bits=zvl'"
>
> Meanwhile, a pre-define macro __riscv_v_fixed_vlen is introduced to
> represent the fixed vlen in a RVV vector register.
>
> For the vint*m*_t below operations are allowed.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
> * CMP: >, <, ==, !=, <=, >=
> * ALU: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> The CMP will return vint*m*_t the same as aarch64 sve. For example:
> typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128)));
> fixed_vint32m1_t less_than (fixed_vint32m1_t a, fixed_vint32m1_t b)
> {
>   return a < b;
> }
>
> For the vfloat*m*_t below operations are allowed.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
> * CMP: >, <, ==, !=, <=, >=
> * ALU: +, -, *, /, -
>
> The CMP will return vfloat*m*_t the same as aarch64 sve. For example:
> typedef vfloat32m1_t fixed_vfloat32m1_t __attribute__((riscv_rvv_vector_bits(128)));
> fixed_vfloat32m1_t less_than (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> {
>   return a < b;
> }
>
> For the vbool*_t types only below operations are allowed except
> the CMP and ALU. The CMP and ALU operations on vbool*_t is not
> well defined currently.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
>
> For the vint*x*m*_t tuple types are not suppored in this patch which is
> compatible with clang.
>
> This patch passed the below testsuites.
> * The riscv fully regression tests.
>
> gcc/ChangeLog:
>
>         * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Add pre-define
>         macro __riscv_v_fixed_vlen when zvl.
>         * config/riscv/riscv.cc (riscv_handle_rvv_vector_bits_attribute):
>         New static func to take care of the RVV types decorated by
>         the attributes.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h: New test.
>
> Signed-off-by: Pan Li <pan2.li@intel.com>
> ---
>  gcc/config/riscv/riscv-c.cc                   |   3 +
>  gcc/config/riscv/riscv.cc                     |  87 +++++++++++++-
>  .../riscv/rvv/base/riscv_rvv_vector_bits-1.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-10.c |  53 +++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-11.c |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-12.c |  14 +++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-13.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-14.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-15.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-16.c |  11 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-17.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-18.c |  45 ++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-2.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-3.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-4.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-5.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-6.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-7.c  |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-8.c  |  75 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-9.c  |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits.h    | 108 ++++++++++++++++++
>  21 files changed, 698 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
>
> diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
> index 7029ba88186..edb866d51e4 100644
> --- a/gcc/config/riscv/riscv-c.cc
> +++ b/gcc/config/riscv/riscv-c.cc
> @@ -140,6 +140,9 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
>        builtin_define ("__riscv_vector");
>        builtin_define_with_int_value ("__riscv_v_intrinsic",
>                                      riscv_ext_version_value (0, 12));
> +
> +      if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL)
> +       builtin_define_with_int_value ("__riscv_v_fixed_vlen", TARGET_MIN_VLEN);
>      }
>
>    if (TARGET_XTHEADVECTOR)
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 02a927f96b4..14f5b634ea1 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -552,6 +552,8 @@ static const struct riscv_tune_param optimize_size_tune_info = {
>  static bool riscv_avoid_shrink_wrapping_separate ();
>  static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
>  static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
> +static tree riscv_handle_rvv_vector_bits_attribute (tree *, tree, tree, int,
> +                                                   bool *);
>
>  /* Defining target-specific uses of __attribute__.  */
>  static const attribute_spec riscv_gnu_attributes[] =
> @@ -574,7 +576,17 @@ static const attribute_spec riscv_gnu_attributes[] =
>    /* This attribute is used to declare a function, forcing it to use the
>      standard vector calling convention variant. Syntax:
>      __attribute__((riscv_vector_cc)). */
> -  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL}
> +  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL},
> +  /* This attribute is used to declare a new type, to appoint the exactly
> +     bits size of the type.  For example:
> +
> +     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
> +
> +     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
> +     be used in globals, structs, unions, and arrays instead of sizeless
> +     types.  */
> +  {"riscv_rvv_vector_bits", 1, 1, false, true, false, true,
> +   riscv_handle_rvv_vector_bits_attribute, NULL},
>  };
>
>  static const scoped_attribute_specs riscv_gnu_attribute_table  =
> @@ -587,7 +599,17 @@ static const attribute_spec riscv_attributes[] =
>    /* This attribute is used to declare a function, forcing it to use the
>       standard vector calling convention variant. Syntax:
>       [[riscv::vector_cc]]. */
> -  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL}
> +  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL},
> +  /* This attribute is used to declare a new type, to appoint the exactly
> +     bits size of the type.  For example:
> +
> +     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
> +
> +     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
> +     be used in globals, structs, unions, and arrays instead of sizeless
> +     types.  */
> +  {"rvv_vector_bits", 1, 1, false, true, false, true,
> +   riscv_handle_rvv_vector_bits_attribute, NULL},
>  };
>
>  static const scoped_attribute_specs riscv_nongnu_attribute_table =
> @@ -5573,6 +5595,67 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
>    return NULL_TREE;
>  }
>
> +static tree
> +riscv_handle_rvv_vector_bits_attribute (tree *node, tree name, tree args,
> +                                       ATTRIBUTE_UNUSED int flags,
> +                                       bool *no_add_attrs)
> +{
> +  if (!is_attribute_p ("riscv_rvv_vector_bits", name))
> +    return NULL_TREE;
> +
> +  *no_add_attrs = true;
> +
> +  if (rvv_vector_bits != RVV_VECTOR_BITS_ZVL)
> +    {
> +      error (
> +       "%qs is only supported when %<-mrvv-vector-bits=zvl%> is specified",
> +       "riscv_rvv_vector_bits");
> +      return NULL_TREE;
> +    }
> +
> +  tree type = *node;
> +
> +  if (!VECTOR_TYPE_P (type) || !riscv_vector::builtin_type_p (type))
> +    {
> +      error ("%qs applied to non-RVV type %qT", "riscv_rvv_vector_bits", type);
> +      return NULL_TREE;
> +    }
> +
> +  tree size = TREE_VALUE (args);
> +
> +  if (TREE_CODE (size) != INTEGER_CST)
> +    {
> +      error ("%qs requires an integer constant", "riscv_rvv_vector_bits");
> +      return NULL_TREE;
> +    }
> +
> +  unsigned HOST_WIDE_INT args_in_bits = tree_to_uhwi (size);
> +  unsigned HOST_WIDE_INT type_mode_bits
> +    = GET_MODE_PRECISION (TYPE_MODE (type)).to_constant ();
> +
> +  if (args_in_bits != type_mode_bits)
> +    {
> +      error ("invalid RVV vector size %qd, "
> +            "expected size is %qd based on LMUL of type and %qs",
> +            (int)args_in_bits, (int)type_mode_bits, "-mrvv-vector-bits=zvl");
> +      return NULL_TREE;
> +    }
> +
> +  type = build_distinct_type_copy (type);
> +  TYPE_ATTRIBUTES (type)
> +    = remove_attribute ("RVV sizeless type",
> +                       copy_list (TYPE_ATTRIBUTES (type)));
> +
> +  /* The operations like alu/cmp on vbool*_t is not well defined,
> +     continue to treat vbool*_t as indivisible.  */
> +  if (!VECTOR_BOOLEAN_TYPE_P (type))
> +    TYPE_INDIVISIBLE_P (type) = 0;
> +
> +  *node = type;
> +
> +  return NULL_TREE;
> +}
> +
>  /* Return true if function TYPE is an interrupt function.  */
>  static bool
>  riscv_interrupt_type_p (tree type)
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
> new file mode 100644
> index 00000000000..8b08ba28130
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef int fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' applied to non-RVV type 'int'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
> new file mode 100644
> index 00000000000..0ff48a29f7e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
> @@ -0,0 +1,53 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_zve32f_zvl32b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  8,  v1qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 16,  v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  32,  v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  64,  v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 128, v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 256, v32qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  16,  v1hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,   64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  256, v16hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  32, v1si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  64, v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 128, v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 256, v8si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  8,  v1uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 16,  v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  32,  v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  64,  v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 128, v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 256, v32uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  16,  v1uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,   64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  256, v16uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  32, v1usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  64, v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 128, v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 256, v8usi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  16,  v1hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,   64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  256, v16hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  32, v1sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  64, v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 128, v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 256, v8sf)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
> new file mode 100644
> index 00000000000..726c56b4a7e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl4096b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  512,   v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 1024,  v128qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 2048,  v256qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  4096,  v512qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  8192, v1024qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 16384, v2048qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 32768, v4096qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t, 1024,   v64hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 2048,  v128hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  4096,  v256hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  8192,  v512hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 16384, v1024hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 32768, v2048hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 2048,   v64si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  4096,  v128si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  8192,  v256si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 16384,  v512si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 32768, v1024si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  4096,  v64di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  8192, v128di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 16384, v256di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 32768, v512di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  512,   v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 1024,  v128uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 2048,  v256uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  4096,  v512uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  8192, v1024uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 16384, v2048uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 32768, v4096uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t, 1024,   v64uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 2048,  v128uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  4096,  v256uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  8192,  v512uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 16384, v1024uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 32768, v2048uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 2048,   v64usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  4096,  v128usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  8192,  v256usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 16384,  v512usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 32768, v1024usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  4096,  v64udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  8192, v128udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 16384, v256udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 32768, v512udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t, 1024,   v64hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 2048,  v128hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  4096,  v256hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  8192,  v512hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 16384, v1024hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 32768, v2048hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 2048,   v64sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  4096,  v128sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  8192,  v256sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 16384,  v512sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 32768, v1024sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  4096,  v64df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  8192, v128df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 16384, v256df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 32768, v512df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
> new file mode 100644
> index 00000000000..5c2346dff3e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_BOOL_ALL (vbool1_t, 128, v16qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool2_t,  64,  v8qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool4_t,  32,  v4qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool8_t,  16,  v2qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool16_t,  8,  v1qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool32_t,  4,  v1qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool64_t,  2,  v1qi)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
> new file mode 100644
> index 00000000000..71d8b597da0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */
> +
> +void test () {
> +
> +#if defined __riscv_v_fixed_vlen
> +#error "__riscv_v_fixed_vlen should not be defined"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
> new file mode 100644
> index 00000000000..b60ae4d20ff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 128
> +#error "__riscv_v_fixed_vlen should be 128"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
> new file mode 100644
> index 00000000000..95edbbbd38d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 512
> +#error "__riscv_v_fixed_vlen should be 512"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
> new file mode 100644
> index 00000000000..df73f203791
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
> @@ -0,0 +1,11 @@
> +
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=scalable -O3" } */
> +
> +void test () {
> +
> +#if defined __riscv_v_fixed_vlen
> +#error "__riscv_v_fixed_vlen should not be defined"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
> new file mode 100644
> index 00000000000..fa39a18d47c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 4096
> +#error "__riscv_v_fixed_vlen should be 4096"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
> new file mode 100644
> index 00000000000..a7530e27d8f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
> @@ -0,0 +1,45 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +DEF_FIXED_TYPE (vint32m1_t, 256)
> +DEF_FIXED_TYPE (vfloat32m1_t, 256)
> +DEF_FIXED_TYPE (vbool1_t, 256)
> +DEF_FIXED_TYPE (vbool2_t, 128)
> +
> +fixed_vint32m1_t
> +test_1 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool1_t
> +test_2 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vfloat32m1_t
> +test_3 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool1_t
> +test_4 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool2_t
> +test_5 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
> +}
> +
> +fixed_vbool2_t
> +test_6 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
> new file mode 100644
> index 00000000000..6b841d7b1d4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits("123"))); /* { dg-error "'riscv_rvv_vector_bits' requires an integer constant" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
> new file mode 100644
> index 00000000000..e1b0664eacb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' is only supported when '-mrvv-vector-bits=zvl' is specified" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
> new file mode 100644
> index 00000000000..eef15654110
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
> new file mode 100644
> index 00000000000..6b4f19cd9f2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
> new file mode 100644
> index 00000000000..bc346917fe5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32mf2_t fixed_vint32mf2_t __attribute__((riscv_rvv_vector_bits(256))); /* { dg-error "invalid RVV vector size '256', expected size is '128' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
> new file mode 100644
> index 00000000000..611a4bb88ba
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  16,   v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  32,   v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t,  64,   v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  128,  v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  256,  v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t,  512,  v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 1024, v128qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  256, v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  512, v32hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 1024, v64hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t,  64,  v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t,  512, v16si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 1024, v32si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  128,  v2di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  256,  v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t,  512,  v8di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 1024, v16di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  16,   v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  32,   v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t,  64,   v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  128,  v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  256,  v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t,  512,  v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 1024, v128uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  256, v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  512, v32uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 1024, v64uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t,  64,  v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t,  512, v16usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 1024, v32usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  128,  v2udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  256,  v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t,  512,  v8udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 1024, v16udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  256, v16hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  512, v32hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 1024, v64hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t,  64,  v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  128,  v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  256,  v8sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t,  512, v16sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 1024, v32sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  128,  v2df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  256,  v4df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t,  512,  v8df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 1024, v16df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
> new file mode 100644
> index 00000000000..bb8d1da72b2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
> @@ -0,0 +1,75 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  32,   v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  64,   v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 128,  v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  256,  v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  512,  v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 1024, v128qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 2048, v256qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  64,   v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 128,   v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  256,  v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  512,  v32hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 1024,  v64hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 2048, v128hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  512, v16si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 1024, v32si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 2048, v64si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  256,  v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  512,  v8di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 1024, v16di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 2048, v32di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  64,   v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 128,  v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  256,  v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  512,  v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 1024, v128uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 2048, v256uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  64,   v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 128,   v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  256,  v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  512,  v32uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 1024,  v64uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 2048, v128uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  512, v16usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 1024, v32usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 2048, v64usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  256,  v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  512,  v8udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 1024, v16udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 2048, v32udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  64,   v4hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 128,   v8hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  256,  v16hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  512,  v32hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 1024,  v64hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 2048, v128hi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 128,  v4si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  256,  v8si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  512, v16si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 1024, v32si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 2048, v64si)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  256,  v4di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  512,  v8di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 1024, v16di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 2048, v32di)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
> new file mode 100644
> index 00000000000..701f833b41b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_zve64d_zvl64b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  8,  v1qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 16,  v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 32,  v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  64,  v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t, 128, v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 256, v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 512, v64qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  16,  v1hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  256, v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  512, v32hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 32,  v1si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  64,  v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t, 128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 512, v16si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  64, v1di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t, 128, v2di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 256, v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 512, v8di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  8,  v1uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 16,  v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 32,  v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  64,  v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t, 128, v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 256, v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 512, v64uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  16,  v1uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  256, v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  512, v32uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 32,  v1usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  64,  v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t, 128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 512, v16usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  64, v1udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t, 128, v2udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 256, v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 512, v8udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  16,  v1hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  256, v16hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  512, v32hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 32,  v1sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  64,  v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t, 128,  v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 256,  v8sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 512, v16sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  64, v1df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t, 128, v2df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 256, v4df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 512, v8df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> new file mode 100644
> index 00000000000..fd2d352d3e1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> @@ -0,0 +1,108 @@
> +#ifndef HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
> +#define HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
> +
> +#include "riscv_vector.h"
> +#include "../autovec/vls/def.h"
> +
> +#define DEF_FIXED_TYPE(T, N)                                                   \
> +  typedef T fixed_##T __attribute__((riscv_rvv_vector_bits(N)));
> +
> +#define DEF_FIXED_GLOBAL_VAR(T, N)                                             \
> +  fixed_##T global_fixed_##T##_##N##_bits_var;
> +
> +#define DEF_FIXED_STRUCT_TYPE(T, N)                                            \
> +  struct fixed_##T##_##N##_bits_struct                                         \
> +  {                                                                            \
> +    fixed_##T a, b[2];                                                         \
> +  };
> +
> +#define DEF_FIXED_UNION_TYPE(T, N)                                             \
> +  union fixed_##T##_##N##_bits_union                                           \
> +  {                                                                            \
> +    fixed_##T a, b[3];                                                         \
> +  };
> +
> +#define DEF_FIXED_TYPE_SIZE(T, N)                                              \
> +  void test_fixed_##T##_##N##_bits_size ()                                     \
> +  {                                                                            \
> +    _Static_assert (sizeof (fixed_##T) * 8 == (N < 8 ? 8 : N),                 \
> +                   "Fixed RVV register types should be equal.");              \
> +  }
> +
> +#define DEF_FIXED_TYPE_CVT(T, N, NEW_TYPE)                                     \
> +  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)                       \
> +  {                                                                            \
> +    return (NEW_TYPE) a;                                                       \
> +  }
> +
> +#define DEF_FIXED_BINARY(T, N, OP, NAME)                                       \
> +  fixed_##T test_fixed_##T##_##N##_bits_binary_##NAME (fixed_##T a,            \
> +                                                      fixed_##T b)            \
> +  {                                                                            \
> +    return a OP b;                                                             \
> +  }
> +
> +#define DEF_FIXED_UNARY(T, N, OP, NAME)                                        \
> +  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)             \
> +  {                                                                            \
> +    return OP a;                                                               \
> +  }
> +
> +#define DEF_FIXED_TYPE_CMP(T, N)                                               \
> +  DEF_FIXED_BINARY(T, N, ==, eq)                                               \
> +  DEF_FIXED_BINARY(T, N, !=, ne)                                               \
> +  DEF_FIXED_BINARY(T, N, >,  gt)                                               \
> +  DEF_FIXED_BINARY(T, N, <,  lt)                                               \
> +  DEF_FIXED_BINARY(T, N, >=, ge)                                               \
> +  DEF_FIXED_BINARY(T, N, <=, le)
> +
> +#define DEF_FIXED_TYPE_INT_ALU(T, N)                                           \
> +  DEF_FIXED_BINARY(T, N, +,  add)                                              \
> +  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
> +  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
> +  DEF_FIXED_BINARY(T, N, /,  div)                                              \
> +  DEF_FIXED_BINARY(T, N, %,  mod)                                              \
> +  DEF_FIXED_BINARY(T, N, &,  and)                                              \
> +  DEF_FIXED_BINARY(T, N, |,  ior)                                              \
> +  DEF_FIXED_BINARY(T, N, ^,  xor)                                              \
> +  DEF_FIXED_BINARY(T, N, >>, rsh)                                              \
> +  DEF_FIXED_BINARY(T, N, <<, lsh)                                              \
> +  DEF_FIXED_UNARY(T, N, ~, not)                                                \
> +  DEF_FIXED_UNARY(T, N, -, neg)
> +
> +#define DEF_FIXED_TYPE_FLOAT_ALU(T, N)                                         \
> +  DEF_FIXED_BINARY(T, N, +,  add)                                              \
> +  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
> +  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
> +  DEF_FIXED_BINARY(T, N, /,  div)                                              \
> +  DEF_FIXED_UNARY(T, N, -,  neg)
> +
> +#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                                \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
> +  DEF_FIXED_TYPE_CMP (T, N)                                                    \
> +  DEF_FIXED_TYPE_INT_ALU (T, N)                                                \
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                              \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
> +  DEF_FIXED_TYPE_CMP (T, N)                                                    \
> +  DEF_FIXED_TYPE_FLOAT_ALU (T, N)                                              \
> +
> +#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                               \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> +
> +#endif
> --
> 2.34.1
>
Li, Pan2 March 22, 2024, 10:39 a.m. UTC | #2
Committed, thanks Kito.

Pan

-----Original Message-----
From: Kito Cheng <kito.cheng@gmail.com> 
Sent: Friday, March 22, 2024 6:06 PM
To: Li, Pan2 <pan2.li@intel.com>
Cc: gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; Wang, Yanzhang <yanzhang.wang@intel.com>; rdapp.gcc@gmail.com; vineetg@rivosinc.com; palmer@rivosinc.com
Subject: Re: [PATCH v4] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV

LGTM, thanks :)

On Fri, Mar 22, 2024 at 2:55 PM <pan2.li@intel.com> wrote:
>
> From: Pan Li <pan2.li@intel.com>
>
> This patch would like to introduce one new gcc attribute for RVV.
> This attribute is used to define fixed-length variants of one
> existing sizeless RVV types.
>
> This attribute is valid if and only if the mrvv-vector-bits=zvl, the only
> one args should be the integer constant and its' value is terminated
> by the LMUL and the vector register bits in zvl*b.  For example:
>
> typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128)));
>
> The above type define is valid when -march=rv64gc_zve64d_zvl64b
> (aka 2(m2) * 64 = 128 for vin32m2_t), and will report error when
> -march=rv64gcv_zvl128b similar to below.
>
> "error: invalid RVV vector size '128', expected size is '256' based on
> LMUL of type and '-mrvv-vector-bits=zvl'"
>
> Meanwhile, a pre-define macro __riscv_v_fixed_vlen is introduced to
> represent the fixed vlen in a RVV vector register.
>
> For the vint*m*_t below operations are allowed.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
> * CMP: >, <, ==, !=, <=, >=
> * ALU: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> The CMP will return vint*m*_t the same as aarch64 sve. For example:
> typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128)));
> fixed_vint32m1_t less_than (fixed_vint32m1_t a, fixed_vint32m1_t b)
> {
>   return a < b;
> }
>
> For the vfloat*m*_t below operations are allowed.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
> * CMP: >, <, ==, !=, <=, >=
> * ALU: +, -, *, /, -
>
> The CMP will return vfloat*m*_t the same as aarch64 sve. For example:
> typedef vfloat32m1_t fixed_vfloat32m1_t __attribute__((riscv_rvv_vector_bits(128)));
> fixed_vfloat32m1_t less_than (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> {
>   return a < b;
> }
>
> For the vbool*_t types only below operations are allowed except
> the CMP and ALU. The CMP and ALU operations on vbool*_t is not
> well defined currently.
> * The sizeof.
> * The global variable(s).
> * The element of union and struct.
> * The cast to other equalities.
>
> For the vint*x*m*_t tuple types are not suppored in this patch which is
> compatible with clang.
>
> This patch passed the below testsuites.
> * The riscv fully regression tests.
>
> gcc/ChangeLog:
>
>         * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Add pre-define
>         macro __riscv_v_fixed_vlen when zvl.
>         * config/riscv/riscv.cc (riscv_handle_rvv_vector_bits_attribute):
>         New static func to take care of the RVV types decorated by
>         the attributes.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c: New test.
>         * gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h: New test.
>
> Signed-off-by: Pan Li <pan2.li@intel.com>
> ---
>  gcc/config/riscv/riscv-c.cc                   |   3 +
>  gcc/config/riscv/riscv.cc                     |  87 +++++++++++++-
>  .../riscv/rvv/base/riscv_rvv_vector_bits-1.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-10.c |  53 +++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-11.c |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-12.c |  14 +++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-13.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-14.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-15.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-16.c |  11 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-17.c |  10 ++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-18.c |  45 ++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-2.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-3.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-4.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-5.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-6.c  |   6 +
>  .../riscv/rvv/base/riscv_rvv_vector_bits-7.c  |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-8.c  |  75 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits-9.c  |  76 ++++++++++++
>  .../riscv/rvv/base/riscv_rvv_vector_bits.h    | 108 ++++++++++++++++++
>  21 files changed, 698 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
>
> diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
> index 7029ba88186..edb866d51e4 100644
> --- a/gcc/config/riscv/riscv-c.cc
> +++ b/gcc/config/riscv/riscv-c.cc
> @@ -140,6 +140,9 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
>        builtin_define ("__riscv_vector");
>        builtin_define_with_int_value ("__riscv_v_intrinsic",
>                                      riscv_ext_version_value (0, 12));
> +
> +      if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL)
> +       builtin_define_with_int_value ("__riscv_v_fixed_vlen", TARGET_MIN_VLEN);
>      }
>
>    if (TARGET_XTHEADVECTOR)
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 02a927f96b4..14f5b634ea1 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -552,6 +552,8 @@ static const struct riscv_tune_param optimize_size_tune_info = {
>  static bool riscv_avoid_shrink_wrapping_separate ();
>  static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
>  static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
> +static tree riscv_handle_rvv_vector_bits_attribute (tree *, tree, tree, int,
> +                                                   bool *);
>
>  /* Defining target-specific uses of __attribute__.  */
>  static const attribute_spec riscv_gnu_attributes[] =
> @@ -574,7 +576,17 @@ static const attribute_spec riscv_gnu_attributes[] =
>    /* This attribute is used to declare a function, forcing it to use the
>      standard vector calling convention variant. Syntax:
>      __attribute__((riscv_vector_cc)). */
> -  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL}
> +  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL},
> +  /* This attribute is used to declare a new type, to appoint the exactly
> +     bits size of the type.  For example:
> +
> +     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
> +
> +     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
> +     be used in globals, structs, unions, and arrays instead of sizeless
> +     types.  */
> +  {"riscv_rvv_vector_bits", 1, 1, false, true, false, true,
> +   riscv_handle_rvv_vector_bits_attribute, NULL},
>  };
>
>  static const scoped_attribute_specs riscv_gnu_attribute_table  =
> @@ -587,7 +599,17 @@ static const attribute_spec riscv_attributes[] =
>    /* This attribute is used to declare a function, forcing it to use the
>       standard vector calling convention variant. Syntax:
>       [[riscv::vector_cc]]. */
> -  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL}
> +  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL},
> +  /* This attribute is used to declare a new type, to appoint the exactly
> +     bits size of the type.  For example:
> +
> +     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
> +
> +     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
> +     be used in globals, structs, unions, and arrays instead of sizeless
> +     types.  */
> +  {"rvv_vector_bits", 1, 1, false, true, false, true,
> +   riscv_handle_rvv_vector_bits_attribute, NULL},
>  };
>
>  static const scoped_attribute_specs riscv_nongnu_attribute_table =
> @@ -5573,6 +5595,67 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
>    return NULL_TREE;
>  }
>
> +static tree
> +riscv_handle_rvv_vector_bits_attribute (tree *node, tree name, tree args,
> +                                       ATTRIBUTE_UNUSED int flags,
> +                                       bool *no_add_attrs)
> +{
> +  if (!is_attribute_p ("riscv_rvv_vector_bits", name))
> +    return NULL_TREE;
> +
> +  *no_add_attrs = true;
> +
> +  if (rvv_vector_bits != RVV_VECTOR_BITS_ZVL)
> +    {
> +      error (
> +       "%qs is only supported when %<-mrvv-vector-bits=zvl%> is specified",
> +       "riscv_rvv_vector_bits");
> +      return NULL_TREE;
> +    }
> +
> +  tree type = *node;
> +
> +  if (!VECTOR_TYPE_P (type) || !riscv_vector::builtin_type_p (type))
> +    {
> +      error ("%qs applied to non-RVV type %qT", "riscv_rvv_vector_bits", type);
> +      return NULL_TREE;
> +    }
> +
> +  tree size = TREE_VALUE (args);
> +
> +  if (TREE_CODE (size) != INTEGER_CST)
> +    {
> +      error ("%qs requires an integer constant", "riscv_rvv_vector_bits");
> +      return NULL_TREE;
> +    }
> +
> +  unsigned HOST_WIDE_INT args_in_bits = tree_to_uhwi (size);
> +  unsigned HOST_WIDE_INT type_mode_bits
> +    = GET_MODE_PRECISION (TYPE_MODE (type)).to_constant ();
> +
> +  if (args_in_bits != type_mode_bits)
> +    {
> +      error ("invalid RVV vector size %qd, "
> +            "expected size is %qd based on LMUL of type and %qs",
> +            (int)args_in_bits, (int)type_mode_bits, "-mrvv-vector-bits=zvl");
> +      return NULL_TREE;
> +    }
> +
> +  type = build_distinct_type_copy (type);
> +  TYPE_ATTRIBUTES (type)
> +    = remove_attribute ("RVV sizeless type",
> +                       copy_list (TYPE_ATTRIBUTES (type)));
> +
> +  /* The operations like alu/cmp on vbool*_t is not well defined,
> +     continue to treat vbool*_t as indivisible.  */
> +  if (!VECTOR_BOOLEAN_TYPE_P (type))
> +    TYPE_INDIVISIBLE_P (type) = 0;
> +
> +  *node = type;
> +
> +  return NULL_TREE;
> +}
> +
>  /* Return true if function TYPE is an interrupt function.  */
>  static bool
>  riscv_interrupt_type_p (tree type)
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
> new file mode 100644
> index 00000000000..8b08ba28130
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef int fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' applied to non-RVV type 'int'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
> new file mode 100644
> index 00000000000..0ff48a29f7e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
> @@ -0,0 +1,53 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_zve32f_zvl32b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  8,  v1qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 16,  v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  32,  v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  64,  v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 128, v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 256, v32qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  16,  v1hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,   64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  256, v16hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  32, v1si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  64, v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 128, v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 256, v8si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  8,  v1uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 16,  v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  32,  v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  64,  v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 128, v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 256, v32uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  16,  v1uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,   64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  256, v16uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  32, v1usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  64, v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 128, v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 256, v8usi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  16,  v1hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,   64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  256, v16hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  32, v1sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  64, v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 128, v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 256, v8sf)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
> new file mode 100644
> index 00000000000..726c56b4a7e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl4096b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  512,   v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 1024,  v128qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 2048,  v256qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  4096,  v512qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  8192, v1024qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 16384, v2048qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 32768, v4096qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t, 1024,   v64hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 2048,  v128hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  4096,  v256hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  8192,  v512hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 16384, v1024hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 32768, v2048hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 2048,   v64si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  4096,  v128si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  8192,  v256si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 16384,  v512si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 32768, v1024si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  4096,  v64di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  8192, v128di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 16384, v256di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 32768, v512di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  512,   v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 1024,  v128uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 2048,  v256uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  4096,  v512uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  8192, v1024uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 16384, v2048uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 32768, v4096uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t, 1024,   v64uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 2048,  v128uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  4096,  v256uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  8192,  v512uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 16384, v1024uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 32768, v2048uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 2048,   v64usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  4096,  v128usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  8192,  v256usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 16384,  v512usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 32768, v1024usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  4096,  v64udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  8192, v128udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 16384, v256udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 32768, v512udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t, 1024,   v64hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 2048,  v128hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  4096,  v256hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  8192,  v512hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 16384, v1024hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 32768, v2048hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 2048,   v64sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  4096,  v128sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  8192,  v256sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 16384,  v512sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 32768, v1024sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  4096,  v64df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  8192, v128df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 16384, v256df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 32768, v512df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
> new file mode 100644
> index 00000000000..5c2346dff3e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_BOOL_ALL (vbool1_t, 128, v16qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool2_t,  64,  v8qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool4_t,  32,  v4qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool8_t,  16,  v2qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool16_t,  8,  v1qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool32_t,  4,  v1qi)
> +TEST_FIXED_TYPE_BOOL_ALL (vbool64_t,  2,  v1qi)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
> new file mode 100644
> index 00000000000..71d8b597da0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */
> +
> +void test () {
> +
> +#if defined __riscv_v_fixed_vlen
> +#error "__riscv_v_fixed_vlen should not be defined"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
> new file mode 100644
> index 00000000000..b60ae4d20ff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 128
> +#error "__riscv_v_fixed_vlen should be 128"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
> new file mode 100644
> index 00000000000..95edbbbd38d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 512
> +#error "__riscv_v_fixed_vlen should be 512"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
> new file mode 100644
> index 00000000000..df73f203791
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
> @@ -0,0 +1,11 @@
> +
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=scalable -O3" } */
> +
> +void test () {
> +
> +#if defined __riscv_v_fixed_vlen
> +#error "__riscv_v_fixed_vlen should not be defined"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
> new file mode 100644
> index 00000000000..fa39a18d47c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +void test () {
> +
> +#if __riscv_v_fixed_vlen != 4096
> +#error "__riscv_v_fixed_vlen should be 4096"
> +#endif
> +
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
> new file mode 100644
> index 00000000000..a7530e27d8f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
> @@ -0,0 +1,45 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +DEF_FIXED_TYPE (vint32m1_t, 256)
> +DEF_FIXED_TYPE (vfloat32m1_t, 256)
> +DEF_FIXED_TYPE (vbool1_t, 256)
> +DEF_FIXED_TYPE (vbool2_t, 128)
> +
> +fixed_vint32m1_t
> +test_1 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool1_t
> +test_2 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vfloat32m1_t
> +test_3 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool1_t
> +test_4 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b;
> +}
> +
> +fixed_vbool2_t
> +test_5 (fixed_vint32m1_t a, fixed_vint32m1_t b)
> +{
> +  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
> +}
> +
> +fixed_vbool2_t
> +test_6 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
> +{
> +  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
> new file mode 100644
> index 00000000000..6b841d7b1d4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits("123"))); /* { dg-error "'riscv_rvv_vector_bits' requires an integer constant" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
> new file mode 100644
> index 00000000000..e1b0664eacb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv -mabi=lp64 -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' is only supported when '-mrvv-vector-bits=zvl' is specified" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
> new file mode 100644
> index 00000000000..eef15654110
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
> new file mode 100644
> index 00000000000..6b4f19cd9f2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
> new file mode 100644
> index 00000000000..bc346917fe5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_vector.h"
> +
> +typedef vint32mf2_t fixed_vint32mf2_t __attribute__((riscv_rvv_vector_bits(256))); /* { dg-error "invalid RVV vector size '256', expected size is '128' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
> new file mode 100644
> index 00000000000..611a4bb88ba
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl128b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  16,   v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  32,   v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t,  64,   v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  128,  v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  256,  v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t,  512,  v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 1024, v128qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  256, v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  512, v32hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 1024, v64hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t,  64,  v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t,  512, v16si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 1024, v32si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  128,  v2di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  256,  v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t,  512,  v8di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 1024, v16di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  16,   v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  32,   v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t,  64,   v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  128,  v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  256,  v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t,  512,  v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 1024, v128uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  256, v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  512, v32uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 1024, v64uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t,  64,  v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t,  512, v16usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 1024, v32usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  128,  v2udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  256,  v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t,  512,  v8udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 1024, v16udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  256, v16hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  512, v32hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 1024, v64hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t,  64,  v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  128,  v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  256,  v8sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t,  512, v16sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 1024, v32sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  128,  v2df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  256,  v4df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t,  512,  v8df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 1024, v16df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
> new file mode 100644
> index 00000000000..bb8d1da72b2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
> @@ -0,0 +1,75 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gcv_zvl256b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  32,   v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  64,   v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 128,  v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  256,  v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  512,  v64qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 1024, v128qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 2048, v256qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  64,   v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 128,   v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  256,  v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  512,  v32hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 1024,  v64hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 2048, v128hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  512, v16si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 1024, v32si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 2048, v64si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  256,  v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  512,  v8di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 1024, v16di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 2048, v32di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  64,   v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 128,  v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  256,  v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  512,  v64uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 1024, v128uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 2048, v256uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  64,   v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 128,   v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  256,  v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  512,  v32uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 1024,  v64uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 2048, v128uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  512, v16usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 1024, v32usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 2048, v64usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  256,  v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  512,  v8udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 1024, v16udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 2048, v32udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  64,   v4hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 128,   v8hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  256,  v16hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  512,  v32hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 1024,  v64hi)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 2048, v128hi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 128,  v4si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  256,  v8si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  512, v16si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 1024, v32si)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 2048, v64si)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  256,  v4di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  512,  v8di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 1024, v16di)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 2048, v32di)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
> new file mode 100644
> index 00000000000..701f833b41b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
> @@ -0,0 +1,76 @@
> +/* { dg-do compile } */
> +/* { dg-options "-march=rv64gc_zve64d_zvl64b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
> +
> +#include "riscv_rvv_vector_bits.h"
> +
> +TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  8,  v1qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 16,  v2qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 32,  v4qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  64,  v8qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m2_t, 128, v16qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 256, v32qi)
> +TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 512, v64qi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  16,  v1hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  32,  v2hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   64,  v4hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  128,  v8hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  256, v16hi)
> +TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  512, v32hi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 32,  v1si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  64,  v2si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m2_t, 128,  v4si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 256,  v8si)
> +TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 512, v16si)
> +
> +TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  64, v1di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m2_t, 128, v2di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 256, v4di)
> +TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 512, v8di)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  8,  v1uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 16,  v2uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 32,  v4uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  64,  v8uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m2_t, 128, v16uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 256, v32uqi)
> +TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 512, v64uqi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  16,  v1uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  32,  v2uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   64,  v4uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  128,  v8uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  256, v16uhi)
> +TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  512, v32uhi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 32,  v1usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  64,  v2usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m2_t, 128,  v4usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 256,  v8usi)
> +TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 512, v16usi)
> +
> +TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  64, v1udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m2_t, 128, v2udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 256, v4udi)
> +TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 512, v8udi)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  16,  v1hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  32,  v2hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   64,  v4hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  128,  v8hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  256, v16hf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  512, v32hf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 32,  v1sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  64,  v2sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t, 128,  v4sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 256,  v8sf)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 512, v16sf)
> +
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  64, v1df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t, 128, v2df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 256, v4df)
> +TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 512, v8df)
> +
> +/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> new file mode 100644
> index 00000000000..fd2d352d3e1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> @@ -0,0 +1,108 @@
> +#ifndef HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
> +#define HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
> +
> +#include "riscv_vector.h"
> +#include "../autovec/vls/def.h"
> +
> +#define DEF_FIXED_TYPE(T, N)                                                   \
> +  typedef T fixed_##T __attribute__((riscv_rvv_vector_bits(N)));
> +
> +#define DEF_FIXED_GLOBAL_VAR(T, N)                                             \
> +  fixed_##T global_fixed_##T##_##N##_bits_var;
> +
> +#define DEF_FIXED_STRUCT_TYPE(T, N)                                            \
> +  struct fixed_##T##_##N##_bits_struct                                         \
> +  {                                                                            \
> +    fixed_##T a, b[2];                                                         \
> +  };
> +
> +#define DEF_FIXED_UNION_TYPE(T, N)                                             \
> +  union fixed_##T##_##N##_bits_union                                           \
> +  {                                                                            \
> +    fixed_##T a, b[3];                                                         \
> +  };
> +
> +#define DEF_FIXED_TYPE_SIZE(T, N)                                              \
> +  void test_fixed_##T##_##N##_bits_size ()                                     \
> +  {                                                                            \
> +    _Static_assert (sizeof (fixed_##T) * 8 == (N < 8 ? 8 : N),                 \
> +                   "Fixed RVV register types should be equal.");              \
> +  }
> +
> +#define DEF_FIXED_TYPE_CVT(T, N, NEW_TYPE)                                     \
> +  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)                       \
> +  {                                                                            \
> +    return (NEW_TYPE) a;                                                       \
> +  }
> +
> +#define DEF_FIXED_BINARY(T, N, OP, NAME)                                       \
> +  fixed_##T test_fixed_##T##_##N##_bits_binary_##NAME (fixed_##T a,            \
> +                                                      fixed_##T b)            \
> +  {                                                                            \
> +    return a OP b;                                                             \
> +  }
> +
> +#define DEF_FIXED_UNARY(T, N, OP, NAME)                                        \
> +  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)             \
> +  {                                                                            \
> +    return OP a;                                                               \
> +  }
> +
> +#define DEF_FIXED_TYPE_CMP(T, N)                                               \
> +  DEF_FIXED_BINARY(T, N, ==, eq)                                               \
> +  DEF_FIXED_BINARY(T, N, !=, ne)                                               \
> +  DEF_FIXED_BINARY(T, N, >,  gt)                                               \
> +  DEF_FIXED_BINARY(T, N, <,  lt)                                               \
> +  DEF_FIXED_BINARY(T, N, >=, ge)                                               \
> +  DEF_FIXED_BINARY(T, N, <=, le)
> +
> +#define DEF_FIXED_TYPE_INT_ALU(T, N)                                           \
> +  DEF_FIXED_BINARY(T, N, +,  add)                                              \
> +  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
> +  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
> +  DEF_FIXED_BINARY(T, N, /,  div)                                              \
> +  DEF_FIXED_BINARY(T, N, %,  mod)                                              \
> +  DEF_FIXED_BINARY(T, N, &,  and)                                              \
> +  DEF_FIXED_BINARY(T, N, |,  ior)                                              \
> +  DEF_FIXED_BINARY(T, N, ^,  xor)                                              \
> +  DEF_FIXED_BINARY(T, N, >>, rsh)                                              \
> +  DEF_FIXED_BINARY(T, N, <<, lsh)                                              \
> +  DEF_FIXED_UNARY(T, N, ~, not)                                                \
> +  DEF_FIXED_UNARY(T, N, -, neg)
> +
> +#define DEF_FIXED_TYPE_FLOAT_ALU(T, N)                                         \
> +  DEF_FIXED_BINARY(T, N, +,  add)                                              \
> +  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
> +  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
> +  DEF_FIXED_BINARY(T, N, /,  div)                                              \
> +  DEF_FIXED_UNARY(T, N, -,  neg)
> +
> +#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                                \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
> +  DEF_FIXED_TYPE_CMP (T, N)                                                    \
> +  DEF_FIXED_TYPE_INT_ALU (T, N)                                                \
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                              \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
> +  DEF_FIXED_TYPE_CMP (T, N)                                                    \
> +  DEF_FIXED_TYPE_FLOAT_ALU (T, N)                                              \
> +
> +#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                               \
> +  DEF_FIXED_TYPE (T, N)                                                        \
> +  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
> +  DEF_FIXED_UNION_TYPE (T, N)                                                  \
> +  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> +
> +#endif
> --
> 2.34.1
>
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 7029ba88186..edb866d51e4 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -140,6 +140,9 @@  riscv_cpu_cpp_builtins (cpp_reader *pfile)
       builtin_define ("__riscv_vector");
       builtin_define_with_int_value ("__riscv_v_intrinsic",
 				     riscv_ext_version_value (0, 12));
+
+      if (rvv_vector_bits == RVV_VECTOR_BITS_ZVL)
+	builtin_define_with_int_value ("__riscv_v_fixed_vlen", TARGET_MIN_VLEN);
     }
 
   if (TARGET_XTHEADVECTOR)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 02a927f96b4..14f5b634ea1 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -552,6 +552,8 @@  static const struct riscv_tune_param optimize_size_tune_info = {
 static bool riscv_avoid_shrink_wrapping_separate ();
 static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
 static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
+static tree riscv_handle_rvv_vector_bits_attribute (tree *, tree, tree, int,
+						    bool *);
 
 /* Defining target-specific uses of __attribute__.  */
 static const attribute_spec riscv_gnu_attributes[] =
@@ -574,7 +576,17 @@  static const attribute_spec riscv_gnu_attributes[] =
   /* This attribute is used to declare a function, forcing it to use the
     standard vector calling convention variant. Syntax:
     __attribute__((riscv_vector_cc)). */
-  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL}
+  {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL},
+  /* This attribute is used to declare a new type, to appoint the exactly
+     bits size of the type.  For example:
+
+     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
+
+     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
+     be used in globals, structs, unions, and arrays instead of sizeless
+     types.  */
+  {"riscv_rvv_vector_bits", 1, 1, false, true, false, true,
+   riscv_handle_rvv_vector_bits_attribute, NULL},
 };
 
 static const scoped_attribute_specs riscv_gnu_attribute_table  =
@@ -587,7 +599,17 @@  static const attribute_spec riscv_attributes[] =
   /* This attribute is used to declare a function, forcing it to use the
      standard vector calling convention variant. Syntax:
      [[riscv::vector_cc]]. */
-  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL}
+  {"vector_cc", 0, 0, false, true, true, true, NULL, NULL},
+  /* This attribute is used to declare a new type, to appoint the exactly
+     bits size of the type.  For example:
+
+     typedef vint8m1_t f_vint8m1_t __attribute__((riscv_rvv_vector_bits(256)));
+
+     The new created type f_vint8m1_t will be exactly 256 bits.  It can be
+     be used in globals, structs, unions, and arrays instead of sizeless
+     types.  */
+  {"rvv_vector_bits", 1, 1, false, true, false, true,
+   riscv_handle_rvv_vector_bits_attribute, NULL},
 };
 
 static const scoped_attribute_specs riscv_nongnu_attribute_table =
@@ -5573,6 +5595,67 @@  riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args,
   return NULL_TREE;
 }
 
+static tree
+riscv_handle_rvv_vector_bits_attribute (tree *node, tree name, tree args,
+					ATTRIBUTE_UNUSED int flags,
+					bool *no_add_attrs)
+{
+  if (!is_attribute_p ("riscv_rvv_vector_bits", name))
+    return NULL_TREE;
+
+  *no_add_attrs = true;
+
+  if (rvv_vector_bits != RVV_VECTOR_BITS_ZVL)
+    {
+      error (
+	"%qs is only supported when %<-mrvv-vector-bits=zvl%> is specified",
+	"riscv_rvv_vector_bits");
+      return NULL_TREE;
+    }
+
+  tree type = *node;
+
+  if (!VECTOR_TYPE_P (type) || !riscv_vector::builtin_type_p (type))
+    {
+      error ("%qs applied to non-RVV type %qT", "riscv_rvv_vector_bits", type);
+      return NULL_TREE;
+    }
+
+  tree size = TREE_VALUE (args);
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      error ("%qs requires an integer constant", "riscv_rvv_vector_bits");
+      return NULL_TREE;
+    }
+
+  unsigned HOST_WIDE_INT args_in_bits = tree_to_uhwi (size);
+  unsigned HOST_WIDE_INT type_mode_bits
+    = GET_MODE_PRECISION (TYPE_MODE (type)).to_constant ();
+
+  if (args_in_bits != type_mode_bits)
+    {
+      error ("invalid RVV vector size %qd, "
+	     "expected size is %qd based on LMUL of type and %qs",
+	     (int)args_in_bits, (int)type_mode_bits, "-mrvv-vector-bits=zvl");
+      return NULL_TREE;
+    }
+
+  type = build_distinct_type_copy (type);
+  TYPE_ATTRIBUTES (type)
+    = remove_attribute ("RVV sizeless type",
+			copy_list (TYPE_ATTRIBUTES (type)));
+
+  /* The operations like alu/cmp on vbool*_t is not well defined,
+     continue to treat vbool*_t as indivisible.  */
+  if (!VECTOR_BOOLEAN_TYPE_P (type))
+    TYPE_INDIVISIBLE_P (type) = 0;
+
+  *node = type;
+
+  return NULL_TREE;
+}
+
 /* Return true if function TYPE is an interrupt function.  */
 static bool
 riscv_interrupt_type_p (tree type)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
new file mode 100644
index 00000000000..8b08ba28130
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-1.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_vector.h"
+
+typedef int fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' applied to non-RVV type 'int'" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
new file mode 100644
index 00000000000..0ff48a29f7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-10.c
@@ -0,0 +1,53 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve32f_zvl32b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  8,  v1qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 16,  v2qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  32,  v4qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  64,  v8qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 128, v16qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 256, v32qi)
+
+TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  16,  v1hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   32,  v2hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m2_t,   64,  v4hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  128,  v8hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  256, v16hi)
+
+TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  32, v1si)
+TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  64, v2si)
+TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 128, v4si)
+TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 256, v8si)
+
+TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  8,  v1uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 16,  v2uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  32,  v4uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  64,  v8uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 128, v16uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 256, v32uqi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  16,  v1uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   32,  v2uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,   64,  v4uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  128,  v8uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  256, v16uhi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  32, v1usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  64, v2usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 128, v4usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 256, v8usi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  16,  v1hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   32,  v2hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,   64,  v4hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  128,  v8hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  256, v16hf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  32, v1sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  64, v2sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 128, v4sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 256, v8sf)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
new file mode 100644
index 00000000000..726c56b4a7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-11.c
@@ -0,0 +1,76 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  512,   v64qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 1024,  v128qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 2048,  v256qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  4096,  v512qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  8192, v1024qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 16384, v2048qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 32768, v4096qi)
+
+TEST_FIXED_TYPE_INT_ALL (vint16mf4_t, 1024,   v64hi)
+TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 2048,  v128hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  4096,  v256hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  8192,  v512hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 16384, v1024hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 32768, v2048hi)
+
+TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 2048,   v64si)
+TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  4096,  v128si)
+TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  8192,  v256si)
+TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 16384,  v512si)
+TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 32768, v1024si)
+
+TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  4096,  v64di)
+TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  8192, v128di)
+TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 16384, v256di)
+TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 32768, v512di)
+
+TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  512,   v64uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 1024,  v128uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 2048,  v256uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  4096,  v512uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  8192, v1024uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 16384, v2048uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 32768, v4096uqi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t, 1024,   v64uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 2048,  v128uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  4096,  v256uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  8192,  v512uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 16384, v1024uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 32768, v2048uhi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 2048,   v64usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  4096,  v128usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  8192,  v256usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 16384,  v512usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 32768, v1024usi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  4096,  v64udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  8192, v128udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 16384, v256udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 32768, v512udi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t, 1024,   v64hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 2048,  v128hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  4096,  v256hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  8192,  v512hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 16384, v1024hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 32768, v2048hf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 2048,   v64sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  4096,  v128sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  8192,  v256sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 16384,  v512sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 32768, v1024sf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  4096,  v64df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  8192, v128df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 16384, v256df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 32768, v512df)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
new file mode 100644
index 00000000000..5c2346dff3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-12.c
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_BOOL_ALL (vbool1_t, 128, v16qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool2_t,  64,  v8qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool4_t,  32,  v4qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool8_t,  16,  v2qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool16_t,  8,  v1qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool32_t,  4,  v1qi)
+TEST_FIXED_TYPE_BOOL_ALL (vbool64_t,  2,  v1qi)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
new file mode 100644
index 00000000000..71d8b597da0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-13.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */
+
+void test () {
+
+#if defined __riscv_v_fixed_vlen
+#error "__riscv_v_fixed_vlen should not be defined"
+#endif
+
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
new file mode 100644
index 00000000000..b60ae4d20ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-14.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
+
+void test () {
+
+#if __riscv_v_fixed_vlen != 128
+#error "__riscv_v_fixed_vlen should be 128"
+#endif
+
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
new file mode 100644
index 00000000000..95edbbbd38d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-15.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl512b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
+
+void test () {
+
+#if __riscv_v_fixed_vlen != 512
+#error "__riscv_v_fixed_vlen should be 512"
+#endif
+
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
new file mode 100644
index 00000000000..df73f203791
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-16.c
@@ -0,0 +1,11 @@ 
+
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -mrvv-vector-bits=scalable -O3" } */
+
+void test () {
+
+#if defined __riscv_v_fixed_vlen
+#error "__riscv_v_fixed_vlen should not be defined"
+#endif
+
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
new file mode 100644
index 00000000000..fa39a18d47c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-17.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
+
+void test () {
+
+#if __riscv_v_fixed_vlen != 4096
+#error "__riscv_v_fixed_vlen should be 4096"
+#endif
+
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
new file mode 100644
index 00000000000..a7530e27d8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-18.c
@@ -0,0 +1,45 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64d -O3 -mrvv-vector-bits=zvl" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+DEF_FIXED_TYPE (vint32m1_t, 256)
+DEF_FIXED_TYPE (vfloat32m1_t, 256)
+DEF_FIXED_TYPE (vbool1_t, 256)
+DEF_FIXED_TYPE (vbool2_t, 128)
+
+fixed_vint32m1_t
+test_1 (fixed_vint32m1_t a, fixed_vint32m1_t b)
+{
+  return a == b;
+}
+
+fixed_vbool1_t
+test_2 (fixed_vint32m1_t a, fixed_vint32m1_t b)
+{
+  return a == b;
+}
+
+fixed_vfloat32m1_t
+test_3 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
+{
+  return a == b;
+}
+
+fixed_vbool1_t
+test_4 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
+{
+  return a == b;
+}
+
+fixed_vbool2_t
+test_5 (fixed_vint32m1_t a, fixed_vint32m1_t b)
+{
+  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
+}
+
+fixed_vbool2_t
+test_6 (fixed_vfloat32m1_t a, fixed_vfloat32m1_t b)
+{
+  return a == b; /* { dg-error {incompatible types when returning type '__vector\(8\) int' but 'fixed_vbool2_t' {aka 'vbool2_t'} was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
new file mode 100644
index 00000000000..6b841d7b1d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_vector.h"
+
+typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits("123"))); /* { dg-error "'riscv_rvv_vector_bits' requires an integer constant" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
new file mode 100644
index 00000000000..e1b0664eacb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3" } */
+
+#include "riscv_vector.h"
+
+typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "'riscv_rvv_vector_bits' is only supported when '-mrvv-vector-bits=zvl' is specified" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
new file mode 100644
index 00000000000..eef15654110
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-4.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_vector.h"
+
+typedef vint32m1_t fixed_vint32m1_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
new file mode 100644
index 00000000000..6b4f19cd9f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-5.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl128b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_vector.h"
+
+typedef vint32m2_t fixed_vint32m2_t __attribute__((riscv_rvv_vector_bits(128))); /* { dg-error "invalid RVV vector size '128', expected size is '256' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
new file mode 100644
index 00000000000..bc346917fe5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-6.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_vector.h"
+
+typedef vint32mf2_t fixed_vint32mf2_t __attribute__((riscv_rvv_vector_bits(256))); /* { dg-error "invalid RVV vector size '256', expected size is '128' based on LMUL of type and '-mrvv-vector-bits=zvl'" } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
new file mode 100644
index 00000000000..611a4bb88ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-7.c
@@ -0,0 +1,76 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl128b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  16,   v2qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  32,   v4qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf2_t,  64,   v8qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  128,  v16qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  256,  v32qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m4_t,  512,  v64qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 1024, v128qi)
+
+TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  32,  v2hi)
+TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  64,  v4hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  128,  v8hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  256, v16hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  512, v32hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 1024, v64hi)
+
+TEST_FIXED_TYPE_INT_ALL (vint32mf2_t,  64,  v2si)
+TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  128,  v4si)
+TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  256,  v8si)
+TEST_FIXED_TYPE_INT_ALL (vint32m4_t,  512, v16si)
+TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 1024, v32si)
+
+TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  128,  v2di)
+TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  256,  v4di)
+TEST_FIXED_TYPE_INT_ALL (vint64m4_t,  512,  v8di)
+TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 1024, v16di)
+
+TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  16,   v2uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  32,   v4uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t,  64,   v8uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  128,  v16uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  256,  v32uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m4_t,  512,  v64uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 1024, v128uqi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  32,  v2uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  64,  v4uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  128,  v8uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  256, v16uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  512, v32uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 1024, v64uhi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t,  64,  v2usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  128,  v4usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  256,  v8usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m4_t,  512, v16usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 1024, v32usi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  128,  v2udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  256,  v4udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m4_t,  512,  v8udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 1024, v16udi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  32,  v2hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  64,  v4hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  128,  v8hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  256, v16hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  512, v32hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 1024, v64hf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t,  64,  v2sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  128,  v4sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  256,  v8sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t,  512, v16sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 1024, v32sf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  128,  v2df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  256,  v4df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t,  512,  v8df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 1024, v16df)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
new file mode 100644
index 00000000000..bb8d1da72b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-8.c
@@ -0,0 +1,75 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl256b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  32,   v4qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf4_t,  64,   v8qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 128,  v16qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  256,  v32qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m2_t,  512,  v64qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 1024, v128qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 2048, v256qi)
+
+TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  64,   v4hi)
+TEST_FIXED_TYPE_INT_ALL (vint16mf2_t, 128,   v8hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m1_t,  256,  v16hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  512,  v32hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m4_t, 1024,  v64hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m8_t, 2048, v128hi)
+
+TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 128,  v4si)
+TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  256,  v8si)
+TEST_FIXED_TYPE_INT_ALL (vint32m2_t,  512, v16si)
+TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 1024, v32si)
+TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 2048, v64si)
+
+TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  256,  v4di)
+TEST_FIXED_TYPE_INT_ALL (vint64m2_t,  512,  v8di)
+TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 1024, v16di)
+TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 2048, v32di)
+
+TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t,  64,   v8uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 128,  v16uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  256,  v32uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m2_t,  512,  v64uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 1024, v128uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 2048, v256uqi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  64,   v4uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t, 128,   v8uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,  256,  v16uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  512,  v32uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m4_t, 1024,  v64uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m8_t, 2048, v128uhi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 128,  v4usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  256,  v8usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m2_t,  512, v16usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 1024, v32usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 2048, v64usi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  256,  v4udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m2_t,  512,  v8udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 1024, v16udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 2048, v32udi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  64,   v4hi)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t, 128,   v8hi)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,  256,  v16hi)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  512,  v32hi)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t, 1024,  v64hi)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t, 2048, v128hi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 128,  v4si)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  256,  v8si)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t,  512, v16si)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 1024, v32si)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 2048, v64si)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  256,  v4di)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t,  512,  v8di)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 1024, v16di)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 2048, v32di)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
new file mode 100644
index 00000000000..701f833b41b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits-9.c
@@ -0,0 +1,76 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve64d_zvl64b_zfh_zvfh -mabi=lp64 -mrvv-vector-bits=zvl -O3" } */
+
+#include "riscv_rvv_vector_bits.h"
+
+TEST_FIXED_TYPE_INT_ALL (vint8mf8_t,  8,  v1qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf4_t, 16,  v2qi)
+TEST_FIXED_TYPE_INT_ALL (vint8mf2_t, 32,  v4qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m1_t,  64,  v8qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m2_t, 128, v16qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m4_t, 256, v32qi)
+TEST_FIXED_TYPE_INT_ALL (vint8m8_t, 512, v64qi)
+
+TEST_FIXED_TYPE_INT_ALL (vint16mf4_t,  16,  v1hi)
+TEST_FIXED_TYPE_INT_ALL (vint16mf2_t,  32,  v2hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m1_t,   64,  v4hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m2_t,  128,  v8hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m4_t,  256, v16hi)
+TEST_FIXED_TYPE_INT_ALL (vint16m8_t,  512, v32hi)
+
+TEST_FIXED_TYPE_INT_ALL (vint32mf2_t, 32,  v1si)
+TEST_FIXED_TYPE_INT_ALL (vint32m1_t,  64,  v2si)
+TEST_FIXED_TYPE_INT_ALL (vint32m2_t, 128,  v4si)
+TEST_FIXED_TYPE_INT_ALL (vint32m4_t, 256,  v8si)
+TEST_FIXED_TYPE_INT_ALL (vint32m8_t, 512, v16si)
+
+TEST_FIXED_TYPE_INT_ALL (vint64m1_t,  64, v1di)
+TEST_FIXED_TYPE_INT_ALL (vint64m2_t, 128, v2di)
+TEST_FIXED_TYPE_INT_ALL (vint64m4_t, 256, v4di)
+TEST_FIXED_TYPE_INT_ALL (vint64m8_t, 512, v8di)
+
+TEST_FIXED_TYPE_INT_ALL (vuint8mf8_t,  8,  v1uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf4_t, 16,  v2uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8mf2_t, 32,  v4uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m1_t,  64,  v8uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m2_t, 128, v16uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m4_t, 256, v32uqi)
+TEST_FIXED_TYPE_INT_ALL (vuint8m8_t, 512, v64uqi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint16mf4_t,  16,  v1uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16mf2_t,  32,  v2uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m1_t,   64,  v4uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m2_t,  128,  v8uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m4_t,  256, v16uhi)
+TEST_FIXED_TYPE_INT_ALL (vuint16m8_t,  512, v32uhi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint32mf2_t, 32,  v1usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m1_t,  64,  v2usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m2_t, 128,  v4usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m4_t, 256,  v8usi)
+TEST_FIXED_TYPE_INT_ALL (vuint32m8_t, 512, v16usi)
+
+TEST_FIXED_TYPE_INT_ALL (vuint64m1_t,  64, v1udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m2_t, 128, v2udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m4_t, 256, v4udi)
+TEST_FIXED_TYPE_INT_ALL (vuint64m8_t, 512, v8udi)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf4_t,  16,  v1hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16mf2_t,  32,  v2hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m1_t,   64,  v4hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m2_t,  128,  v8hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m4_t,  256, v16hf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat16m8_t,  512, v32hf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32mf2_t, 32,  v1sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m1_t,  64,  v2sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m2_t, 128,  v4sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m4_t, 256,  v8sf)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat32m8_t, 512, v16sf)
+
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m1_t,  64, v1df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m2_t, 128, v2df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m4_t, 256, v4df)
+TEST_FIXED_TYPE_FLOAT_ALL (vfloat64m8_t, 512, v8df)
+
+/* { dg-final { scan-assembler-not {csrr\s+[atx][0-9]+,\s*vlenb} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
new file mode 100644
index 00000000000..fd2d352d3e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
@@ -0,0 +1,108 @@ 
+#ifndef HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
+#define HAVE_DEF_RISCV_RVV_VECTOR_BITS_H
+
+#include "riscv_vector.h"
+#include "../autovec/vls/def.h"
+
+#define DEF_FIXED_TYPE(T, N)                                                   \
+  typedef T fixed_##T __attribute__((riscv_rvv_vector_bits(N)));
+
+#define DEF_FIXED_GLOBAL_VAR(T, N)                                             \
+  fixed_##T global_fixed_##T##_##N##_bits_var;
+
+#define DEF_FIXED_STRUCT_TYPE(T, N)                                            \
+  struct fixed_##T##_##N##_bits_struct                                         \
+  {                                                                            \
+    fixed_##T a, b[2];                                                         \
+  };
+
+#define DEF_FIXED_UNION_TYPE(T, N)                                             \
+  union fixed_##T##_##N##_bits_union                                           \
+  {                                                                            \
+    fixed_##T a, b[3];                                                         \
+  };
+
+#define DEF_FIXED_TYPE_SIZE(T, N)                                              \
+  void test_fixed_##T##_##N##_bits_size ()                                     \
+  {                                                                            \
+    _Static_assert (sizeof (fixed_##T) * 8 == (N < 8 ? 8 : N),                 \
+		    "Fixed RVV register types should be equal.");              \
+  }
+
+#define DEF_FIXED_TYPE_CVT(T, N, NEW_TYPE)                                     \
+  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)                       \
+  {                                                                            \
+    return (NEW_TYPE) a;                                                       \
+  }
+
+#define DEF_FIXED_BINARY(T, N, OP, NAME)                                       \
+  fixed_##T test_fixed_##T##_##N##_bits_binary_##NAME (fixed_##T a,            \
+						       fixed_##T b)            \
+  {                                                                            \
+    return a OP b;                                                             \
+  }
+
+#define DEF_FIXED_UNARY(T, N, OP, NAME)                                        \
+  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)             \
+  {                                                                            \
+    return OP a;                                                               \
+  }
+
+#define DEF_FIXED_TYPE_CMP(T, N)                                               \
+  DEF_FIXED_BINARY(T, N, ==, eq)                                               \
+  DEF_FIXED_BINARY(T, N, !=, ne)                                               \
+  DEF_FIXED_BINARY(T, N, >,  gt)                                               \
+  DEF_FIXED_BINARY(T, N, <,  lt)                                               \
+  DEF_FIXED_BINARY(T, N, >=, ge)                                               \
+  DEF_FIXED_BINARY(T, N, <=, le)
+
+#define DEF_FIXED_TYPE_INT_ALU(T, N)                                           \
+  DEF_FIXED_BINARY(T, N, +,  add)                                              \
+  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
+  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
+  DEF_FIXED_BINARY(T, N, /,  div)                                              \
+  DEF_FIXED_BINARY(T, N, %,  mod)                                              \
+  DEF_FIXED_BINARY(T, N, &,  and)                                              \
+  DEF_FIXED_BINARY(T, N, |,  ior)                                              \
+  DEF_FIXED_BINARY(T, N, ^,  xor)                                              \
+  DEF_FIXED_BINARY(T, N, >>, rsh)                                              \
+  DEF_FIXED_BINARY(T, N, <<, lsh)                                              \
+  DEF_FIXED_UNARY(T, N, ~, not)                                                \
+  DEF_FIXED_UNARY(T, N, -, neg)
+
+#define DEF_FIXED_TYPE_FLOAT_ALU(T, N)                                         \
+  DEF_FIXED_BINARY(T, N, +,  add)                                              \
+  DEF_FIXED_BINARY(T, N, -,  sub)                                              \
+  DEF_FIXED_BINARY(T, N, *,  mul)                                              \
+  DEF_FIXED_BINARY(T, N, /,  div)                                              \
+  DEF_FIXED_UNARY(T, N, -,  neg)
+
+#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                                \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
+  DEF_FIXED_TYPE_CMP (T, N)                                                    \
+  DEF_FIXED_TYPE_INT_ALU (T, N)                                                \
+
+#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                              \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                          \
+  DEF_FIXED_TYPE_CMP (T, N)                                                    \
+  DEF_FIXED_TYPE_FLOAT_ALU (T, N)                                              \
+
+#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                               \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  DEF_FIXED_TYPE_SIZE (T, N)                                                   \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  DEF_FIXED_TYPE_CVT (T, N, NEW_TYPE)
+
+#endif