diff --git a/gcc/config.gcc b/gcc/config.gcc
index 3675e063a5365ff84854eb5c2c27921216494c69..50d3401e3aa94f077d7e0675ee443a94431dba1e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -352,7 +352,7 @@ arc*-*-*)
 	;;
 arm*-*-*)
 	cpu_type=arm
-	extra_objs="arm-builtins.o aarch-common.o"
+	extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
 	extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
 	target_type_format_char='%'
 	c_target_objs="arm-c.o"
diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index cc7901bca8dc9c5c27ed6afc5bc26afd42689e6d..d1414f6e0e1c2bd0a7364b837c16adf493221376 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -28,6 +28,7 @@
 #include "c-family/c-pragma.h"
 #include "stringpool.h"
 #include "arm-builtins.h"
+#include "arm-protos.h"
 
 tree
 arm_resolve_cde_builtin (location_t loc, tree fndecl, void *arglist)
@@ -129,6 +130,24 @@ arm_resolve_cde_builtin (location_t loc, tree fndecl, void *arglist)
   return call_expr;
 }
 
+/* Implement "#pragma GCC arm".  */
+static void
+arm_pragma_arm (cpp_reader *)
+{
+  tree x;
+  if (pragma_lex (&x) != CPP_STRING)
+    {
+      error ("%<#pragma GCC arm%> requires a string parameter");
+      return;
+    }
+
+  const char *name = TREE_STRING_POINTER (x);
+  if (strcmp (name, "arm_mve_types.h") == 0)
+    arm_mve::handle_arm_mve_types_h ();
+  else
+    error ("unknown %<#pragma GCC arm%> option %qs", name);
+}
+
 /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN.  This is currently only
    used for the MVE related builtins for the CDE extension.
    Here we ensure the type of arguments is such that the size is correct, and
@@ -476,6 +495,8 @@ arm_register_target_pragmas (void)
   targetm.target_option.pragma_parse = arm_pragma_target_parse;
   targetm.resolve_overloaded_builtin = arm_resolve_overloaded_builtin;
 
+  c_register_pragma ("GCC", "arm", arm_pragma_arm);
+
 #ifdef REGISTER_SUBTARGET_PRAGMAS
   REGISTER_SUBTARGET_PRAGMAS ();
 #endif
