diff mbox series

ISC-V: Enable basic RVV auto-vectorization support.

Message ID 20230506014942.1462251-1-juzhe.zhong@rivai.ai
State New
Headers show
Series ISC-V: Enable basic RVV auto-vectorization support. | expand

Commit Message

juzhe.zhong@rivai.ai May 6, 2023, 1:49 a.m. UTC
From: Juzhe-Zhong <juzhe.zhong@rivai.ai>

gcc/ChangeLog:

        * config/riscv/riscv-protos.h (preferred_simd_mode): New function.
        * config/riscv/riscv-v.cc (autovec_use_vlmax_p): Ditto.
        (preferred_simd_mode): Ditto.
        * config/riscv/riscv.cc (riscv_get_arg_info): Handle RVV type in function arg.
        (riscv_convert_vector_bits): Adjust for RVV auto-vectorization.
        (riscv_preferred_simd_mode): New function.
        (TARGET_VECTORIZE_PREFERRED_SIMD_MODE): New target hook support.
        * config/riscv/vector.md: Add autovec.md.
        * config/riscv/autovec.md: New file.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/rvv/rvv.exp: Add testcases for RVV auto-vectorization.
        * gcc.target/riscv/rvv/autovec/fixed-vlmax-1.c: New test.
        * gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.c: New test.
        * gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.h: New test.
        * gcc.target/riscv/rvv/autovec/partial/single_rgroup_run-1.c: New test.
        * gcc.target/riscv/rvv/autovec/scalable-1.c: New test.
        * gcc.target/riscv/rvv/autovec/template-1.h: New test.
        * gcc.target/riscv/rvv/autovec/v-1.c: New test.
        * gcc.target/riscv/rvv/autovec/v-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32f-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32f-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32f-3.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32f_zvl128b-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32f_zvl128b-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32x-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32x-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32x-3.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32x_zvl128b-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve32x_zvl128b-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64d-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64d-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64d-3.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64d_zvl128b-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64d_zvl128b-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64f-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64f-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64f-3.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64f_zvl128b-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64f_zvl128b-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64x-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64x-2.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64x-3.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64x_zvl128b-1.c: New test.
        * gcc.target/riscv/rvv/autovec/zve64x_zvl128b-2.c: New test.

---
 gcc/config/riscv/autovec.md                   |  49 ++++++++
 gcc/config/riscv/riscv-protos.h               |   1 +
 gcc/config/riscv/riscv-v.cc                   |  51 +++++++++
 gcc/config/riscv/riscv.cc                     |  31 ++++-
 gcc/config/riscv/vector.md                    |   4 +-
 .../riscv/rvv/autovec/fixed-vlmax-1.c         |  24 ++++
 .../rvv/autovec/partial/single_rgroup-1.c     |   8 ++
 .../rvv/autovec/partial/single_rgroup-1.h     | 106 ++++++++++++++++++
 .../rvv/autovec/partial/single_rgroup_run-1.c |  19 ++++
 .../gcc.target/riscv/rvv/autovec/scalable-1.c |  15 +++
 .../gcc.target/riscv/rvv/autovec/template-1.h |  68 +++++++++++
 .../gcc.target/riscv/rvv/autovec/v-1.c        |   9 ++
 .../gcc.target/riscv/rvv/autovec/v-2.c        |   6 +
 .../gcc.target/riscv/rvv/autovec/zve32f-1.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve32f-2.c   |   5 +
 .../gcc.target/riscv/rvv/autovec/zve32f-3.c   |   6 +
 .../riscv/rvv/autovec/zve32f_zvl128b-1.c      |   4 +
 .../riscv/rvv/autovec/zve32f_zvl128b-2.c      |   6 +
 .../gcc.target/riscv/rvv/autovec/zve32x-1.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve32x-2.c   |   6 +
 .../gcc.target/riscv/rvv/autovec/zve32x-3.c   |   6 +
 .../riscv/rvv/autovec/zve32x_zvl128b-1.c      |   5 +
 .../riscv/rvv/autovec/zve32x_zvl128b-2.c      |   6 +
 .../gcc.target/riscv/rvv/autovec/zve64d-1.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64d-2.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64d-3.c   |   6 +
 .../riscv/rvv/autovec/zve64d_zvl128b-1.c      |   4 +
 .../riscv/rvv/autovec/zve64d_zvl128b-2.c      |   6 +
 .../gcc.target/riscv/rvv/autovec/zve64f-1.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64f-2.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64f-3.c   |   6 +
 .../riscv/rvv/autovec/zve64f_zvl128b-1.c      |   4 +
 .../riscv/rvv/autovec/zve64f_zvl128b-2.c      |   6 +
 .../gcc.target/riscv/rvv/autovec/zve64x-1.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64x-2.c   |   4 +
 .../gcc.target/riscv/rvv/autovec/zve64x-3.c   |   6 +
 .../riscv/rvv/autovec/zve64x_zvl128b-1.c      |   4 +
 .../riscv/rvv/autovec/zve64x_zvl128b-2.c      |   6 +
 gcc/testsuite/gcc.target/riscv/rvv/rvv.exp    |  16 +++
 39 files changed, 529 insertions(+), 2 deletions(-)
 create mode 100644 gcc/config/riscv/autovec.md
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/fixed-vlmax-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.h
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup_run-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/scalable-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/template-1.h
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/v-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/v-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-2.c
diff mbox series

