diff mbox series

[2/2] arm: Declare MVE types internally via pragma

Message ID 55ba6a8c-4dda-c023-0e93-a052e4830d06@arm.com
State New
Headers show
Series arm: Define MVE types internally | expand

Commit Message

Murray Steele Nov. 16, 2021, 10:15 a.m. UTC
Hi all,

This patch moves the implementation of MVE ACLE types from
arm_mve_types.h to inside GCC via a new pragma, which replaces the prior
type definitions. This allows for the types to be used internally for
intrinsic function definitions.

Bootstrapped and regression tested on arm-none-linux-gnuabihf, and
regression tested on arm-eabi -- no issues.

Thanks,
Murray

gcc/ChangeLog:

        * config.gcc: Add arm-mve-builtins.o to extra_objs for arm-*-*-*
        targets.
        * config/arm/arm-c.c (arm_pragma_arm): Handle new pragma.
        (arm_register_target_pragmas): Register new pragma.
        * config/arm/arm-protos.h: Add arm_mve namespace and declare
        arm_handle_mve_types_h.
        * config/arm/arm_mve_types.h: Replace MVE type definitions with
        new pragma.
        * config/arm/t-arm: Add arm-mve-builtins.o target.
        * config/arm/arm-mve-builtins.cc: New file.
        * config/arm/arm-mve-builtins.def: New file.
        * config/arm/arm-mve-builtins.h: New file.

gcc/testsuite/ChangeLog:

        * gcc.target/arm/mve/mve.exp: Add new subdirectories.
        * gcc.target/arm/mve/general-c/type_redef_1.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_10.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_11.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_12.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_13.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_14.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_15.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_16.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_17.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_18.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_19.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_2.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_20.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_21.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_22.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_23.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_24.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_25.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_26.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_27.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_28.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_29.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_3.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_30.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_31.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_4.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_5.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_6.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_7.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_8.c: New test.
        * gcc.target/arm/mve/general-c/type_redef_9.c: New test.
        * gcc.target/arm/mve/general/double_pragmas_1.c: New test.
        * gcc.target/arm/mve/general/nomve_1.c: New test.

Comments

Richard Earnshaw Nov. 18, 2021, 3:45 p.m. UTC | #1
On 16/11/2021 10:15, Murray Steele via Gcc-patches wrote:
> Hi all,
> 
> This patch moves the implementation of MVE ACLE types from
> arm_mve_types.h to inside GCC via a new pragma, which replaces the prior
> type definitions. This allows for the types to be used internally for
> intrinsic function definitions.
> 
> Bootstrapped and regression tested on arm-none-linux-gnuabihf, and
> regression tested on arm-eabi -- no issues.
> 
> Thanks,
> Murray
> 
> gcc/ChangeLog:
> 
>          * config.gcc: Add arm-mve-builtins.o to extra_objs for arm-*-*-*
>          targets.
>          * config/arm/arm-c.c (arm_pragma_arm): Handle new pragma.
>          (arm_register_target_pragmas): Register new pragma.
>          * config/arm/arm-protos.h: Add arm_mve namespace and declare
>          arm_handle_mve_types_h.
>          * config/arm/arm_mve_types.h: Replace MVE type definitions with
>          new pragma.
>          * config/arm/t-arm: Add arm-mve-builtins.o target.
>          * config/arm/arm-mve-builtins.cc: New file.
>          * config/arm/arm-mve-builtins.def: New file.
>          * config/arm/arm-mve-builtins.h: New file.
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/arm/mve/mve.exp: Add new subdirectories.
>          * gcc.target/arm/mve/general-c/type_redef_1.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_10.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_11.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_12.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_13.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_14.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_15.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_16.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_17.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_18.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_19.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_2.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_20.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_21.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_22.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_23.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_24.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_25.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_26.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_27.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_28.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_29.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_3.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_30.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_31.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_4.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_5.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_6.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_7.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_8.c: New test.
>          * gcc.target/arm/mve/general-c/type_redef_9.c: New test.
>          * gcc.target/arm/mve/general/double_pragmas_1.c: New test.
>          * gcc.target/arm/mve/general/nomve_1.c: New test.
> 
> 

