diff mbox series

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

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

Commit Message

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

Update in v3:
* Add pre-defined __riscv_v_fixed_vlen when zvl.

Update in v2:
* Cleanup some unused code.
* Fix some typo of commit log.

Original log:

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: +, -, *, /, %, &, |, ^, >>, <<, ~, -

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: +, -, *, /, -

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-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-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 ++++++++++++++++++
 20 files changed, 653 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-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

Stefan O'Rear March 12, 2024, 1:25 p.m. UTC | #1
On Tue, Mar 12, 2024, at 2:15 AM, pan2.li@intel.com wrote:
> From: Pan Li <pan2.li@intel.com>
>
> Update in v3:
> * Add pre-defined __riscv_v_fixed_vlen when zvl.
>
> Update in v2:
> * Cleanup some unused code.
> * Fix some typo of commit log.
>
> Original log:
>
> 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.

Shouldn't a major user-facing change like this be discussed in a PR against
https://github.com/riscv-non-isa/riscv-c-api-doc/ or
https://github.com/riscv-non-isa/rvv-intrinsic-doc before or concurrent with
compiler implementation?

-s

> 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: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> 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: +, -, *, /, -
>
> 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-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-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 ++++++++++++++++++
>  20 files changed, 653 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-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 3755ec0b8ef..d90be2ec0e8 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 680c4a728e9..0bc12d4f595 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -535,6 +535,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[] =
> @@ -557,7 +559,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  =
> @@ -570,7 +582,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 =
> @@ -5555,6 +5577,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-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..a7d68f2c36b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> @@ -0,0 +1,108 @@
> +#ifndef HAVE_TEST_RISCV_RVV_VECTOR_BITS_H
> +#define HAVE_TEST_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 TEST_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 TEST_FIXED_TYPE_CVT(T, N, NEW_TYPE)                            
>         \
> +  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)               
>         \
> +  {                                                                    
>         \
> +    return (NEW_TYPE) a;                                               
>         \
> +  }
> +
> +#define TEST_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 TEST_FIXED_UNARY(T, N, OP, NAME)                               
>         \
> +  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)     
>         \
> +  {                                                                    
>         \
> +    return OP a;                                                       
>         \
> +  }
> +
> +#define TEST_FIXED_TYPE_CMP(T, N)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, ==, eq)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, !=, ne)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, >,  gt)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, <,  lt)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, >=, ge)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, <=, le)
> +
> +#define TEST_FIXED_TYPE_INT_ALU(T, N)                                  
>         \
> +  TEST_FIXED_BINARY(T, N, +,  add)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, -,  sub)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, *,  mul)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, /,  div)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, %,  mod)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, &,  and)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, |,  ior)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, ^,  xor)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, >>, rsh)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, <<, lsh)                                     
>         \
> +  TEST_FIXED_UNARY(T, N, ~, not)                                       
>         \
> +  TEST_FIXED_UNARY(T, N, -, neg)
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALU(T, N)                                
>         \
> +  TEST_FIXED_BINARY(T, N, +,  add)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, -,  sub)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, *,  mul)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, /,  div)                                     
>         \
> +  TEST_FIXED_UNARY(T, N, -,  neg)
> +
> +#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                        
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                 
>         \
> +  TEST_FIXED_TYPE_CMP (T, N)                                           
>         \
> +  TEST_FIXED_TYPE_INT_ALU (T, N)                                       
>         \
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                      
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                 
>         \
> +  TEST_FIXED_TYPE_CMP (T, N)                                           
>         \
> +  TEST_FIXED_TYPE_FLOAT_ALU (T, N)                                     
>         \
> +
> +#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                       
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> +
> +#endif
> -- 
> 2.34.1
Li, Pan2 March 15, 2024, 1:45 a.m. UTC | #2
> Shouldn't a major user-facing change like this be discussed in a PR against
> https://github.com/riscv-non-isa/riscv-c-api-doc/ or
> https://github.com/riscv-non-isa/rvv-intrinsic-doc before or concurrent with
> compiler implementation?

I think Kito is working on the spec doc already.

Hi Kito
Could you please help to correct me the behavior of the riscv_rvv_vector_bits attribute?
Sort of details and I suspect there is something missing, or different behavior compared with clang side.

Pan

-----Original Message-----
From: Stefan O'Rear <sorear@fastmail.com> 
Sent: Tuesday, March 12, 2024 9:25 PM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org
Cc: juzhe.zhong@rivai.ai; Kito Cheng <kito.cheng@gmail.com>; Wang, Yanzhang <yanzhang.wang@intel.com>; rdapp.gcc@gmail.com; Vineet Gupta <vineetg@rivosinc.com>; Palmer Dabbelt <palmer@rivosinc.com>
Subject: Re: [PATCH v3] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV

On Tue, Mar 12, 2024, at 2:15 AM, pan2.li@intel.com wrote:
> From: Pan Li <pan2.li@intel.com>
>
> Update in v3:
> * Add pre-defined __riscv_v_fixed_vlen when zvl.
>
> Update in v2:
> * Cleanup some unused code.
> * Fix some typo of commit log.
>
> Original log:
>
> 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.

Shouldn't a major user-facing change like this be discussed in a PR against
https://github.com/riscv-non-isa/riscv-c-api-doc/ or
https://github.com/riscv-non-isa/rvv-intrinsic-doc before or concurrent with
compiler implementation?

-s

> 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: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> 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: +, -, *, /, -
>
> 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-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-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 ++++++++++++++++++
>  20 files changed, 653 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-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 3755ec0b8ef..d90be2ec0e8 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 680c4a728e9..0bc12d4f595 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -535,6 +535,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[] =
> @@ -557,7 +559,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  =
> @@ -570,7 +582,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 =
> @@ -5555,6 +5577,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-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..a7d68f2c36b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> @@ -0,0 +1,108 @@
> +#ifndef HAVE_TEST_RISCV_RVV_VECTOR_BITS_H
> +#define HAVE_TEST_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 TEST_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 TEST_FIXED_TYPE_CVT(T, N, NEW_TYPE)                            
>         \
> +  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)               
>         \
> +  {                                                                    
>         \
> +    return (NEW_TYPE) a;                                               
>         \
> +  }
> +
> +#define TEST_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 TEST_FIXED_UNARY(T, N, OP, NAME)                               
>         \
> +  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)     
>         \
> +  {                                                                    
>         \
> +    return OP a;                                                       
>         \
> +  }
> +
> +#define TEST_FIXED_TYPE_CMP(T, N)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, ==, eq)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, !=, ne)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, >,  gt)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, <,  lt)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, >=, ge)                                      
>         \
> +  TEST_FIXED_BINARY(T, N, <=, le)
> +
> +#define TEST_FIXED_TYPE_INT_ALU(T, N)                                  
>         \
> +  TEST_FIXED_BINARY(T, N, +,  add)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, -,  sub)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, *,  mul)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, /,  div)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, %,  mod)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, &,  and)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, |,  ior)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, ^,  xor)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, >>, rsh)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, <<, lsh)                                     
>         \
> +  TEST_FIXED_UNARY(T, N, ~, not)                                       
>         \
> +  TEST_FIXED_UNARY(T, N, -, neg)
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALU(T, N)                                
>         \
> +  TEST_FIXED_BINARY(T, N, +,  add)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, -,  sub)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, *,  mul)                                     
>         \
> +  TEST_FIXED_BINARY(T, N, /,  div)                                     
>         \
> +  TEST_FIXED_UNARY(T, N, -,  neg)
> +
> +#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                        
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                 
>         \
> +  TEST_FIXED_TYPE_CMP (T, N)                                           
>         \
> +  TEST_FIXED_TYPE_INT_ALU (T, N)                                       
>         \
> +
> +#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                      
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                 
>         \
> +  TEST_FIXED_TYPE_CMP (T, N)                                           
>         \
> +  TEST_FIXED_TYPE_FLOAT_ALU (T, N)                                     
>         \
> +
> +#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                       
>         \
> +  DEF_FIXED_TYPE (T, N)                                                
>         \
> +  TEST_FIXED_TYPE_SIZE (T, N)                                          
>         \
> +  DEF_FIXED_GLOBAL_VAR (T, N)                                          
>         \
> +  DEF_FIXED_STRUCT_TYPE (T, N)                                         
>         \
> +  DEF_FIXED_UNION_TYPE (T, N)                                          
>         \
> +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> +
> +#endif
> -- 
> 2.34.1
Kito Cheng March 21, 2024, 1:25 p.m. UTC | #3
> 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: >, <, ==, !=, <=, >=

The result of comparison should be vbool* rather than v[u]int*.

> * ALU: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> 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: >, <, ==, !=, <=, >=

The result of comparison should be vbool* rather than vfloat*,
otherwise all 1 is not really meanful for floating point value.

But I know clang generates the same strange/wrong code here...

> * ALU: +, -, *, /, -
>
> 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.