diff --git a/gcc/config/arm/arm-mve-builtins.cc b/gcc/config/arm/arm-mve-builtins.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8030a4c0d0437bf98f00d06f9dcdbde81ae73074
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.cc
@@ -0,0 +1,192 @@
+/* ACLE support for Arm MVE
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "diagnostic.h"
+#include "arm-protos.h"
+#include "arm-builtins.h"
+#include "arm-mve-builtins.h"
+
+namespace arm_mve {
+
+/* Static information about each single-predicate or single-vector
+   ACLE type.  */
+struct vector_type_info
+{
+  /* The name of the type as declared by arm_mve.h.  */
+  const char *acle_name;
+
+  /* Whether the type requires a floating point abi.  */
+  const bool requires_float;
+};
+
+/* Flag indicating whether the arm MVE types have been handled.  */
+static bool handle_arm_mve_types_p = false;
+
+/* Information about each single-predicate or single-vector type.  */
+static CONSTEXPR const vector_type_info vector_types[] = {
+#define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
+  { #ACLE_NAME, REQUIRES_FLOAT },
+#include "arm-mve-builtins.def"
+#undef DEF_MVE_TYPE
+};
+
+/* The scalar type associated with each vector type.  */
+GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+
+/* The single-predicate and single-vector types, with their built-in
+   "__simd128_..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
+   yields a null tree.  */
+static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
+
+/* Same, but with the arm_mve.h names.  */
+GTY(()) tree acle_vector_types[3][NUM_VECTOR_TYPES + 1];
+
+/* Return the MVE abi type with element of type TYPE.  */
+static tree
+arm_mve_type_for_scalar_type (tree eltype)
+{
+  for (unsigned int i = 0; i < __TYPE_FINAL; ++i)
+      if (arm_simd_types[i].eltype == eltype
+	  && GET_MODE_SIZE (arm_simd_types[i].mode) == 16)
+	return arm_simd_types[i].itype;
+
+  gcc_unreachable ();
+}
+
+/* Register the built-in MVE ABI vector types, such as uint32x4_t.  */
+static void
+register_builtin_types ()
+{
+#define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
+  scalar_types[VECTOR_TYPE_ ## ACLE_NAME] = SCALAR_TYPE;
+#include "arm-mve-builtins.def"
+#undef DEF_MVE_TYPE
+  for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+    {
+      if (vector_types[i].requires_float && !TARGET_HAVE_MVE_FLOAT)
+	continue;
+      tree eltype = scalar_types[i];
+      tree vectype;
+      if (eltype == boolean_type_node)
+	{
+	  vectype = get_typenode_from_name (UINT16_TYPE);
+	  gcc_assert (GET_MODE_SIZE (TYPE_MODE (vectype)) == 2);
+	}
+      else
+	{
+	  vectype = arm_mve_type_for_scalar_type (eltype);
+	  gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype))
+		      && GET_MODE_SIZE (TYPE_MODE (vectype)) == 16);
+	}
+      abi_vector_types[i] = vectype;
+    }
+}
+
+/* Register vector type TYPE under its arm_mve.h name.  */
+static void
+register_vector_type (vector_type_index type)
+{
+  if (vector_types[type].requires_float && !TARGET_HAVE_MVE_FLOAT)
+    return;
+  tree vectype = abi_vector_types[type];
+  tree id = get_identifier (vector_types[type].acle_name);
+  tree decl = build_decl (input_location, TYPE_DECL, id, vectype);
+  decl = lang_hooks.decls.pushdecl (decl);
+
+  /* Record the new ACLE type if pushdecl succeeded without error.  Use
+     the ABI type otherwise, so that the type we record at least has the
+     right form, even if it doesn't have the right name.  This should give
+     better error recovery behavior than installing error_mark_node or
+     installing an incorrect type.  */
+  if (decl
+      && TREE_CODE (decl) == TYPE_DECL
+      && TREE_TYPE (decl) != error_mark_node
+      && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype)
+    vectype = TREE_TYPE (decl);
+  acle_vector_types[0][type] = vectype;
+}
+
+/* Register tuple type TYPE with NUM_VECTORS arity under its
+   arm_mve_types.h name.  */
+static void
+register_builtin_tuple_types (vector_type_index type)
+{
+  const vector_type_info* info = &vector_types[type];
+  if (scalar_types[type] == boolean_type_node
+      || (info->requires_float && !TARGET_HAVE_MVE_FLOAT))
+    return;
+  const char *vector_type_name = info->acle_name;
+  char buffer[sizeof ("float32x4x2_t")];
+  for (unsigned int num_vectors = 2; num_vectors <= 4; num_vectors += 2)
+    {
+      snprintf (buffer, sizeof (buffer), "%.*sx%d_t",
+		(int) strlen (vector_type_name) - 2, vector_type_name,
+		num_vectors);
+
+      tree vectype = acle_vector_types[0][type];
+      tree arrtype = build_array_type_nelts (vectype, num_vectors);
+      gcc_assert (TYPE_MODE_RAW (arrtype) == TYPE_MODE (arrtype));
+      tree field = build_decl (input_location, FIELD_DECL,
+			       get_identifier ("val"), arrtype);
+
+      tree t = lang_hooks.types.simulate_record_decl (input_location, buffer,
+						      make_array_slice (&field,
+									1));
+      gcc_assert (TYPE_MODE_RAW (t) == TYPE_MODE (t));
+      acle_vector_types[num_vectors >> 1][type] = TREE_TYPE (t);
+    }
+}
+
+/* Implement #pragma GCC arm "arm_mve_types.h".  */
+void
+handle_arm_mve_types_h ()
+{
+  if (handle_arm_mve_types_p)
+    {
+      error ("duplicate definition of %qs", "arm_mve_types.h");
+      return;
+    }
+  handle_arm_mve_types_p = true;
+  if (!TARGET_HAVE_MVE)
+    {
+      error ("this definition requires the MVE ISA extension");
+      return;
+    }
+  register_builtin_types ();
+  for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
+    {
+      vector_type_index type = vector_type_index (type_i);
+      register_vector_type (type);
+      if (type_i != VECTOR_TYPE_mve_pred16_t)
+	register_builtin_tuple_types (type);
+    }
+}
+
+}
diff --git a/gcc/config/arm/arm-mve-builtins.def b/gcc/config/arm/arm-mve-builtins.def
new file mode 100644
index 0000000000000000000000000000000000000000..02a46bec3e4cba6add9bce4021c732e15aa8b012
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.def
@@ -0,0 +1,41 @@
+/* Builtin lists for Arm MVE
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DEF_MVE_TYPE
+#define DEF_MVE_TYPE(A, B)
+#endif
+
+#define REQUIRES_FLOAT false
+DEF_MVE_TYPE (mve_pred16_t, boolean_type_node)
+DEF_MVE_TYPE (uint8x16_t, unsigned_intQI_type_node)
+DEF_MVE_TYPE (uint16x8_t, unsigned_intHI_type_node)
+DEF_MVE_TYPE (uint32x4_t, unsigned_intSI_type_node)
+DEF_MVE_TYPE (uint64x2_t, unsigned_intDI_type_node)
+DEF_MVE_TYPE (int8x16_t, intQI_type_node)
+DEF_MVE_TYPE (int16x8_t, intHI_type_node)
+DEF_MVE_TYPE (int32x4_t, intSI_type_node)
+DEF_MVE_TYPE (int64x2_t, intDI_type_node)
+#undef REQUIRES_FLOAT
+
+#define REQUIRES_FLOAT true
+DEF_MVE_TYPE (float16x8_t, arm_fp16_type_node)
+DEF_MVE_TYPE (float32x4_t, float_type_node)
+#undef REQUIRES_FLOAT
+
+#undef DEF_MVE_TYPE
diff --git a/gcc/config/arm/arm-mve-builtins.h b/gcc/config/arm/arm-mve-builtins.h
new file mode 100644
index 0000000000000000000000000000000000000000..f64b81331c323fbde0aadb0107dfdc5f7a4c1e53
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.h
@@ -0,0 +1,34 @@
+/* ACLE support for Arm MVE
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_ARM_MVE_BUILTINS_H
+#define GCC_ARM_MVE_BUILTINS_H
+
+/* Enumerates the MVE predicate and (data) vector types, together called
+   "vector types" for brevity.  */
+enum vector_type_index
+{
+#define DEF_MVE_TYPE(ACLE_NAME, SCALAR_TYPE) \
+  VECTOR_TYPE_ ## ACLE_NAME,
+#include "arm-mve-builtins.def"
+  NUM_VECTOR_TYPES
+};
+#undef DEF_MVE_TYPE
+
+#endif /* GCC_ARM_MVE_BUILTINS_H */
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 9b1f61394ad7d778a6c0b84bc6c805f14709f598..c91cb5ad69b9d911c31e6018a2ca6bf2ac6239d3 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -204,6 +204,11 @@ extern int arm_apply_result_size (void);
 
 #endif /* RTX_CODE */
 