Patch

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
new file mode 100644
index 00000000000..b5d46ff57ab
--- /dev/null
+++ b/gcc/config/riscv/autovec.md
@@ -0,0 +1,49 @@ 
+;; Machine description for auto-vectorization using RVV for GNU compiler.
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; =========================================================================
+;; == Loads/Stores
+;; =========================================================================
+
+;; len_load/len_store is a sub-optimal pattern for RVV auto-vectorization support.
+;; We will replace them when len_maskload/len_maskstore is supported in loop vectorizer.
+(define_expand "len_load_<mode>"
+  [(match_operand:V 0 "register_operand")
+   (match_operand:V 1 "memory_operand")
+   (match_operand 2 "vector_length_operand")
+   (match_operand 3 "const_0_operand")]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
+				  operands[1], operands[2], <VM>mode);
+  DONE;
+})
+
+(define_expand "len_store_<mode>"
+  [(match_operand:V 0 "memory_operand")
+   (match_operand:V 1 "register_operand")
+   (match_operand 2 "vector_length_operand")
+   (match_operand 3 "const_0_operand")]
+  "TARGET_VECTOR"
+{
+  riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
+				  operands[1], operands[2], <VM>mode);
+  DONE;
+})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 7760a9cac8d..6086306a924 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -217,6 +217,7 @@  bool slide1_sew64_helper (int, machine_mode, machine_mode,
 			  machine_mode, rtx *);
 rtx gen_avl_for_scalar_move (rtx);
 void expand_tuple_move (machine_mode, rtx *);