This is mostly OK, but can't we reduce the number of tests somewhat? 
For example, I think you can merge type_redef_13.c and type_redef_14.c 
by writing

/* { 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'" } */
int uint16x8x2_t; /* { dg-message "note: previous declaration of 
'uint16x8x2_t'" } */

#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x4_t' 
redeclared} } */
   /* { dg-error {'uint16x8x2_t' redeclared} {target *-*-*} .-1 } */

etc.  Note the second dg-error is anchored to the line above it (.-1).

R.
Murray Steele Nov. 23, 2021, 9:37 a.m. UTC | #2
On 18/11/2021 15:45, Richard Earnshaw wrote:

> 
> This is mostly OK, but can't we reduce the number of tests somewhat? For example, I think you can merge type_redef_13.c and type_redef_14.c by writing
> 
> /* { 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'" } */
> int uint16x8x2_t; /* { dg-message "note: previous declaration of 'uint16x8x2_t'" } */
> 
> #pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x4_t' redeclared} } */
>   /* { dg-error {'uint16x8x2_t' redeclared} {target *-*-*} .-1 } */
> 
> etc.  Note the second dg-error is anchored to the line above it (.-1).
> 
> R.

Thanks. I think if we'd like to reduce the number of tests, it would make the most
sense to merge the test cases in the way you've described based on their implementation
and target features. i.e.

- type_redef_1.c : covers mve_pred16_t.
- type_redef_2.c : covers single-integer-vector types.
- type_redef_3.c : covers single-float-vector types.
- type_redef_4.c : covers integer-vector-tuple types.
- type_redef_5.c : covers float-vector-tuple types.

The idea being that the test results for these tests should allow someone to triangulate
the cause of the failure. For example, if tests 4 and 5 fail, it is likely due to a
deficiency in the MVE tuple type implementation, rather than the handling of target-specific
features. More specific tests failures can be determined by looking through log files.

Thanks,
Murray
Richard Earnshaw Nov. 23, 2021, 2:16 p.m. UTC | #3
On 23/11/2021 09:37, Murray Steele wrote:
> On 18/11/2021 15:45, Richard Earnshaw wrote:
> 
>>
>> This is mostly OK, but can't we reduce the number of tests somewhat? For example, I think you can merge type_redef_13.c and type_redef_14.c by writing
>>
>> /* { 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'" } */
>> int uint16x8x2_t; /* { dg-message "note: previous declaration of 'uint16x8x2_t'" } */
>>
>> #pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x4_t' redeclared} } */
>>    /* { dg-error {'uint16x8x2_t' redeclared} {target *-*-*} .-1 } */
>>
>> etc.  Note the second dg-error is anchored to the line above it (.-1).
>>
>> R.
> 
> Thanks. I think if we'd like to reduce the number of tests, it would make the most
> sense to merge the test cases in the way you've described based on their implementation
> and target features. i.e.
> 
> - type_redef_1.c : covers mve_pred16_t.
> - type_redef_2.c : covers single-integer-vector types.
> - type_redef_3.c : covers single-float-vector types.
> - type_redef_4.c : covers integer-vector-tuple types.
> - type_redef_5.c : covers float-vector-tuple types.
> 
> The idea being that the test results for these tests should allow someone to triangulate
> the cause of the failure. For example, if tests 4 and 5 fail, it is likely due to a
> deficiency in the MVE tuple type implementation, rather than the handling of target-specific
> features. More specific tests failures can be determined by looking through log files.
> 
> Thanks,
> Murray
> 