+/* MVE functions.  */
+namespace arm_mve {
+  void handle_arm_mve_types_h ();
+}
+
 /* Thumb functions.  */
 extern void arm_init_expanders (void);
 extern const char *thumb1_unexpanded_epilogue (void);
diff --git a/gcc/config/arm/arm_mve_types.h b/gcc/config/arm/arm_mve_types.h
index 8958f4efdb9952602887bfcb186db6e8364d6351..7fbc89b5982ea73de973dfc25774a8f67ca8bf48 100644
--- a/gcc/config/arm/arm_mve_types.h
+++ b/gcc/config/arm/arm_mve_types.h
@@ -25,37 +25,9 @@
 #if (__ARM_FEATURE_MVE & 2) /* MVE Floating point.  */
 typedef __fp16 float16_t;
 typedef float float32_t;
-typedef __simd128_float16_t float16x8_t;
-typedef __simd128_float32_t float32x4_t;
-
-typedef struct { float16x8_t val[2]; } float16x8x2_t;
-typedef struct { float16x8_t val[4]; } float16x8x4_t;
-typedef struct { float32x4_t val[2]; } float32x4x2_t;
-typedef struct { float32x4_t val[4]; } float32x4x4_t;
 #endif
 
-typedef uint16_t mve_pred16_t;
-typedef __simd128_uint8_t uint8x16_t;
-typedef __simd128_uint16_t uint16x8_t;
-typedef __simd128_uint32_t uint32x4_t;
-typedef __simd128_uint64_t uint64x2_t;
-typedef __simd128_int8_t int8x16_t;
-typedef __simd128_int16_t int16x8_t;
-typedef __simd128_int32_t int32x4_t;
-typedef __simd128_int64_t int64x2_t;
-
-typedef struct { int16x8_t val[2]; } int16x8x2_t;
-typedef struct { int16x8_t val[4]; } int16x8x4_t;
-typedef struct { int32x4_t val[2]; } int32x4x2_t;
-typedef struct { int32x4_t val[4]; } int32x4x4_t;
-typedef struct { int8x16_t val[2]; } int8x16x2_t;
-typedef struct { int8x16_t val[4]; } int8x16x4_t;
-typedef struct { uint16x8_t val[2]; } uint16x8x2_t;
-typedef struct { uint16x8_t val[4]; } uint16x8x4_t;
-typedef struct { uint32x4_t val[2]; } uint32x4x2_t;
-typedef struct { uint32x4_t val[4]; } uint32x4x4_t;
-typedef struct { uint8x16_t val[2]; } uint8x16x2_t;
-typedef struct { uint8x16_t val[4]; } uint8x16x4_t;
+#pragma GCC arm "arm_mve_types.h"
 
 __extension__ extern __inline int16x8_t
 __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 5f69ee6451efb8709fe9b455a45c2e634e009170..f655f369724ca711f0a389abaf0e70adb3ab4b7c 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -153,6 +153,16 @@ arm-builtins.o: $(srcdir)/config/arm/arm-builtins.c $(CONFIG_H) \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/arm/arm-builtins.c
 