+machine_mode preferred_simd_mode (scalar_mode);
 }
 
 /* We classify builtin types into two classes:
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 3950aa80338..1f887f7e747 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -43,6 +43,7 @@ 
 #include "optabs.h"
 #include "tm-constrs.h"
 #include "rtx-vector-builder.h"
+#include "targhooks.h"
 
 using namespace riscv_vector;
 
@@ -924,4 +925,54 @@  expand_tuple_move (machine_mode mask_mode, rtx *ops)
     }
 }
 
+/* SCALABLE means that the vector-length is agnostic (run-time invariant and
+   compile-time unknown). FIXED meands that the vector-length is specific
+   (compile-time known). Both RVV_SCALABLE and RVV_FIXED_VLMAX are doing
+   auto-vectorization using VLMAX vsetvl configuration.  */
+static bool
+autovec_use_vlmax_p (void)
+{
+  return riscv_autovec_preference == RVV_SCALABLE
+	 || riscv_autovec_preference == RVV_FIXED_VLMAX;
+}
+
+/* Return the vectorization machine mode for RVV according to LMUL.  */
+machine_mode
+preferred_simd_mode (scalar_mode mode)
+{
+  /* We will disable auto-vectorization when TARGET_MIN_VLEN < 128 &&
+     riscv_autovec_lmul < RVV_M2. Since GCC loop vectorizer report ICE when we
+     enable -march=rv64gc_zve32* and -march=rv32gc_zve64*. in the
+     'can_duplicate_and_interleave_p' of tree-vect-slp.cc. Since we have
+     VNx1SImode in -march=*zve32* and VNx1DImode in -march=*zve64*, they are
+     enabled in targetm. vector_mode_supported_p and SLP vectorizer will try to
+     use them. Currently, we can support auto-vectorization in
+     -march=rv32_zve32x_zvl128b. Wheras, -march=rv32_zve32x_zvl32b or
+     -march=rv32_zve32x_zvl64b are disabled.
+ */
+  if (autovec_use_vlmax_p ())
+    {
+      /* If TARGET_MIN_VLEN < 128, we don't allow LMUL < 2
+	 auto-vectorization since Loop Vectorizer may use VNx1SImode or
+	 VNx1DImode to vectorize which will create ICE in the
+	 'can_duplicate_and_interleave_p' of tree-vect-slp.cc.  */
+      if (TARGET_MIN_VLEN < 128 && riscv_autovec_lmul < RVV_M2)
+	return word_mode;
+      /* We use LMUL = 1 as base bytesize which is BYTES_PER_RISCV_VECTOR and
+	 riscv_autovec_lmul as multiply factor to calculate the the NUNITS to
+	 get the auto-vectorization mode.  */
+      poly_uint64 nunits;
+      poly_uint64 vector_size
+	= BYTES_PER_RISCV_VECTOR * ((int) riscv_autovec_lmul);
+      poly_uint64 scalar_size = GET_MODE_SIZE (mode);
+      gcc_assert (multiple_p (vector_size, scalar_size, &nunits));
+      machine_mode rvv_mode;
+      if (get_vector_mode (mode, nunits).exists (&rvv_mode))
+	return rvv_mode;
+    }
+  /* TODO: We will support minimum length VLS auto-vectorization in the future.
+   */
+  return word_mode;
+}
+
 } // namespace riscv_vector
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 45a63cab9c9..aa985c2f456 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3791,6 +3791,13 @@  riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   info->gpr_offset = cum->num_gprs;
   info->fpr_offset = cum->num_fprs;
 
+  /* TODO: Currently, it will cause an ICE for --param
+     riscv-autovec-preference=fixed-vlmax. So, we just return NULL_RTX here
+     let GCC generate loads/stores. Ideally, we should either warn the user not
+     to use an RVV vector type as function argument or support the calling
+     convention directly.  */
+  if (riscv_v_ext_mode_p (mode))
+    return NULL_RTX;
   if (named)
     {
       riscv_aggregate_field fields[2];
@@ -6334,7 +6341,15 @@  riscv_convert_vector_bits (void)
      to set RVV mode size. The RVV machine modes size are run-time constant if
      TARGET_VECTOR is enabled. The RVV machine modes size remains default
      compile-time constant if TARGET_VECTOR is disabled.  */
-  return TARGET_VECTOR ? poly_uint16 (1, 1) : 1;
+  if (TARGET_VECTOR)
+    {
+      if (riscv_autovec_preference == RVV_FIXED_VLMAX)
+	return (int) TARGET_MIN_VLEN / (riscv_bytes_per_vector_chunk * 8);
+      else
+	return poly_uint16 (1, 1);
+    }
+  else
+    return 1;
 }
 
 /* Implement TARGET_OPTION_OVERRIDE.  */
@@ -7345,6 +7360,17 @@  riscv_use_divmod_expander (void)
   return tune_param->use_divmod_expansion;
 }
 