Merged files will still have the same number of tests, and the same 
possible test names, just from fewer source files.  So I don't think 
triangulation will be an issue.
Murray Steele Nov. 23, 2021, 3:45 p.m. UTC | #4
On 23/11/2021 14:16, Richard Earnshaw wrote:
> 
> 
> On 23/11/2021 09:37, Murray Steele wrote:
>> On 18/11/2021 15:45, Richard Earnshaw wrote:
>>
>>>
>>> This is mostly OK, but can't we reduce the number of tests somewhat? For example, I think you can merge type_redef_13.c and type_redef_14.c by writing
>>>
>>> /* { 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'" } */
>>> int uint16x8x2_t; /* { dg-message "note: previous declaration of 'uint16x8x2_t'" } */
>>>
>>> #pragma GCC arm "arm_mve_types.h"  /* { dg-error {'uint8x16x4_t' redeclared} } */
>>>    /* { dg-error {'uint16x8x2_t' redeclared} {target *-*-*} .-1 } */
>>>
>>> etc.  Note the second dg-error is anchored to the line above it (.-1).
>>>
>>> R.
>>
>> Thanks. I think if we'd like to reduce the number of tests, it would make the most
>> sense to merge the test cases in the way you've described based on their implementation
>> and target features. i.e.
>>
>> - type_redef_1.c : covers mve_pred16_t.
>> - type_redef_2.c : covers single-integer-vector types.
>> - type_redef_3.c : covers single-float-vector types.
>> - type_redef_4.c : covers integer-vector-tuple types.
>> - type_redef_5.c : covers float-vector-tuple types.
>>
>> The idea being that the test results for these tests should allow someone to triangulate
>> the cause of the failure. For example, if tests 4 and 5 fail, it is likely due to a
>> deficiency in the MVE tuple type implementation, rather than the handling of target-specific
>> features. More specific tests failures can be determined by looking through log files.
>>
>> Thanks,
>> Murray
>>
> 
> Merged files will still have the same number of tests, and the same possible test names, just from fewer source files.  So I don't think triangulation will be an issue.

Ok. In that case we could merge all source files into one which covers all types.

Thanks,
Murray
Murray Steele Nov. 25, 2021, 9:42 a.m. UTC | #5
Changes from original patch:

1. Merged test_redef_* test files into one
2. Encapsulated contents of arm-mve-builtins.h in namespace arm_mve (missed
   in initial patch).
3. Added extern declarations for scalar_types and acle_vector types to
   arm-mve-builtins.h (missed in initial patch).
4. Added arm-mve-builtins.(cc|h) to gt_targets for arm-*-*-* (missed in
   initial patch).
5. Added include for gt-arm-mve-builtins.h to arm-mve-builtins.cc (missed in
   initial patch).
6. Removed explicit initialisation of handle_arm_mve_types_p as it is unneeded.

---

This patch moves the implementation of MVE ACLE types from
arm_mve_types.h to inside GCC via a new pragma, which replaces the prior
type definitions. This allows for the types to be used internally for
intrinsic function definitions.

Bootstrapped and regression tested on arm-none-linux-gnuabihf, and
regression tested on arm-eabi -- no issues.

Thanks,
Murray

gcc/ChangeLog:

        * config.gcc: Add arm-mve-builtins.o to extra_objs for arm-*-*-*
        targets.
        * config/arm/arm-c.c (arm_pragma_arm): Handle new pragma.
        (arm_register_target_pragmas): Register new pragma.
        * config/arm/arm-protos.h: Add arm_mve namespace and declare
        arm_handle_mve_types_h.
        * config/arm/arm_mve_types.h: Replace MVE type definitions with
        new pragma.
        * config/arm/t-arm: Add arm-mve-builtins.o target.
        * config/arm/arm-mve-builtins.cc: New file.
        * config/arm/arm-mve-builtins.def: New file.
        * config/arm/arm-mve-builtins.h: New file.

gcc/testsuite/ChangeLog:

        * gcc.target/arm/mve/mve.exp: Add new subdirectories.
        * gcc.target/arm/mve/general-c/type_redef_1.c: New test.
        * gcc.target/arm/mve/general/double_pragmas_1.c: New test.
        * gcc.target/arm/mve/general/nomve_1.c: New test.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index edd12655c4a1e6feb09aabbee77eacd9f66b4171..0aa386403112eff80cb5071fa6ff2fdbe610c9fc 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -352,14 +352,14 @@ 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"
 	cxx_target_objs="arm-c.o"
 	d_target_objs="arm-d.o"
 	extra_options="${extra_options} arm/arm-tables.opt"