&, ^, | has supported on clang, so I think we should support that as well
Kito Cheng March 21, 2024, 1:28 p.m. UTC | #4
Hi Stefan:

I admit that's kinda bad practice here, the spec should appear before
implementation or at least come together, however we have long
discussion on the RISC-V gcc community on this, and we give a waiver
for this feature due to the clang compatibility, and this features
also used on some project, so we would like to moving this forward
even it's incomplete.

For the spec part, we are working in progress and will put the draft soon.

On Fri, Mar 15, 2024 at 9:46 AM Li, Pan2 <pan2.li@intel.com> wrote:
>
> > Shouldn't a major user-facing change like this be discussed in a PR against
> > https://github.com/riscv-non-isa/riscv-c-api-doc/ or
> > https://github.com/riscv-non-isa/rvv-intrinsic-doc before or concurrent with
> > compiler implementation?
>
> I think Kito is working on the spec doc already.
>
> Hi Kito
> Could you please help to correct me the behavior of the riscv_rvv_vector_bits attribute?
> Sort of details and I suspect there is something missing, or different behavior compared with clang side.
>
> Pan
>
> -----Original Message-----
> From: Stefan O'Rear <sorear@fastmail.com>
> Sent: Tuesday, March 12, 2024 9:25 PM
> To: Li, Pan2 <pan2.li@intel.com>; gcc-patches@gcc.gnu.org
> Cc: juzhe.zhong@rivai.ai; Kito Cheng <kito.cheng@gmail.com>; Wang, Yanzhang <yanzhang.wang@intel.com>; rdapp.gcc@gmail.com; Vineet Gupta <vineetg@rivosinc.com>; Palmer Dabbelt <palmer@rivosinc.com>
> Subject: Re: [PATCH v3] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV
>
> On Tue, Mar 12, 2024, at 2:15 AM, pan2.li@intel.com wrote:
> > From: Pan Li <pan2.li@intel.com>
> >
> > Update in v3:
> > * Add pre-defined __riscv_v_fixed_vlen when zvl.
> >
> > Update in v2:
> > * Cleanup some unused code.
> > * Fix some typo of commit log.
> >
> > Original log:
> >
> > 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.
>
> Shouldn't a major user-facing change like this be discussed in a PR against
> https://github.com/riscv-non-isa/riscv-c-api-doc/ or
> https://github.com/riscv-non-isa/rvv-intrinsic-doc before or concurrent with
> compiler implementation?
>
> -s
>
> > 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: +, -, *, /, %, &, |, ^, >>, <<, ~, -
> >
> > 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: +, -, *, /, -
> >
> > 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-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-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 ++++++++++++++++++
> >  20 files changed, 653 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-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 3755ec0b8ef..d90be2ec0e8 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 680c4a728e9..0bc12d4f595 100644
> > --- a/gcc/config/riscv/riscv.cc
> > +++ b/gcc/config/riscv/riscv.cc
> > @@ -535,6 +535,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[] =
> > @@ -557,7 +559,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  =
> > @@ -570,7 +582,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 =
> > @@ -5555,6 +5577,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-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..a7d68f2c36b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
> > @@ -0,0 +1,108 @@
> > +#ifndef HAVE_TEST_RISCV_RVV_VECTOR_BITS_H
> > +#define HAVE_TEST_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 TEST_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 TEST_FIXED_TYPE_CVT(T, N, NEW_TYPE)
> >         \
> > +  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)
> >         \
> > +  {
> >         \
> > +    return (NEW_TYPE) a;
> >         \
> > +  }
> > +
> > +#define TEST_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 TEST_FIXED_UNARY(T, N, OP, NAME)
> >         \
> > +  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)
> >         \
> > +  {
> >         \
> > +    return OP a;
> >         \
> > +  }
> > +
> > +#define TEST_FIXED_TYPE_CMP(T, N)
> >         \
> > +  TEST_FIXED_BINARY(T, N, ==, eq)
> >         \
> > +  TEST_FIXED_BINARY(T, N, !=, ne)
> >         \
> > +  TEST_FIXED_BINARY(T, N, >,  gt)
> >         \
> > +  TEST_FIXED_BINARY(T, N, <,  lt)
> >         \
> > +  TEST_FIXED_BINARY(T, N, >=, ge)
> >         \
> > +  TEST_FIXED_BINARY(T, N, <=, le)
> > +
> > +#define TEST_FIXED_TYPE_INT_ALU(T, N)
> >         \
> > +  TEST_FIXED_BINARY(T, N, +,  add)
> >         \
> > +  TEST_FIXED_BINARY(T, N, -,  sub)
> >         \
> > +  TEST_FIXED_BINARY(T, N, *,  mul)
> >         \
> > +  TEST_FIXED_BINARY(T, N, /,  div)
> >         \
> > +  TEST_FIXED_BINARY(T, N, %,  mod)
> >         \
> > +  TEST_FIXED_BINARY(T, N, &,  and)
> >         \
> > +  TEST_FIXED_BINARY(T, N, |,  ior)
> >         \
> > +  TEST_FIXED_BINARY(T, N, ^,  xor)
> >         \
> > +  TEST_FIXED_BINARY(T, N, >>, rsh)
> >         \
> > +  TEST_FIXED_BINARY(T, N, <<, lsh)
> >         \
> > +  TEST_FIXED_UNARY(T, N, ~, not)
> >         \
> > +  TEST_FIXED_UNARY(T, N, -, neg)
> > +
> > +#define TEST_FIXED_TYPE_FLOAT_ALU(T, N)
> >         \
> > +  TEST_FIXED_BINARY(T, N, +,  add)
> >         \
> > +  TEST_FIXED_BINARY(T, N, -,  sub)
> >         \
> > +  TEST_FIXED_BINARY(T, N, *,  mul)
> >         \
> > +  TEST_FIXED_BINARY(T, N, /,  div)
> >         \
> > +  TEST_FIXED_UNARY(T, N, -,  neg)
> > +
> > +#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)
> >         \
> > +  DEF_FIXED_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_SIZE (T, N)
> >         \
> > +  DEF_FIXED_GLOBAL_VAR (T, N)
> >         \
> > +  DEF_FIXED_STRUCT_TYPE (T, N)
> >         \
> > +  DEF_FIXED_UNION_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> >         \
> > +  TEST_FIXED_TYPE_CMP (T, N)
> >         \
> > +  TEST_FIXED_TYPE_INT_ALU (T, N)
> >         \
> > +
> > +#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)
> >         \
> > +  DEF_FIXED_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_SIZE (T, N)
> >         \
> > +  DEF_FIXED_GLOBAL_VAR (T, N)
> >         \
> > +  DEF_FIXED_STRUCT_TYPE (T, N)
> >         \
> > +  DEF_FIXED_UNION_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> >         \
> > +  TEST_FIXED_TYPE_CMP (T, N)
> >         \
> > +  TEST_FIXED_TYPE_FLOAT_ALU (T, N)
> >         \
> > +
> > +#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)
> >         \
> > +  DEF_FIXED_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_SIZE (T, N)
> >         \
> > +  DEF_FIXED_GLOBAL_VAR (T, N)
> >         \
> > +  DEF_FIXED_STRUCT_TYPE (T, N)
> >         \
> > +  DEF_FIXED_UNION_TYPE (T, N)
> >         \
> > +  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
> > +
> > +#endif
> > --
> > 2.34.1
Li, Pan2 March 21, 2024, 2:11 p.m. UTC | #5
> The result of comparison should be vbool* rather than v[u]int*.
> The result of comparison should be vbool* rather than vfloat*,
> otherwise all 1 is not really meanful for floating point value.