+/* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
+
+static machine_mode
+riscv_preferred_simd_mode (scalar_mode mode)
+{
+  if (TARGET_VECTOR)
+    return riscv_vector::preferred_simd_mode (mode);
+
+  return word_mode;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -7602,6 +7628,9 @@  riscv_use_divmod_expander (void)
 #undef TARGET_ARRAY_MODE
 #define TARGET_ARRAY_MODE riscv_array_mode
 
+#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
+#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE riscv_preferred_simd_mode
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 92115e3935f..1ab0172d804 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -23,7 +23,7 @@ 
 ;; This file include :
 ;;
 ;; - Intrinsics (https://github.com/riscv/rvv-intrinsic-doc)
-;; - Auto-vectorization (TBD)
+;; - Auto-vectorization (autovec.md)
 ;; - Combine optimization (TBD)
 
 (include "vector-iterators.md")
@@ -8187,3 +8187,5 @@ 
     DONE;
   }
 )
+
+(include "autovec.md")
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/fixed-vlmax-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/fixed-vlmax-1.c
new file mode 100644
index 00000000000..09e8396936e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/fixed-vlmax-1.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32 -mpreferred-stack-boundary=3 -fno-schedule-insns -fno-schedule-insns2 -O3 --param riscv-autovec-preference=fixed-vlmax" } */
+
+#include "riscv_vector.h"
+
+void f (char*);
+
+void stack_check_alloca_1 (vuint8m1_t data, uint8_t *base, int y, ...)
+{
+  vuint8m8_t v0, v8, v16, v24;
+  asm volatile ("nop"
+                : "=vr" (v0), "=vr" (v8), "=vr" (v16), "=vr" (v24)
+                :
+                :);
+  asm volatile ("nop"
+                :
+                : "vr" (v0), "vr" (v8), "vr" (v16), "vr" (v24)
+                :);
+  *(vuint8m1_t *)base = data;
+  char* pStr = (char*)__builtin_alloca(y);
+  f(pStr);
+}
+
+/* Compiler should not cause an ICE in this testcase.  */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.c
new file mode 100644
index 00000000000..6384888dd03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rv32gcv -mabi=ilp32d --param riscv-autovec-preference=scalable -fno-vect-cost-model -fno-tree-loop-distribute-patterns" } */
+
+#include "single_rgroup-1.h"
+
+TEST_ALL (test_1)
+
+/* { dg-final { scan-assembler-times {vsetvli} 10 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.h
new file mode 100644
index 00000000000..be6b4c641cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup-1.h
@@ -0,0 +1,106 @@ 
+#include <stddef.h>
+#include <stdint.h>
+
+#define N 777
+
+#define test_1(TYPE)                                                           \
+  TYPE a_##TYPE[N];                                                            \
+  TYPE b_##TYPE[N];                                                            \
+  void __attribute__ ((noinline, noclone)) test_1_##TYPE (unsigned int n)      \
+  {                                                                            \
+    unsigned int i = 0;                                                        \
+    for (i = 0; i < n; i++)                                                    \
+      b_##TYPE[i] = a_##TYPE[i];                                               \
+  }
+
+#define run_1(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 33 + 1 + 109;                                        \
+  test_1_##TYPE (5);                                                           \
+  for (unsigned int i = 0; i < 5; i++)                                         \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_2(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 57 + 1 + 999;                                        \
+  test_1_##TYPE (17);                                                          \
+  for (unsigned int i = 0; i < 17; i++)                                        \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_3(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 77 + 1 + 3;                                          \
+  test_1_##TYPE (32);                                                          \
+  for (unsigned int i = 0; i < 32; i++)                                        \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_4(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 45 + 1 + 11;                                         \
+  test_1_##TYPE (128);                                                         \
+  for (unsigned int i = 0; i < 128; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_5(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 199 + 1 + 79;                                        \
+  test_1_##TYPE (177);                                                         \
+  for (unsigned int i = 0; i < 177; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_6(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 377 + 1 + 73;                                        \
+  test_1_##TYPE (255);                                                         \
+  for (unsigned int i = 0; i < 255; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_7(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 98 + 1 + 66;                                         \
+  test_1_##TYPE (333);                                                         \
+  for (unsigned int i = 0; i < 333; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_8(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 7 + 1 * 7;                                           \
+  test_1_##TYPE (512);                                                         \
+  for (unsigned int i = 0; i < 512; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_9(TYPE)                                                            \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 + 1 + 88;                                              \
+  test_1_##TYPE (637);                                                         \
+  for (unsigned int i = 0; i < 637; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define run_10(TYPE)                                                           \
+  for (unsigned int i = 0; i < N; i++)                                         \
+    a_##TYPE[i] = i * 2 * 331 + 1 + 547;                                       \
+  test_1_##TYPE (777);                                                         \
+  for (unsigned int i = 0; i < 777; i++)                                       \
+    if (b_##TYPE[i] != a_##TYPE[i])                                            \
+      __builtin_abort ();
+
+#define TEST_ALL(T)                                                            \
+  T (int8_t)                                                                   \
+  T (uint8_t)                                                                  \
+  T (int16_t)                                                                  \
+  T (uint16_t)                                                                 \
+  T (int32_t)                                                                  \
+  T (uint32_t)                                                                 \
+  T (int64_t)                                                                  \
+  T (uint64_t)                                                                 \
+  T (float)                                                                    \
+  T (double)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup_run-1.c
new file mode 100644
index 00000000000..4af2f18de8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/single_rgroup_run-1.c
@@ -0,0 +1,19 @@ 
+/* { dg-do run { target { riscv_vector } } } */
+/* { dg-additional-options "-fno-vect-cost-model -fno-tree-loop-distribute-patterns --param riscv-autovec-preference=scalable" } */
+
+#include "single_rgroup-1.c"
+
+int main (void)
+{
+  TEST_ALL (run_1)
+  TEST_ALL (run_2)
+  TEST_ALL (run_3)
+  TEST_ALL (run_4)
+  TEST_ALL (run_5)
+  TEST_ALL (run_6)
+  TEST_ALL (run_7)
+  TEST_ALL (run_8)
+  TEST_ALL (run_9)
+  TEST_ALL (run_10)
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/scalable-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/scalable-1.c
new file mode 100644
index 00000000000..e1236e678ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/scalable-1.c
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d -mabi=ilp32 -O3 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+#include "riscv_vector.h"
+
+void
+f (int32_t *__restrict f, int32_t *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/template-1.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/template-1.h
new file mode 100644
index 00000000000..799e2d7d754
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/template-1.h
@@ -0,0 +1,68 @@ 
+#include <stddef.h>
+#include <stdint.h>
+
+void
+foo0 (int8_t *__restrict f, int16_t *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+} 
+
+void
+foo1 (int16_t *__restrict f, int32_t *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+} 
+
+void
+foo2 (int32_t *__restrict f, int64_t *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+}
+
+void
+foo3 (int16_t *__restrict f, float *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+} 
+
+void
+foo4 (int32_t *__restrict f, float *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+} 
+
+void
+foo5 (float *__restrict f, double *__restrict d, int n)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      f[i * 2 + 0] = 1;
+      f[i * 2 + 1] = 2;
+      d[i] = 3;
+    }
+} 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-1.c
new file mode 100644
index 00000000000..e5e54d08d3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-1.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* Currently, we don't support SLP auto-vectorization for VLA. But it's
+   necessary that we add this testcase here to make sure such unsupported SLP
+   auto-vectorization will not cause an ICE. We will enable "vect" checking when
+   we support SLP auto-vectorization for VLA in the future.  */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-2.c
new file mode 100644
index 00000000000..397d219447b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/v-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 5 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
new file mode 100644
index 00000000000..066d4ae7f84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32f -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-2.c
new file mode 100644
index 00000000000..9c9123d75f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-2.c
@@ -0,0 +1,5 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32f -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-3.c
new file mode 100644
index 00000000000..e0f549aec9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32f -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax --param riscv-autovec-lmul=m2 -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 4 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-1.c
new file mode 100644
index 00000000000..ef70c006ec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32f_zvl128b -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-2.c
new file mode 100644
index 00000000000..3c01e4f6c7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32f_zvl128b-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32f_zvl128b -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fno-vect-cost-model -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 4 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-1.c
new file mode 100644
index 00000000000..80e69ee8e66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32x -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-2.c
new file mode 100644
index 00000000000..f7be76965ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32x -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-3.c
new file mode 100644
index 00000000000..f1d04b46656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32x -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax --param riscv-autovec-lmul=m2 -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 3 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-1.c
new file mode 100644
index 00000000000..48c810a08b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-1.c
@@ -0,0 +1,5 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32x_zvl128b -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-2.c
new file mode 100644
index 00000000000..f025f72c4d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve32x_zvl128b-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve32x_zvl128b -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 2 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-1.c
new file mode 100644
index 00000000000..24300721f6b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-2.c
new file mode 100644
index 00000000000..283752d479a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-2.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-3.c
new file mode 100644
index 00000000000..564cc6fa5c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax --param riscv-autovec-lmul=m2 -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 5 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-1.c
new file mode 100644
index 00000000000..f87c6283e2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d_zvl128b -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-2.c
new file mode 100644
index 00000000000..f82610a4bfc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64d_zvl128b-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64d_zvl128b -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 5 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-1.c
new file mode 100644
index 00000000000..aac10b6d2ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64f -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-2.c
new file mode 100644
index 00000000000..781f3bbce73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-2.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64f -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-3.c
new file mode 100644
index 00000000000..6159e84fc71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64f -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax --param riscv-autovec-lmul=m2 -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 4 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-1.c
new file mode 100644
index 00000000000..e4c8c056077
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64f_zvl128b -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-2.c
new file mode 100644
index 00000000000..133380e6844
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64f_zvl128b-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64f_zvl128b -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 4 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-1.c
new file mode 100644
index 00000000000..bac310af690
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64x -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-2.c
new file mode 100644
index 00000000000..5ec8906fd2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-2.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64x -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-3.c
new file mode 100644
index 00000000000..fedd9a0228c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x-3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64x -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax --param riscv-autovec-lmul=m2 -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 3 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-1.c
new file mode 100644
index 00000000000..67be8501f66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-1.c
@@ -0,0 +1,4 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64x_zvl128b -mabi=ilp32d --param riscv-autovec-preference=scalable -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-2.c
new file mode 100644
index 00000000000..1ad74916168
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/zve64x_zvl128b-2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zve64x_zvl128b -mabi=ilp32d --param riscv-autovec-preference=fixed-vlmax -fdump-tree-vect-details -save-temps" } */
+
+#include "template-1.h"
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 3 "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
index 4b5509db385..0d5481085e2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
+++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp
@@ -46,6 +46,22 @@  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/base/*.\[cS\]]] \
 	"" $CFLAGS
 gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vsetvl/*.\[cS\]]] \
 	"" $CFLAGS
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/*.\[cS\]]] \
+	"-O3 -ftree-vectorize" $CFLAGS
+
+set AUTOVEC_TEST_OPTS [list \
+  {-ftree-vectorize -O3 --param riscv-autovec-lmul=m1} \
+  {-ftree-vectorize -O3 --param riscv-autovec-lmul=m2} \
+  {-ftree-vectorize -O3 --param riscv-autovec-lmul=m4} \
+  {-ftree-vectorize -O3 --param riscv-autovec-lmul=m8} \
+  {-ftree-vectorize -O2 --param riscv-autovec-lmul=m1} \
+  {-ftree-vectorize -O2 --param riscv-autovec-lmul=m2} \
+  {-ftree-vectorize -O2 --param riscv-autovec-lmul=m4} \
+  {-ftree-vectorize -O2 --param riscv-autovec-lmul=m8} ]
+foreach op $AUTOVEC_TEST_OPTS {
+  gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/autovec/partial/*.\[cS\]]] \
+    "" "$op"
+}
 
 # All done.
 dg-finish