-	target_gtfiles="\$(srcdir)/config/arm/arm-builtins.c"
+	target_gtfiles="\$(srcdir)/config/arm/arm-builtins.c \$(srcdir)/config/arm/arm-mve-builtins.h \$(srcdir)/config/arm/arm-mve-builtins.cc"
 	;;
 avr-*-*)
 	cpu_type=avr
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..99ddc8d49aad39e057c1c0d349c6c02c278553d6
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.cc
@@ -0,0 +1,196 @@
+/* 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;
+
+/* 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);
+    }
+}
+
+}
+
+using namespace arm_mve;
+
+#include "gt-arm-mve-builtins.h"
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..c165ce6997b4560fc87626be4bbaa0e8afcbbfed
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.h
@@ -0,0 +1,41 @@
+/* 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
+
+namespace arm_mve {
+
+/* 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
+
+extern tree scalar_types[NUM_VECTOR_TYPES];
+extern tree acle_vector_types[3][NUM_VECTOR_TYPES + 1];
+
+}
+
+#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..cd230f14b2bb136c4b4ab7b335394bc31eb04f71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/mve/general-c/type_redef_1.c
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_fp_ok } */
+/* { dg-add-options arm_v8_1m_mve_fp } */
+
+int mve_pred16_t; /* { dg-message "note: previous declaration of 'mve_pred16_t'" } */
+int int8x16_t; /* { dg-message "note: previous declaration of 'int8x16_t'" } */
+int int16x8_t; /* { dg-message "note: previous declaration of 'int16x8_t'" } */
+int int32x4_t; /* { dg-message "note: previous declaration of 'int32x4_t'" } */
+int int64x2_t; /* { dg-message "note: previous declaration of 'int64x2_t'" } */
+int uint8x16_t; /* { dg-message "note: previous declaration of 'uint8x16_t'" } */
+int uint16x8_t; /* { dg-message "note: previous declaration of 'uint16x8_t'" } */
+int uint32x4_t; /* { dg-message "note: previous declaration of 'uint32x4_t'" } */
+int uint64x2_t; /* { dg-message "note: previous declaration of 'uint64x2_t'" } */
+int float16x8_t; /* { dg-message "note: previous declaration of 'float16x8_t'" } */
+int float32x4_t; /* { dg-message "note: previous declaration of 'float32x4_t'" } */
+int int8x16x2_t; /* { dg-message "note: previous declaration of 'int8x16x2_t'" } */
+int int8x16x4_t; /* { dg-message "note: previous declaration of 'int8x16x4_t'" } */
+int int16x8x2_t; /* { dg-message "note: previous declaration of 'int16x8x2_t'" } */
+int int16x8x4_t; /* { dg-message "note: previous declaration of 'int16x8x4_t'" } */
+int int32x4x2_t; /* { dg-message "note: previous declaration of 'int32x4x2_t'" } */
+int int32x4x4_t; /* { dg-message "note: previous declaration of 'int32x4x4_t'" } */
+int int64x2x2_t; /* { dg-message "note: previous declaration of 'int64x2x2_t'" } */
+int int64x2x4_t; /* { dg-message "note: previous declaration of 'int64x2x4_t'" } */
+int uint8x16x2_t; /* { dg-message "note: previous declaration of 'uint8x16x2_t'" } */
+int uint8x16x4_t; /* { dg-message "note: previous declaration of 'uint8x16x4_t'" } */
+int uint16x8x2_t; /* { dg-message "note: previous declaration of 'uint16x8x2_t'" } */
+int uint16x8x4_t; /* { dg-message "note: previous declaration of 'uint16x8x4_t'" } */
+int uint32x4x2_t; /* { dg-message "note: previous declaration of 'uint32x4x2_t'" } */
+int uint32x4x4_t; /* { dg-message "note: previous declaration of 'uint32x4x4_t'" } */
+int uint64x2x2_t; /* { dg-message "note: previous declaration of 'uint64x2x2_t'" } */
+int uint64x2x4_t; /* { dg-message "note: previous declaration of 'uint64x2x4_t'" } */
+int float16x8x2_t; /* { dg-message "note: previous declaration of 'float16x8x2_t'" } */
+int float16x8x4_t; /* { dg-message "note: previous declaration of 'float16x8x4_t'" } */
+int float32x4x2_t; /* { dg-message "note: previous declaration of 'float32x4x2_t'" } */
+int float32x4x4_t; /* { dg-message "note: previous declaration of 'float32x4x4_t'" } */
+
+#pragma GCC arm "arm_mve_types.h"  /* { dg-error {'mve_pred16_t' redeclared} } */
+  /* { dg-error {'int8x16_t' redeclared} "" {target *-*-*} .-1 } */
+  /* { dg-error {'int16x8_t' redeclared} "" {target *-*-*} .-2 } */
+  /* { dg-error {'int32x4_t' redeclared} "" {target *-*-*} .-3 } */
+  /* { dg-error {'int64x2_t' redeclared} "" {target *-*-*} .-4 } */
+  /* { dg-error {'uint8x16_t' redeclared} "" {target *-*-*} .-5 } */
+  /* { dg-error {'uint16x8_t' redeclared} "" {target *-*-*} .-6 } */
+  /* { dg-error {'uint32x4_t' redeclared} "" {target *-*-*} .-7 } */
+  /* { dg-error {'uint64x2_t' redeclared} "" {target *-*-*} .-8 } */
+  /* { dg-error {'float16x8_t' redeclared} "" {target *-*-*} .-9 } */
+  /* { dg-error {'float32x4_t' redeclared} "" {target *-*-*} .-10 } */
+  /* { dg-error {'int8x16x2_t' redeclared} "" {target *-*-*} .-11 } */
+  /* { dg-error {'int8x16x4_t' redeclared} "" {target *-*-*} .-12 } */
+  /* { dg-error {'int16x8x2_t' redeclared} "" {target *-*-*} .-13 } */
+  /* { dg-error {'int16x8x4_t' redeclared} "" {target *-*-*} .-14 } */
+  /* { dg-error {'int32x4x2_t' redeclared} "" {target *-*-*} .-15 } */
+  /* { dg-error {'int32x4x4_t' redeclared} "" {target *-*-*} .-16 } */
+  /* { dg-error {'int64x2x2_t' redeclared} "" {target *-*-*} .-17 } */
+  /* { dg-error {'int64x2x4_t' redeclared} "" {target *-*-*} .-18 } */
+  /* { dg-error {'uint8x16x2_t' redeclared} "" {target *-*-*} .-19 } */
+  /* { dg-error {'uint8x16x4_t' redeclared} "" {target *-*-*} .-20 } */
+  /* { dg-error {'uint16x8x2_t' redeclared} "" {target *-*-*} .-21 } */
+  /* { dg-error {'uint16x8x4_t' redeclared} "" {target *-*-*} .-22 } */
+  /* { dg-error {'uint32x4x2_t' redeclared} "" {target *-*-*} .-23 } */
+  /* { dg-error {'uint32x4x4_t' redeclared} "" {target *-*-*} .-24 } */
+  /* { dg-error {'uint64x2x2_t' redeclared} "" {target *-*-*} .-25 } */
+  /* { dg-error {'uint64x2x4_t' redeclared} "" {target *-*-*} .-26 } */
+  /* { dg-error {'float16x8x2_t' redeclared} "" {target *-*-*} .-27 } */
+  /* { dg-error {'float16x8x4_t' redeclared} "" {target *-*-*} .-28 } */
+  /* { dg-error {'float32x4x2_t' redeclared} "" {target *-*-*} .-29 } */
+  /* { dg-error {'float32x4x4_t' redeclared} "" {target *-*-*} .-30 } */
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
Murray Steele Dec. 8, 2021, 10:04 a.m. UTC | #6
Hi,