+arm-mve-builtins.o: $(srcdir)/config/arm/arm-mve-builtins.cc $(CONFIG_H) \
+  $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
+  fold-const.h langhooks.h stringpool.h attribs.h diagnostic.h \
+  $(srcdir)/config/arm/arm-protos.h \
+  $(srcdir)/config/arm/arm-builtins.h \
+  $(srcdir)/config/arm/arm-mve-builtins.h \
+  $(srcdir)/config/arm/arm-mve-builtins.def
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/arm/arm-mve-builtins.cc
+
 arm-c.o: $(srcdir)/config/arm/arm-c.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_1.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..0db2b91dc4fe064bffa63a8cf466cd1ec2662db6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int mve_pred16_t; /* { dg-message "note: previous declaration of 'mve_pred16_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'mve_pred16_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_10.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_10.c
new file mode 100644
index 0000000000000000000000000000000000000000..15393a000a23e6d22a03290996270e939610dbc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_10.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float16x8_t; /* { dg-message "note: previous declaration of 'float16x8_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float16x8_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_11.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_11.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd0b2bbc0a828734d149f5b21891477ef7779462
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_11.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float32x4_t; /* { dg-message "note: previous declaration of 'float32x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float32x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_12.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_12.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff9b06965a463d33d28b235c37d9c999bdc28872
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_12.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint8x16x2_t; /* { dg-message "note: previous declaration of 'uint8x16x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_13.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_13.c
new file mode 100644
index 0000000000000000000000000000000000000000..1881555dab1d7c848becd344e84208fb8f876223
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_13.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint8x16x4_t; /* { dg-message "note: previous declaration of 'uint8x16x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_14.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_14.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea92afc5861c9cc67f4c99d48c50e2eae7d87fab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_14.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint16x8x2_t; /* { dg-message "note: previous declaration of 'uint16x8x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint16x8x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_15.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_15.c
new file mode 100644
index 0000000000000000000000000000000000000000..f62271c0b75c980dc53e9d831e4e15523f927874
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_15.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint16x8x4_t; /* { dg-message "note: previous declaration of 'uint16x8x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint16x8x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_16.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_16.c
new file mode 100644
index 0000000000000000000000000000000000000000..dcd6465aad664b48cc70746c627fa54438cd41d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_16.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint32x4x2_t; /* { dg-message "note: previous declaration of 'uint32x4x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint32x4x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_17.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_17.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbbb839361741cf9ea1255e22e9d9a815bc66b7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_17.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint32x4x4_t; /* { dg-message "note: previous declaration of 'uint32x4x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint32x4x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_18.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_18.c
new file mode 100644
index 0000000000000000000000000000000000000000..acaa48cd28d6c796de91a81251f3a034ea72d9ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_18.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint64x2x2_t; /* { dg-message "note: previous declaration of 'uint64x2x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint64x2x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_19.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_19.c
new file mode 100644
index 0000000000000000000000000000000000000000..95bbc98b6dc99e465059c40ef19f2865ee1233b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_19.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint64x2x4_t; /* { dg-message "note: previous declaration of 'uint64x2x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint64x2x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_2.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ff563183b9126a1d1fd1b608c8e565956765f01
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint8x16_t; /* { dg-message "note: previous declaration of 'uint8x16_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_20.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_20.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f5efcff002c29d5024b1ee8da68b7785dab8968
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_20.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int8x16x2_t; /* { dg-message "note: previous declaration of 'int8x16x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int8x16x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_21.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_21.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d9df51c4b51494165b976ccd78067fc4a9386e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_21.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int8x16x4_t; /* { dg-message "note: previous declaration of 'int8x16x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int8x16x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_22.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_22.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a414f656021297a39586c0b4f28314ab163d8ad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_22.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int16x8x2_t; /* { dg-message "note: previous declaration of 'int16x8x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int16x8x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_23.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_23.c
new file mode 100644
index 0000000000000000000000000000000000000000..081ef66390f8c122694fe0bce589ed8c1884af03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_23.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int16x8x4_t; /* { dg-message "note: previous declaration of 'int16x8x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int16x8x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_24.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_24.c
new file mode 100644
index 0000000000000000000000000000000000000000..96d385689dcc49ccbaba57aa73af01df2c60dd57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_24.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int32x4x2_t; /* { dg-message "note: previous declaration of 'int32x4x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int32x4x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_25.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_25.c
new file mode 100644
index 0000000000000000000000000000000000000000..21731f46ef31503fb17ddc3494064514afd532b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_25.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int32x4x4_t; /* { dg-message "note: previous declaration of 'int32x4x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int32x4x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_26.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_26.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ad078c5812c0c938890aa4cc0ad30304b670b42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_26.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int64x2x2_t; /* { dg-message "note: previous declaration of 'int64x2x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int64x2x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_27.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_27.c
new file mode 100644
index 0000000000000000000000000000000000000000..017a265c56298504adac75d71a8984d5f2b6564f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_27.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int64x2x4_t; /* { dg-message "note: previous declaration of 'int64x2x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int64x2x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_28.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_28.c
new file mode 100644
index 0000000000000000000000000000000000000000..7543c84434e124a6c153d39931e4c5930bcec1a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_28.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float16x8x2_t; /* { dg-message "note: previous declaration of 'float16x8x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float16x8x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_29.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_29.c
new file mode 100644
index 0000000000000000000000000000000000000000..aefd329ad44288e3c63fce60e9f477bd29cb25f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_29.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float16x8x4_t; /* { dg-message "note: previous declaration of 'float16x8x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float16x8x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_3.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..cef5a04a04a65d8537ccd1bf6162b3c837d347ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint16x8_t; /* { dg-message "note: previous declaration of 'uint16x8_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint16x8_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_30.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_30.c
new file mode 100644
index 0000000000000000000000000000000000000000..04ab03c55bd8ebf642b1e66d3018f71d576c1252
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_30.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float32x4x2_t; /* { dg-message "note: previous declaration of 'float32x4x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float32x4x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_31.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_31.c
new file mode 100644
index 0000000000000000000000000000000000000000..10bfcc99f3c448e7c1aab8a5bd6d2bd8b8947fd7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_31.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int float32x4x4_t; /* { dg-message "note: previous declaration of 'float32x4x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'float32x4x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_4.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_4.c
new file mode 100644
index 0000000000000000000000000000000000000000..0fb15bd42b7e0ead037236de24562cf41a1a82e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint32x4_t; /* { dg-message "note: previous declaration of 'uint32x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint32x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_5.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_5.c
new file mode 100644
index 0000000000000000000000000000000000000000..0b2b3aafa0c53b032a06e8ed9e36d9ed437348ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_5.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int uint64x2_t; /* { dg-message "note: previous declaration of 'uint64x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint64x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_6.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_6.c
new file mode 100644
index 0000000000000000000000000000000000000000..afcc8c06b6fcc87c2bdfb91af7a0550171afd5d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_6.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int8x16_t; /* { dg-message "note: previous declaration of 'int8x16_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int8x16_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_7.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_7.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8c45ebc5490ac2747edc1418c569aaa86faf169
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_7.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int16x8_t; /* { dg-message "note: previous declaration of 'int16x8_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int16x8_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_8.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_8.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b8ed4c81df007e841a02536fe12665cfbfe2863
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_8.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int32x4_t; /* { dg-message "note: previous declaration of 'int32x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int32x4_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_9.c b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_9.c
new file mode 100644
index 0000000000000000000000000000000000000000..03543c89ba58a5cdcb6ef359727e32f0b68cd1b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_9.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+int int64x2_t; /* { dg-message "note: previous declaration of 'int64x2_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'int64x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general/double_pragmas_1.c b/gcc/testsuite/gcc.target/arm/mve/general/double_pragmas_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..58466db6940d3f272ca6f90ea697a4b35440bbe6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general/double_pragmas_1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+
+/* It doesn't really matter if this produces errors about redefinitions,
+   but it mustn't trigger an ICE.  */
+#pragma GCC arm "arm_mve_types.h"
+#pragma GCC arm "arm_mve_types.h" /* { dg-error "duplicate definition of 'arm_mve_types.h'" } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/general/nomve_1.c b/gcc/testsuite/gcc.target/arm/mve/general/nomve_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..cdfb974b7a23c70b2beb9138a75ea88cc39eca5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general/nomve_1.c
@@ -0,0 +1,3 @@
+/* { dg-options "-mfloat-abi=soft" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {this definition requires the MVE ISA extension} } */
diff --git a/gcc/testsuite/gcc.target/arm/mve/mve.exp b/gcc/testsuite/gcc.target/arm/mve/mve.exp
index a858e52d9208b6e2bbd3c2175ed45724871598e2..7cea03d6befc9a7080acb58b0245af576a19e61c 100644
--- a/gcc/testsuite/gcc.target/arm/mve/mve.exp
+++ b/gcc/testsuite/gcc.target/arm/mve/mve.exp
@@ -44,6 +44,12 @@ dg-init
 dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/intrinsics/*.\[cCS\]]] \
 	"" $DEFAULT_CFLAGS
 
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/general/*.\[cCS\]]] \
+	"" $DEFAULT_CFLAGS
+
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/general-c/*.\[cCS\]]] \
+        "" $DEFAULT_CFLAGS
+
 dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
 	"" $DEFAULT_CFLAGS
 