> But I know clang generates the same strange/wrong code here...

I see, will update the test cases and double check about it in v4.

> &, ^, | has supported on clang, so I think we should support that as well

Looks gcc lack of such operation right now, so mark the TYPE_INDIVISIBLE_P (type) = 0 as aarch64 did.
I have a try but I am afraid we need separated patch to take care of it for risk control consideration.

Pan

-----Original Message-----
From: Kito Cheng <kito.cheng@gmail.com> 
Sent: Thursday, March 21, 2024 9:25 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 v3] RISC-V: Introduce gcc attribute riscv_rvv_vector_bits for RVV

> 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: >, <, ==, !=, <=, >=

The result of comparison should be vbool* rather than v[u]int*.

> * ALU: +, -, *, /, %, &, |, ^, >>, <<, ~, -
>
> 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: >, <, ==, !=, <=, >=

The result of comparison should be vbool* rather than vfloat*,
otherwise all 1 is not really meanful for floating point value.

But I know clang generates the same strange/wrong code here...

> * ALU: +, -, *, /, -
>
> 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.

&, ^, | has supported on clang, so I think we should support that as well
Kito Cheng March 21, 2024, 2:15 p.m. UTC | #6
> > &, ^, | has supported on clang, so I think we should support that as well
>
> Looks gcc lack of such operation right now, so mark the TYPE_INDIVISIBLE_P (type) = 0 as aarch64 did.
> I have a try but I am afraid we need separated patch to take care of it for risk control consideration.