I'd like to ping this patch revision [1]. 

Thanks,
Murray

[1]: https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585400.html

---

On 25/11/2021 09:42, Murray Steele wrote:
> Changes from original patch:
> 
> 1. Merged test_redef_* test files into one
> 2. Encapsulated contents of arm-mve-builtins.h in namespace arm_mve (missed
>    in initial patch).
> 3. Added extern declarations for scalar_types and acle_vector types to
>    arm-mve-builtins.h (missed in initial patch).
> 4. Added arm-mve-builtins.(cc|h) to gt_targets for arm-*-*-* (missed in
>    initial patch).
> 5. Added include for gt-arm-mve-builtins.h to arm-mve-builtins.cc (missed in
>    initial patch).
> 6. Removed explicit initialisation of handle_arm_mve_types_p as it is unneeded.
> 
> ---
> 
> This patch moves the implementation of MVE ACLE types from
> arm_mve_types.h to inside GCC via a new pragma, which replaces the prior
> type definitions. This allows for the types to be used internally for
> intrinsic function definitions.
> 
> Bootstrapped and regression tested on arm-none-linux-gnuabihf, and
> regression tested on arm-eabi -- no issues.
> 
> Thanks,
> Murray
> 
> gcc/ChangeLog:
> 
>         * config.gcc: Add arm-mve-builtins.o to extra_objs for arm-*-*-*
>         targets.
>         * config/arm/arm-c.c (arm_pragma_arm): Handle new pragma.
>         (arm_register_target_pragmas): Register new pragma.
>         * config/arm/arm-protos.h: Add arm_mve namespace and declare
>         arm_handle_mve_types_h.
>         * config/arm/arm_mve_types.h: Replace MVE type definitions with
>         new pragma.
>         * config/arm/t-arm: Add arm-mve-builtins.o target.
>         * config/arm/arm-mve-builtins.cc: New file.
>         * config/arm/arm-mve-builtins.def: New file.
>         * config/arm/arm-mve-builtins.h: New file.
> 
> gcc/testsuite/ChangeLog:
> 
>         * gcc.target/arm/mve/mve.exp: Add new subdirectories.
>         * gcc.target/arm/mve/general-c/type_redef_1.c: New test.
>         * gcc.target/arm/mve/general/double_pragmas_1.c: New test.
>         * gcc.target/arm/mve/general/nomve_1.c: New test.
>
Richard Earnshaw Dec. 8, 2021, 3:23 p.m. UTC | #7
On 25/11/2021 09:42, Murray Steele via Gcc-patches wrote:
> Changes from original patch:
> 
> 1. Merged test_redef_* test files into one
> 2. Encapsulated contents of arm-mve-builtins.h in namespace arm_mve (missed
>     in initial patch).
> 3. Added extern declarations for scalar_types and acle_vector types to
>     arm-mve-builtins.h (missed in initial patch).
> 4. Added arm-mve-builtins.(cc|h) to gt_targets for arm-*-*-* (missed in
>     initial patch).
> 5. Added include for gt-arm-mve-builtins.h to arm-mve-builtins.cc (missed in
>     initial patch).
> 6. Removed explicit initialisation of handle_arm_mve_types_p as it is unneeded.
> 
> ---
> 
> This patch moves the implementation of MVE ACLE types from
> arm_mve_types.h to inside GCC via a new pragma, which replaces the prior
> type definitions. This allows for the types to be used internally for
> intrinsic function definitions.
> 
> Bootstrapped and regression tested on arm-none-linux-gnuabihf, and
> regression tested on arm-eabi -- no issues.
> 
> Thanks,
> Murray
> 

Nearly there, but...

Your changelog entry needs some work:

> gcc/ChangeLog:
> 
>          * config.gcc: Add arm-mve-builtins.o to extra_objs for arm-*-*-*
>          targets.

  * config.gcc (arm*-*-*): Add arm-mve-builtins.o to extra_objs.

>          * config/arm/arm-c.c (arm_pragma_arm): Handle new pragma.

  ... Handle "#pragma GCC arm".

>          (arm_register_target_pragmas): Register new pragma.
  ... Register it.

>          * config/arm/arm-protos.h: Add arm_mve namespace and declare
>          arm_handle_mve_types_h.

  ...arm-protos.h (arm_mve::arm_handle_mve_types.h): New prototype.

>          * config/arm/arm_mve_types.h: Replace MVE type definitions with
>          new pragma.
>          * config/arm/t-arm: Add arm-mve-builtins.o target.

.../t-arm (arm-mve-builtins.o): New target rule.

>          * config/arm/arm-mve-builtins.cc: New file.
>          * config/arm/arm-mve-builtins.def: New file.
>          * config/arm/arm-mve-builtins.h: New file.
> 
> gcc/testsuite/ChangeLog:
> 
>          * gcc.target/arm/mve/mve.exp: Add new subdirectories.
>          * gcc.target/arm/mve/general-c/type_redef_1.c: New test.
>          * gcc.target/arm/mve/general/double_pragmas_1.c: New test.
>          * gcc.target/arm/mve/general/nomve_1.c: New test.
> 


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 @@