Yeah, agree, that's defer this part to GCC 15 :)
diff mbox series

Patch

diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index 3755ec0b8ef..d90be2ec0e8 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 680c4a728e9..0bc12d4f595 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -535,6 +535,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[] =
@@ -557,7 +559,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  =
@@ -570,7 +582,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 =
@@ -5555,6 +5577,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-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..a7d68f2c36b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/riscv_rvv_vector_bits.h
@@ -0,0 +1,108 @@ 
+#ifndef HAVE_TEST_RISCV_RVV_VECTOR_BITS_H
+#define HAVE_TEST_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 TEST_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 TEST_FIXED_TYPE_CVT(T, N, NEW_TYPE)                                    \
+  NEW_TYPE test_fixed_##T##_##N##_bits_cvt (fixed_##T a)                       \
+  {                                                                            \
+    return (NEW_TYPE) a;                                                       \
+  }
+
+#define TEST_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 TEST_FIXED_UNARY(T, N, OP, NAME)                                       \
+  fixed_##T test_fixed_##T##_##N##_bits_unary_##NAME (fixed_##T a)             \
+  {                                                                            \
+    return OP a;                                                               \
+  }
+
+#define TEST_FIXED_TYPE_CMP(T, N)                                              \
+  TEST_FIXED_BINARY(T, N, ==, eq)                                              \
+  TEST_FIXED_BINARY(T, N, !=, ne)                                              \
+  TEST_FIXED_BINARY(T, N, >,  gt)                                              \
+  TEST_FIXED_BINARY(T, N, <,  lt)                                              \
+  TEST_FIXED_BINARY(T, N, >=, ge)                                              \
+  TEST_FIXED_BINARY(T, N, <=, le)
+
+#define TEST_FIXED_TYPE_INT_ALU(T, N)                                          \
+  TEST_FIXED_BINARY(T, N, +,  add)                                             \
+  TEST_FIXED_BINARY(T, N, -,  sub)                                             \
+  TEST_FIXED_BINARY(T, N, *,  mul)                                             \
+  TEST_FIXED_BINARY(T, N, /,  div)                                             \
+  TEST_FIXED_BINARY(T, N, %,  mod)                                             \
+  TEST_FIXED_BINARY(T, N, &,  and)                                             \
+  TEST_FIXED_BINARY(T, N, |,  ior)                                             \
+  TEST_FIXED_BINARY(T, N, ^,  xor)                                             \
+  TEST_FIXED_BINARY(T, N, >>, rsh)                                             \
+  TEST_FIXED_BINARY(T, N, <<, lsh)                                             \
+  TEST_FIXED_UNARY(T, N, ~, not)                                               \
+  TEST_FIXED_UNARY(T, N, -, neg)
+
+#define TEST_FIXED_TYPE_FLOAT_ALU(T, N)                                        \
+  TEST_FIXED_BINARY(T, N, +,  add)                                             \
+  TEST_FIXED_BINARY(T, N, -,  sub)                                             \
+  TEST_FIXED_BINARY(T, N, *,  mul)                                             \
+  TEST_FIXED_BINARY(T, N, /,  div)                                             \
+  TEST_FIXED_UNARY(T, N, -,  neg)
+
+#define TEST_FIXED_TYPE_INT_ALL(T, N, NEW_TYPE)                                \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  TEST_FIXED_TYPE_SIZE (T, N)                                                  \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                         \
+  TEST_FIXED_TYPE_CMP (T, N)                                                   \
+  TEST_FIXED_TYPE_INT_ALU (T, N)                                               \
+
+#define TEST_FIXED_TYPE_FLOAT_ALL(T, N, NEW_TYPE)                              \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  TEST_FIXED_TYPE_SIZE (T, N)                                                  \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)                                         \
+  TEST_FIXED_TYPE_CMP (T, N)                                                   \
+  TEST_FIXED_TYPE_FLOAT_ALU (T, N)                                             \
+
+#define TEST_FIXED_TYPE_BOOL_ALL(T, N, NEW_TYPE)                               \
+  DEF_FIXED_TYPE (T, N)                                                        \
+  TEST_FIXED_TYPE_SIZE (T, N)                                                  \
+  DEF_FIXED_GLOBAL_VAR (T, N)                                                  \
+  DEF_FIXED_STRUCT_TYPE (T, N)                                                 \
+  DEF_FIXED_UNION_TYPE (T, N)                                                  \
+  TEST_FIXED_TYPE_CVT (T, N, NEW_TYPE)
+
+#endif