+#ifndef DEF_MVE_TYPE
+#define DEF_MVE_TYPE(A, B)
+#endif

When would this file ever be included when this macro wasn't defined? 
Better to require the caller to define this by using #error if it's missing.

then...

+
+#undef DEF_MVE_TYPE

This isn't needed anymore, because caller should undef it after use.

diff --git a/gcc/config/arm/arm-mve-builtins.cc 
b/gcc/config/arm/arm-mve-builtins.cc
new file mode 100644
index 
0000000000000000000000000000000000000000..99ddc8d49aad39e057c1c0d349c6c02c278553d6
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.cc

...
+}
+
+}
+
+using namespace arm_mve;

Add a comment that this is the end of the earlier namespace declaration.

diff --git a/gcc/config/arm/arm-mve-builtins.h 
b/gcc/config/arm/arm-mve-builtins.h
new file mode 100644
index 
0000000000000000000000000000000000000000..c165ce6997b4560fc87626be4bbaa0e8afcbbfed
--- /dev/null
+++ b/gcc/config/arm/arm-mve-builtins.h
@@ -0,0 +1,41 @@


...
+}
+

Likewise.

R.
Murray Steele Dec. 8, 2021, 3:39 p.m. UTC | #8
Hi,

Thank you for the feedback, I'll make the noted changes to the changelog and
add the missing end-of-namespace comments.

On 08/12/2021 15:23, Richard Earnshaw wrote:

> 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 @@
> 
> +#ifndef DEF_MVE_TYPE
> +#define DEF_MVE_TYPE(A, B)
> +#endif
> 
> When would this file ever be included when this macro wasn't defined? Better to require the caller to define this by using #error if it's missing.
> 
> then...
> 
> +
> +#undef DEF_MVE_TYPE
> 
> This isn't needed anymore, because caller should undef it after use.


I'd added this because later patches that build from this series will most
likely need to define further DEF_MVE_* macros, in the style of the current
SVE implementation. You are right that it is unnecessary for right now though,
and I'll remove it too.

Thanks again,

Murray
Richard Earnshaw Dec. 8, 2021, 5:34 p.m. UTC | #9
On 08/12/2021 15:39, Murray Steele via Gcc-patches wrote:
> Hi,
> 
> Thank you for the feedback, I'll make the noted changes to the changelog and
> add the missing end-of-namespace comments.
> 
> On 08/12/2021 15:23, Richard Earnshaw wrote:
> 
>> 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 @@
>>
>> +#ifndef DEF_MVE_TYPE
>> +#define DEF_MVE_TYPE(A, B)
>> +#endif
>>
>> When would this file ever be included when this macro wasn't defined? Better to require the caller to define this by using #error if it's missing.
>>
>> then...
>>
>> +
>> +#undef DEF_MVE_TYPE
>>
>> This isn't needed anymore, because caller should undef it after use.
> 
> 
> I'd added this because later patches that build from this series will most
> likely need to define further DEF_MVE_* macros, in the style of the current
> SVE implementation. You are right that it is unnecessary for right now though,
> and I'll remove it too.

The best thing to do in that case then is to require the caller to
explicitly define DEF_MVE_TYPE as a NOP when it isn't required.  It
means a bit more churn at each call site, but I think it's more robust
longer term as it is clear which operations are going to be extracted.

R.

> 
> Thanks again,
> 
> Murray
>
diff mbox series

Patch

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