[Arm,2/4] Custom Datapath Extension intrinsics: instructions using FPU/MVE S/D registers

Message ID DB7PR08MB3227E3DCA796334231BAF0BC84FA0@DB7PR08MB3227.eurprd08.prod.outlook.com
State New
Headers show
Series
  • [Arm,1/3] Support for Arm Custom Datapath Extension (CDE): enable the feature
Related show

Commit Message

Dennis Zhang March 13, 2020, 7:31 p.m.
Hi all,

This patch is part of a series that adds support for the ARMv8.m Custom Datapath Extension (CDE).
It enables the ACLE intrinsics calling VCX1<A>, VCX2<A>, and VCX3<A> instructions who work with FPU/MVE 32-bit/64-bit registers.

This patch depends on the CDE feature patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-March/541921.html
It also depends on the MVE framework patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540415.html
ISA has been announced at https://developer.arm.com/architectures/instruction-sets/custom-instructions

Regtested and bootstrapped for arm-none-linux-gnueabi-armv8-m.main.

Is it OK for commit please?

Cheers
Dennis

gcc/ChangeLog:

2020-03-12  Dennis Zhang  <dennis.zhang@arm.com>
	     Matthew Malcomson <matthew.malcomson@arm.com>

	* config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro.
	(CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise.
	(CX_TERNARY_QUALIFIERS): Likewise.
	(ARM_BUILTIN_CDE_PATTERN_START): Likewise.
	(ARM_BUILTIN_CDE_PATTERN_END): Likewise.
	(arm_init_acle_builtins): Initialize CDE builtins.
	(arm_expand_acle_builtin): Check CDE constant operands.
	* config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the range
	of CDE constant operand.
	(ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3): Likewise.
	* config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface.
	(__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise.
	(__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise.
	(__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise.
	(__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise.
	* config/arm/arm_cde_builtins.def: New file.
	* config/arm/iterators.md (V_reg): New attribute of SI.
	* config/arm/predicates.md (const_int_coproc_operand): New.
	(const_int_vcde1_operand, const_int_vcde2_operand): New.
	(const_int_vcde3_operand): New.
	* config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New.
	* config/arm/vfp.md (arm_vcx1<mode>): New entry.
	(arm_vcx1a<mode>, arm_vcx2<mode>, arm_vcx2a<mode>): Likewise.
	(arm_vcx3<mode>, arm_vcx3a<mode>): Likewise.

gcc/testsuite/ChangeLog:

2020-03-12  Dennis Zhang  <dennis.zhang@arm.com>

	* gcc.target/arm/acle/cde_v_1.c: New test.
	* gcc.target/arm/acle/cde_v_1_err.c: New test.
	* gcc.target/arm/acle/cde_v_1_mve.c: New test.

Comments

Dennis Zhang March 20, 2020, 3:18 p.m. | #1
Hi all,

This patch is updated as attached.
It's rebased to the top. Is it ready for commit please?

Cheers
Dennis

> Hi all,
>
> This patch is part of a series that adds support for the ARMv8.m Custom Datapath Extension (CDE).
> It enables the ACLE intrinsics calling VCX1<A>, VCX2<A>, and VCX3<A> instructions who work with FPU/MVE 32-bit/64-bit registers.
>
> This patch depends on the CDE feature patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-March/541921.html
> It also depends on the MVE framework patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540415.html
> ISA has been announced at https://developer.arm.com/architectures/instruction-sets/custom-instructions
>
> Regtested and bootstrapped for arm-none-linux-gnueabi-armv8-m.main.
>
> Is it OK for commit please?
>
> Cheers
> Dennis
>
> gcc/ChangeLog:
>
> 2020-03-12  Dennis Zhang  <dennis.zhang@arm.com>
>              Matthew Malcomson <matthew.malcomson@arm.com>
>
>         * config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro.
>         (CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise.
>         (CX_TERNARY_QUALIFIERS): Likewise.
>         (ARM_BUILTIN_CDE_PATTERN_START): Likewise.
>         (ARM_BUILTIN_CDE_PATTERN_END): Likewise.
>         (arm_init_acle_builtins): Initialize CDE builtins.
>         (arm_expand_acle_builtin): Check CDE constant operands.
>         * config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the range
>         of CDE constant operand.
>         (ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3): Likewise.
>         * config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface.
>         (__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise.
>         (__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise.
>         (__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise.
>         (__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise.
>         * config/arm/arm_cde_builtins.def: New file.
>         * config/arm/iterators.md (V_reg): New attribute of SI.
>         * config/arm/predicates.md (const_int_coproc_operand): New.
>         (const_int_vcde1_operand, const_int_vcde2_operand): New.
>         (const_int_vcde3_operand): New.
>         * config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New.
>         * config/arm/vfp.md (arm_vcx1<mode>): New entry.
>         (arm_vcx1a<mode>, arm_vcx2<mode>, arm_vcx2a<mode>): Likewise.
>         (arm_vcx3<mode>, arm_vcx3a<mode>): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> 2020-03-12  Dennis Zhang  <dennis.zhang@arm.com>
>
>         * gcc.target/arm/acle/cde_v_1.c: New test.
>         * gcc.target/arm/acle/cde_v_1_err.c: New test.
>         * gcc.target/arm/acle/cde_v_1_mve.c: New test.
>
Dennis Zhang April 7, 2020, 12:31 p.m. | #2
Hi all,

This patch is updated to support DImode for vfp target as required by CDE.
Changelog is updated as following.

Is this ready for commit please?

Cheers
Dennis

gcc/ChangeLog:

2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>
	    Matthew Malcomson <matthew.malcomson@arm.com>

	* config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro.
	(CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise.
	(CX_TERNARY_QUALIFIERS): Likewise.
	(ARM_BUILTIN_CDE_PATTERN_START): Likewise.
	(ARM_BUILTIN_CDE_PATTERN_END): Likewise.
	(arm_init_acle_builtins): Initialize CDE builtins.
	(arm_expand_acle_builtin): Check CDE constant operands.
	* config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the range
	of CDE constant operand.
	* config/arm/arm.c (arm_hard_regno_mode_ok): Support DImode for
	TARGET_VFP_BASE.
	(ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3): Likewise.
	* config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface.
	(__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise.
	(__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise.
	(__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise.
	(__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise.
	* config/arm/arm_cde_builtins.def: New file.
	* config/arm/iterators.md (V_reg): New attribute of SI.
	* config/arm/predicates.md (const_int_coproc_operand): New.
	(const_int_vcde1_operand, const_int_vcde2_operand): New.
	(const_int_vcde3_operand): New.
	* config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New.
	* config/arm/vfp.md (arm_vcx1<mode>): New entry.
	(arm_vcx1a<mode>, arm_vcx2<mode>, arm_vcx2a<mode>): Likewise.
	(arm_vcx3<mode>, arm_vcx3a<mode>): Likewise.

gcc/testsuite/ChangeLog:

2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>

	* gcc.target/arm/acle/cde_v_1.c: New test.
	* gcc.target/arm/acle/cde_v_1_err.c: New test.
	* gcc.target/arm/acle/cde_v_1_mve.c: New test.

> Hi all,
>
> This patch is updated as attached.
> It's rebased to the top. Is it ready for commit please?
>
> Cheers
> Dennis
>
> > Hi all,
> >
> > This patch is part of a series that adds support for the ARMv8.m Custom Datapath Extension (CDE).
> > It enables the ACLE intrinsics calling VCX1<A>, VCX2<A>, and VCX3<A> instructions who work with FPU/MVE 32-bit/64-bit registers.
> >
> > This patch depends on the CDE feature patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-March/541921.html
> > It also depends on the MVE framework patch: https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540415.html
> > ISA has been announced at https://developer.arm.com/architectures/instruction-sets/custom-instructions
> >
> > Regtested and bootstrapped for arm-none-linux-gnueabi-armv8-m.main.
> >
> > Is it OK for commit please?
> >
> > Cheers
> > Dennis
> >
Kyrylo Tkachov April 7, 2020, 2:07 p.m. | #3
Hi Dennis,

> -----Original Message-----

> From: Dennis Zhang <Dennis.Zhang@arm.com>

> Sent: 07 April 2020 13:31

> To: gcc-patches@gcc.gnu.org

> Cc: nd <nd@arm.com>; Richard Earnshaw <Richard.Earnshaw@arm.com>;

> Ramana Radhakrishnan <Ramana.Radhakrishnan@arm.com>; Kyrylo

> Tkachov <Kyrylo.Tkachov@arm.com>

> Subject: Re: [PATCH][Arm][2/4] Custom Datapath Extension intrinsics:

> instructions using FPU/MVE S/D registers

> 

> Hi all,

> 

> This patch is updated to support DImode for vfp target as required by CDE.

> Changelog is updated as following.

> 

> Is this ready for commit please?


This is ok.
Has the first patch been updated and committed yet?
Thanks,
Kyrill

> 

> Cheers

> Dennis

> 

> gcc/ChangeLog:

> 

> 2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>

>     Matthew Malcomson <matthew.malcomson@arm.com>

> 

> * config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro.

> (CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise.

> (CX_TERNARY_QUALIFIERS): Likewise.

> (ARM_BUILTIN_CDE_PATTERN_START): Likewise.

> (ARM_BUILTIN_CDE_PATTERN_END): Likewise.

> (arm_init_acle_builtins): Initialize CDE builtins.

> (arm_expand_acle_builtin): Check CDE constant operands.

> * config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the

> range

> of CDE constant operand.

> * config/arm/arm.c (arm_hard_regno_mode_ok): Support DImode for

> TARGET_VFP_BASE.

> (ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3):

> Likewise.

> * config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface.

> (__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise.

> (__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise.

> (__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise.

> (__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise.

> * config/arm/arm_cde_builtins.def: New file.

> * config/arm/iterators.md (V_reg): New attribute of SI.

> * config/arm/predicates.md (const_int_coproc_operand): New.

> (const_int_vcde1_operand, const_int_vcde2_operand): New.

> (const_int_vcde3_operand): New.

> * config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New.

> * config/arm/vfp.md (arm_vcx1<mode>): New entry.

> (arm_vcx1a<mode>, arm_vcx2<mode>, arm_vcx2a<mode>): Likewise.

> (arm_vcx3<mode>, arm_vcx3a<mode>): Likewise.

> 

> gcc/testsuite/ChangeLog:

> 

> 2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>

> 

> * gcc.target/arm/acle/cde_v_1.c: New test.

> * gcc.target/arm/acle/cde_v_1_err.c: New test.

> * gcc.target/arm/acle/cde_v_1_mve.c: New test.

> 

> > Hi all,

> >

> > This patch is updated as attached.

> > It's rebased to the top. Is it ready for commit please?

> >

> > Cheers

> > Dennis

> >

> > > Hi all,

> > >

> > > This patch is part of a series that adds support for the ARMv8.m Custom

> Datapath Extension (CDE).

> > > It enables the ACLE intrinsics calling VCX1<A>, VCX2<A>, and VCX3<A>

> instructions who work with FPU/MVE 32-bit/64-bit registers.

> > >

> > > This patch depends on the CDE feature patch:

> https://gcc.gnu.org/pipermail/gcc-patches/2020-March/541921.html

> > > It also depends on the MVE framework patch:

> https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540415.html

> > > ISA has been announced at

> https://developer.arm.com/architectures/instruction-sets/custom-

> instructions

> > >

> > > Regtested and bootstrapped for arm-none-linux-gnueabi-armv8-m.main.

> > >

> > > Is it OK for commit please?

> > >

> > > Cheers

> > > Dennis

> > >
Dennis Zhang April 8, 2020, 3:25 p.m. | #4
Hi kyrylo,

> ________________________________________
> From: Kyrylo Tkachov <Kyrylo.Tkachov@arm.com>
> Sent: Tuesday, April 7, 2020 3:07 PM
> To: Dennis Zhang; gcc-patches@gcc.gnu.org
> Cc: nd; Richard Earnshaw; Ramana Radhakrishnan
> Subject: RE: [PATCH][Arm][2/4]  Custom Datapath Extension intrinsics: instructions using FPU/MVE S/D registers
>
> Hi Dennis,
>
> > -----Original Message-----
> > From: Dennis Zhang <Dennis.Zhang@arm.com>
> > Sent: 07 April 2020 13:31
> > To: gcc-patches@gcc.gnu.org
> > Cc: nd <nd@arm.com>; Richard Earnshaw <Richard.Earnshaw@arm.com>;
> > Ramana Radhakrishnan <Ramana.Radhakrishnan@arm.com>; Kyrylo
> > Tkachov <Kyrylo.Tkachov@arm.com>
> > Subject: Re: [PATCH][Arm][2/4] Custom Datapath Extension intrinsics:
> > instructions using FPU/MVE S/D registers
> >
> > Hi all,
> >
> > This patch is updated to support DImode for vfp target as required by CDE.
> > Changelog is updated as following.
> >
> > Is this ready for commit please?
>
> This is ok.
> Has the first patch been updated and committed yet?
> Thanks,
> Kyrill
>

This patch has been committed as 07b9bfd02b88cad2f6b3f50ad610dd75cb989ed3.

Many thanks
Dennis

> >
> > Cheers
> > Dennis
> >
> > gcc/ChangeLog:
> >
> > 2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>
> >     Matthew Malcomson <matthew.malcomson@arm.com>
> >
> > * config/arm/arm-builtins.c (CX_IMM_QUALIFIERS): New macro.
> > (CX_UNARY_QUALIFIERS, CX_BINARY_QUALIFIERS): Likewise.
> > (CX_TERNARY_QUALIFIERS): Likewise.
> > (ARM_BUILTIN_CDE_PATTERN_START): Likewise.
> > (ARM_BUILTIN_CDE_PATTERN_END): Likewise.
> > (arm_init_acle_builtins): Initialize CDE builtins.
> > (arm_expand_acle_builtin): Check CDE constant operands.
> > * config/arm/arm.h (ARM_CDE_CONST_COPROC): New macro to set the
> > range
> > of CDE constant operand.
> > * config/arm/arm.c (arm_hard_regno_mode_ok): Support DImode for
> > TARGET_VFP_BASE.
> > (ARM_VCDE_CONST_1, ARM_VCDE_CONST_2, ARM_VCDE_CONST_3):
> > Likewise.
> > * config/arm/arm_cde.h (__arm_vcx1_u32): New macro of ACLE interface.
> > (__arm_vcx1a_u32, __arm_vcx2_u32, __arm_vcx2a_u32): Likewise.
> > (__arm_vcx3_u32, __arm_vcx3a_u32, __arm_vcx1d_u64): Likewise.
> > (__arm_vcx1da_u64, __arm_vcx2d_u64, __arm_vcx2da_u64): Likewise.
> > (__arm_vcx3d_u64, __arm_vcx3da_u64): Likewise.
> > * config/arm/arm_cde_builtins.def: New file.
> > * config/arm/iterators.md (V_reg): New attribute of SI.
> > * config/arm/predicates.md (const_int_coproc_operand): New.
> > (const_int_vcde1_operand, const_int_vcde2_operand): New.
> > (const_int_vcde3_operand): New.
> > * config/arm/unspecs.md (UNSPEC_VCDE, UNSPEC_VCDEA): New.
> > * config/arm/vfp.md (arm_vcx1<mode>): New entry.
> > (arm_vcx1a<mode>, arm_vcx2<mode>, arm_vcx2a<mode>): Likewise.
> > (arm_vcx3<mode>, arm_vcx3a<mode>): Likewise.
> >
> > gcc/testsuite/ChangeLog:
> >
> > 2020-04-07  Dennis Zhang  <dennis.zhang@arm.com>
> >
> > * gcc.target/arm/acle/cde_v_1.c: New test.
> > * gcc.target/arm/acle/cde_v_1_err.c: New test.
> > * gcc.target/arm/acle/cde_v_1_mve.c: New test.
> >
> > > Hi all,
> > >
> > > This patch is updated as attached.
> > > It's rebased to the top. Is it ready for commit please?
> > >
> > > Cheers
> > > Dennis
> > >
> > > > Hi all,
> > > >
> > > > This patch is part of a series that adds support for the ARMv8.m Custom
> > Datapath Extension (CDE).
> > > > It enables the ACLE intrinsics calling VCX1<A>, VCX2<A>, and VCX3<A>
> > instructions who work with FPU/MVE 32-bit/64-bit registers.
> > > >
> > > > This patch depends on the CDE feature patch:
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-March/541921.html
> > > > It also depends on the MVE framework patch:
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-February/540415.html
> > > > ISA has been announced at
> > https://developer.arm.com/architectures/instruction-sets/custom-
> > instructions
> > > >
> > > > Regtested and bootstrapped for arm-none-linux-gnueabi-armv8-m.main.
> > > >
> > > > Is it OK for commit please?
> > > >
> > > > Cheers
> > > > Dennis

Patch

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 4d31405cf6e09e3a61faa3e8142940bbdb23c60a..89142a276b071b069cddabb5170ad0d4ca213d20 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -305,6 +305,35 @@  arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
 #define MRRC_QUALIFIERS \
   (arm_mrrc_qualifiers)
 
+/* T (immediate, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_cx_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_none, qualifier_immediate, qualifier_unsigned_immediate };
+#define CX_IMM_QUALIFIERS (arm_cx_imm_qualifiers)
+
+/* T (immediate, T, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_cx_unary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_none, qualifier_immediate, qualifier_none,
+      qualifier_unsigned_immediate };
+#define CX_UNARY_QUALIFIERS (arm_cx_unary_qualifiers)
+
+/* T (immediate, T, T, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_cx_binary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_none, qualifier_immediate,
+      qualifier_none, qualifier_none,
+      qualifier_unsigned_immediate };
+#define CX_BINARY_QUALIFIERS (arm_cx_binary_qualifiers)
+
+/* T (immediate, T, T, T, unsigned immediate).  */
+static enum arm_type_qualifiers
+arm_cx_ternary_qualifiers[SIMD_MAX_BUILTIN_ARGS]
+  = { qualifier_none, qualifier_immediate,
+      qualifier_none, qualifier_none, qualifier_none,
+      qualifier_unsigned_immediate };
+#define CX_TERNARY_QUALIFIERS (arm_cx_ternary_qualifiers)
+
 /* The first argument (return type) of a store should be void type,
    which we represent with qualifier_void.  Their first operand will be
    a DImode pointer to the location to store to, so we must use
@@ -438,7 +467,23 @@  static arm_builtin_datum acle_builtin_data[] =
 };
 
 #undef VAR1
+/* IMM_MAX sets the maximum valid value of the CDE immediate operand.
+   ECF_FLAG sets the flag used for set_call_expr_flags.  */
+#define VAR1(T, N, A, IMM_MAX, ECF_FLAG) \
+  {{#N #A, UP (A), CODE_FOR_arm_##N##A, 0, T##_QUALIFIERS}, IMM_MAX, ECF_FLAG},
+
+typedef struct {
+  arm_builtin_datum base;
+  unsigned int imm_max;
+  int ecf_flag;
+} arm_builtin_cde_datum;
+
+static arm_builtin_cde_datum cde_builtin_data[] =
+{
+#include "arm_cde_builtins.def"
+};
 
+#undef VAR1
 #define VAR1(T, N, X) \
   ARM_BUILTIN_NEON_##N##X,
 
@@ -732,6 +777,14 @@  enum arm_builtins
 
 #include "arm_acle_builtins.def"
 
+#undef VAR1
+#define VAR1(T, N, X, ... ) \
+  ARM_BUILTIN_##N##X,
+
+  ARM_BUILTIN_CDE_BASE,
+
+#include "arm_cde_builtins.def"
+
   ARM_BUILTIN_MAX
 };
 
@@ -744,6 +797,12 @@  enum arm_builtins
 #define ARM_BUILTIN_ACLE_PATTERN_START \
   (ARM_BUILTIN_ACLE_BASE + 1)
 
+#define ARM_BUILTIN_CDE_PATTERN_START \
+  (ARM_BUILTIN_CDE_BASE + 1)
+
+#define ARM_BUILTIN_CDE_PATTERN_END \
+  (ARM_BUILTIN_CDE_BASE + ARRAY_SIZE (cde_builtin_data))
+
 #undef CF
 #undef VAR1
 #undef VAR2
@@ -1263,6 +1322,15 @@  arm_init_acle_builtins (void)
       arm_builtin_datum *d = &acle_builtin_data[i];
       arm_init_builtin (fcode, d, "__builtin_arm");
     }
+
+  fcode = ARM_BUILTIN_CDE_PATTERN_START;
+  for (i = 0; i < ARRAY_SIZE (cde_builtin_data); i++, fcode++)
+    {
+      arm_builtin_cde_datum *cde = &cde_builtin_data[i];
+      arm_builtin_datum *d = &cde->base;
+      arm_init_builtin (fcode, d, "__builtin_arm");
+      set_call_expr_flags (arm_builtin_decls[fcode], cde->ecf_flag);
+    }
 }
 
 /* Set up all the NEON builtins, even builtins for instructions that are not
@@ -2373,8 +2441,29 @@  constant_arg:
 	      if (!(*insn_data[icode].operand[opno].predicate)
 		  (op[argc], mode[argc]))
 		{
-		  error ("%Kargument %d must be a constant immediate",
-			 exp, argc + 1);
+		  if (IN_RANGE (fcode, ARM_BUILTIN_CDE_PATTERN_START,
+				ARM_BUILTIN_CDE_PATTERN_END))
+		    {
+		      if (argc == 0)
+			{
+			  unsigned int cp_bit = UINTVAL (op[argc]);
+			  if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC))
+			    error ("%Kcoprocessor %d is not enabled "
+				   "with +cdecp%d", exp, cp_bit, cp_bit);
+			  else
+			    error ("%Kcoproc must be a constant immediate in "
+				   "range [0-%d] enabled with +cdecp<N>", exp,
+				   ARM_CDE_CONST_COPROC);
+			}
+		      else
+			error ("%Kargument %d must be a constant immediate "
+			       "in range [0-%d]", exp, argc + 1,
+			       cde_builtin_data[fcode -
+			       ARM_BUILTIN_CDE_PATTERN_START].imm_max);
+		    }
+		  else
+		    error ("%Kargument %d must be a constant immediate",
+			   exp, argc + 1);
 		  /* We have failed to expand the pattern, and are safely
 		     in to invalid code.  But the mid-end will still try to
 		     build an assignment for this node while it expands,
@@ -2595,8 +2684,12 @@  arm_expand_acle_builtin (int fcode, tree exp, rtx target)
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
+
+  gcc_assert (fcode != ARM_BUILTIN_CDE_BASE);
   arm_builtin_datum *d
-    = &acle_builtin_data[fcode - ARM_BUILTIN_ACLE_PATTERN_START];
+    = (fcode < ARM_BUILTIN_CDE_BASE)
+      ? &acle_builtin_data[fcode - ARM_BUILTIN_ACLE_PATTERN_START]
+      : &cde_builtin_data[fcode - ARM_BUILTIN_CDE_PATTERN_START].base;
 
   return arm_expand_builtin_1 (fcode, exp, target, d);
 }
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 218ded1c015389214a647e346dba09c1f30ed407..27baa006c1867f66c38009137968c4e365034cbe 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -558,6 +558,10 @@  extern int arm_arch_bf16;
 extern int arm_arch_cde;
 extern int arm_arch_cde_coproc;
 extern const int arm_arch_cde_coproc_bits[];
+#define ARM_CDE_CONST_COPROC	7
+#define ARM_VCDE_CONST_1	((1 << 11) - 1)
+#define ARM_VCDE_CONST_2	((1 << 6 ) - 1)
+#define ARM_VCDE_CONST_3	((1 << 3 ) - 1)
 
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT  (MASK_APCS_FRAME)
diff --git a/gcc/config/arm/arm_cde.h b/gcc/config/arm/arm_cde.h
index f975754632f6e87da331a19a63300c4de3c1f033..4c9f7ebeed4e2abf532f53040f5891da8b1aadac 100644
--- a/gcc/config/arm/arm_cde.h
+++ b/gcc/config/arm/arm_cde.h
@@ -33,6 +33,77 @@  extern "C" {
 
 #include <stdint.h>
 
+#if defined (__ARM_FEATURE_CDE)
+
+#if defined (__ARM_FP) || defined (__ARM_FEATURE_MVE)
+
+/* CDE builtins using FPU/MVE registers.  */
+
+/* uint32_t
+   __arm_vcx1_u32(int coproc, uint32_t imm);  */
+#define __arm_vcx1_u32(coproc, imm) \
+	__builtin_arm_vcx1si(coproc, imm)
+
+/* uint32_t
+   __arm_vcx1a_u32(int coproc, uint32_t acc, uint32_t imm);  */
+#define __arm_vcx1a_u32(coproc, acc, imm) \
+	__builtin_arm_vcx1asi(coproc, acc, imm)
+
+/* uint32_t
+   __arm_vcx2_u32(int coproc, uint32_t n, uint32_t imm);  */
+#define __arm_vcx2_u32(coproc, n, imm) \
+	__builtin_arm_vcx2si(coproc, n, imm)
+
+/* uint32_t
+   __arm_vcx2a_u32(int coproc, uint32_t acc, uint32_t n, uint32_t imm);  */
+#define __arm_vcx2a_u32(coproc, acc, n, imm) \
+	__builtin_arm_vcx2asi(coproc, acc, n, imm)
+
+/* uint32_t
+   __arm_vcx3_u32(int coproc, uint32_t n, uint32_t m, uint32_t imm);  */
+#define __arm_vcx3_u32(coproc, n, m, imm) \
+	__builtin_arm_vcx3si(coproc, n, m, imm)
+
+/* uint32_t
+   __arm_vcx3a_u32(int coproc, uint32_t acc, uint32_t n, uint32_t m,
+		   uint32_t imm);  */
+#define __arm_vcx3a_u32(coproc, acc, n, m, imm) \
+	__builtin_arm_vcx3asi(coproc, acc, n, m, imm)
+
+/* uint64_t
+   __arm_vcx1d_u64(int coproc, uint32_t imm);  */
+#define __arm_vcx1d_u64(coproc, imm) \
+	__builtin_arm_vcx1di(coproc, imm)
+
+/* uint64_t
+   __arm_vcx1da_u64(int coproc, uint64_t acc, uint32_t imm);  */
+#define __arm_vcx1da_u64(coproc, acc, imm) \
+	__builtin_arm_vcx1adi(coproc, acc, imm)
+
+/* uint64_t
+   __arm_vcx2d_u64(int coproc, uint64_t m, uint32_t imm);  */
+#define __arm_vcx2d_u64(coproc, m, imm) \
+	__builtin_arm_vcx2di(coproc, m, imm)
+
+/* uint64_t
+   __arm_vcx2da_u64(int coproc, uint64_t acc, uint64_t m, uint32_t imm);  */
+#define __arm_vcx2da_u64(coproc, acc, m, imm) \
+	__builtin_arm_vcx2adi(coproc, acc, m, imm)
+
+/* uint64_t
+   __arm_vcx3d_u64(int coproc, uint64_t n, uint64_t m, uint32_t imm);  */
+#define __arm_vcx3d_u64(coproc, n, m, imm) \
+	__builtin_arm_vcx3di(coproc, n, m, imm)
+
+/* uint64_t
+   __arm_vcx3da_u64(int coproc, uint64_t acc, uint64_t n, uint64_t m,
+		    uint32_t imm);  */
+#define __arm_vcx3da_u64(coproc, acc, n, m, imm) \
+	__builtin_arm_vcx3adi(coproc, acc, n, m, imm)
+
+#endif /* __ARM_FP || __ARM_FEATURE_MVE.  */
+#endif /* __ARM_FEATURE_CDE.  */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/gcc/config/arm/arm_cde_builtins.def b/gcc/config/arm/arm_cde_builtins.def
new file mode 100644
index 0000000000000000000000000000000000000000..a9fea937b9650f21a26d8183572b550e39b0fe7d
--- /dev/null
+++ b/gcc/config/arm/arm_cde_builtins.def
@@ -0,0 +1,33 @@ 
+/* Arm Custom Datapath Extension (CDE) builtin definitions.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Contributed by Arm Ltd.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#undef CDE_VAR2
+#define CDE_VAR2(T, N, A, B, IMM_MAX, ECF_FLAG) \
+  VAR1 (T, N, A, IMM_MAX, ECF_FLAG) \
+  VAR1 (T, N, B, IMM_MAX, ECF_FLAG)
+
+CDE_VAR2 (CX_IMM, vcx1, si, di, ARM_VCDE_CONST_1, ECF_CONST)
+CDE_VAR2 (CX_UNARY, vcx1a, si, di, ARM_VCDE_CONST_1, ECF_CONST)
+CDE_VAR2 (CX_UNARY, vcx2, si, di, ARM_VCDE_CONST_2, ECF_CONST)
+CDE_VAR2 (CX_BINARY, vcx2a, si, di, ARM_VCDE_CONST_2, ECF_CONST)
+CDE_VAR2 (CX_BINARY, vcx3, si, di, ARM_VCDE_CONST_3, ECF_CONST)
+CDE_VAR2 (CX_TERNARY, vcx3a, si, di, ARM_VCDE_CONST_3, ECF_CONST)
+
+#undef CDE_VAR2
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 5f4e3d1235813ab81c176505f9a98d702359f7ec..66ef724945bdf4c53e7363fb7c371ccc6208d387 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -596,7 +596,7 @@ 
 			 (V2SI "P") (V4SI  "q")
 			 (V2SF "P") (V4SF  "q")
 			 (DI   "P") (V2DI  "q")
-			 (V2HF "") (SF   "")
+			 (V2HF "") (SF   "") (SI "")
 			 (DF    "P") (HF   "")])
 
 ;; Output template to select the high VFP register of a mult-register value.
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 3a3941e22462c435d1bcff74b2db08d6f00ea61c..39ac7181323e0ace4c703710aa21c3aafc355955 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -182,6 +182,23 @@ 
   (and (match_operand 0 "const_int_operand")
        (match_test "satisfies_constraint_M (op)")))
 
+(define_predicate "const_int_coproc_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "IN_RANGE (UINTVAL (op), 0, ARM_CDE_CONST_COPROC)")
+       (match_test "arm_arch_cde_coproc_bits[UINTVAL (op)] & arm_arch_cde_coproc")))
+
+(define_predicate "const_int_vcde1_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_1)")))
+
+(define_predicate "const_int_vcde2_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_2)")))
+
+(define_predicate "const_int_vcde3_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "IN_RANGE (UINTVAL (op), 0, ARM_VCDE_CONST_3)")))
+
 ;; This doesn't have to do much because the constant is already checked
 ;; in the shift_operator predicate.
 (define_predicate "shift_amount_operand"
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index b36ae512a6ebcf231b46a24e127c62e22e71a34f..7ee24f63fcc1309ae43c8569eb9c072c3c9e6876 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -154,6 +154,8 @@ 
   UNSPEC_SMUADX		; Represent the SMUADX operation.
   UNSPEC_SSAT16		; Represent the SSAT16 operation.
   UNSPEC_USAT16		; Represent the USAT16 operation.
+  UNSPEC_VCDE		; Custom Datapath Extension instruction.
+  UNSPEC_VCDEA		; Custom Datapath Extension instruction.
 ])
 
 
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 99d6be4a94210d05a877a0cf38c02a73cc8cb1d6..fd4db6fadbcb5bce3d2f3ec091e214be43a70312 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -2133,3 +2133,74 @@ 
   DONE;
 }
 )
+
+;; CDE instructions using FPU/MVE S/D registers
+
+(define_insn "arm_vcx1<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SI 2 "const_int_vcde1_operand" "i")]
+	 UNSPEC_VCDE))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx1\\tp%c1, %<V_reg>0, #%c2"
+  [(set_attr "type" "coproc")]
+)
+
+(define_insn "arm_vcx1a<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SIDI 2 "register_operand" "0")
+		      (match_operand:SI 3 "const_int_vcde1_operand" "i")]
+	 UNSPEC_VCDEA))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx1a\\tp%c1, %<V_reg>0, #%c3"
+  [(set_attr "type" "coproc")]
+)
+
+(define_insn "arm_vcx2<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SIDI 2 "register_operand" "t")
+		      (match_operand:SI 3 "const_int_vcde2_operand" "i")]
+	 UNSPEC_VCDE))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx2\\tp%c1, %<V_reg>0, %<V_reg>2, #%c3"
+  [(set_attr "type" "coproc")]
+)
+
+(define_insn "arm_vcx2a<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SIDI 2 "register_operand" "0")
+		      (match_operand:SIDI 3 "register_operand" "t")
+		      (match_operand:SI 4 "const_int_vcde2_operand" "i")]
+	 UNSPEC_VCDEA))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx2a\\tp%c1, %<V_reg>0, %<V_reg>3, #%c4"
+  [(set_attr "type" "coproc")]
+)
+
+(define_insn "arm_vcx3<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SIDI 2 "register_operand" "t")
+		      (match_operand:SIDI 3 "register_operand" "t")
+		      (match_operand:SI 4 "const_int_vcde3_operand" "i")]
+	 UNSPEC_VCDE))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx3\\tp%c1, %<V_reg>0, %<V_reg>2, %<V_reg>3, #%c4"
+  [(set_attr "type" "coproc")]
+)
+
+(define_insn "arm_vcx3a<mode>"
+  [(set (match_operand:SIDI 0 "register_operand" "=t")
+	(unspec:SIDI [(match_operand:SI 1 "const_int_coproc_operand" "i")
+		      (match_operand:SIDI 2 "register_operand" "0")
+		      (match_operand:SIDI 3 "register_operand" "t")
+		      (match_operand:SIDI 4 "register_operand" "t")
+		      (match_operand:SI 5 "const_int_vcde3_operand" "i")]
+	 UNSPEC_VCDEA))]
+  "TARGET_CDE && (TARGET_ARM_FP || TARGET_HAVE_MVE)"
+  "vcx3a\\tp%c1, %<V_reg>0, %<V_reg>3, %<V_reg>4, #%c5"
+  [(set_attr "type" "coproc")]
+)
diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..3104db4ae608365667f4b617c5a4d58c90f5f5aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1.c
@@ -0,0 +1,94 @@ 
+/* Test the CDE ACLE intrinsic.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8m_main_cde_fp_ok } */
+/* { dg-options "-save-temps -O2" } */
+/* { dg-add-options arm_v8m_main_cde_fp } */
+
+#include "arm_cde.h"
+
+#define TEST0(T, N, C, I) \
+T test_arm_##N##_##C##_##I () { \
+  return __arm_##N (C, I); \
+}
+
+#define TEST1(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, I); \
+}
+
+#define TEST2(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, a, I); \
+}
+
+#define TEST3(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, a, a, I); \
+}
+
+#define TEST_ALL(C) \
+TEST0 (uint32_t, vcx1_u32,	C, 0) \
+TEST1 (uint32_t, vcx1a_u32,	C, 0) \
+TEST1 (uint32_t, vcx2_u32,	C, 0) \
+TEST2 (uint32_t, vcx2a_u32,	C, 0) \
+TEST2 (uint32_t, vcx3_u32,	C, 0) \
+TEST3 (uint32_t, vcx3a_u32,	C, 0) \
+TEST0 (uint64_t, vcx1d_u64,	C, 0) \
+TEST1 (uint64_t, vcx1da_u64,	C, 0) \
+TEST1 (uint64_t, vcx2d_u64,	C, 0) \
+TEST2 (uint64_t, vcx2da_u64,	C, 0) \
+TEST2 (uint64_t, vcx3d_u64,	C, 0) \
+TEST3 (uint64_t, vcx3da_u64,	C, 0) \
+TEST0 (uint32_t, vcx1_u32,	C, 2047) \
+TEST1 (uint32_t, vcx1a_u32,	C, 2047) \
+TEST1 (uint32_t, vcx2_u32,	C, 63) \
+TEST2 (uint32_t, vcx2a_u32,	C, 63) \
+TEST2 (uint32_t, vcx3_u32,	C, 7) \
+TEST3 (uint32_t, vcx3a_u32,	C, 7) \
+TEST0 (uint64_t, vcx1d_u64,	C, 2047) \
+TEST1 (uint64_t, vcx1da_u64,	C, 2047) \
+TEST1 (uint64_t, vcx2d_u64,	C, 63) \
+TEST2 (uint64_t, vcx2da_u64,	C, 63) \
+TEST2 (uint64_t, vcx3d_u64,	C, 7) \
+TEST3 (uint64_t, vcx3da_u64,	C, 7)
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp0+fp")
+TEST_ALL (0)
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp1+fp")
+TEST_ALL (1)
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp2+cdecp3+cdecp4+cdecp5+cdecp6+cdecp7+fp")
+TEST_ALL (2)
+TEST_ALL (3)
+TEST_ALL (4)
+TEST_ALL (5)
+TEST_ALL (6)
+TEST_ALL (7)
+#pragma GCC pop_options
+
+/* { dg-final { scan-assembler-times {\tvcx1\tp0, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp1, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp2, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp3, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp4, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp5, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp6, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp7, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp[0-7], s[0-9]+, #2047} 8 } } */
+/* { dg-final { scan-assembler-times {\tvcx1a\tp[0-7], s[0-9]+, #[0,2047]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx2\tp[0-7], s[0-9]+, s[0-9]+, #[0,63]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx2a\tp[0-7], s[0-9]+, s[0-9]+, #[0,63]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx3\tp[0-7], s[0-9]+, s[0-9]+, s[0-9]+, #[0,7]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx3a\tp[0-7], s[0-9]+, s[0-9]+, s[0-9]+, #[0,7]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp[0-7], d[0-9]+, #[0,2047]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx1a\tp[0-7], d[0-9]+, #[0,2047]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx2\tp[0-7], d[0-9]+, d[0-9]+, #[0,63]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx2a\tp[0-7], d[0-9]+, d[0-9]+, #[0,63]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx3\tp[0-7], d[0-9]+, d[0-9]+, d[0-9]+, #[0,7]} 16 } } */
+/* { dg-final { scan-assembler-times {\tvcx3a\tp[0-7], d[0-9]+, d[0-9]+, d[0-9]+, #[0,7]} 16 } } */
diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c
new file mode 100644
index 0000000000000000000000000000000000000000..023fab4ef9bf46dbf630d4698c2a0570bd2e4d14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c
@@ -0,0 +1,127 @@ 
+/* Test the CDE ACLE intrinsic.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8m_main_cde_fp_ok } */
+/* { dg-add-options arm_v8m_main_cde_fp } */
+
+#include "arm_cde.h"
+
+uint64_t test_coproc_range (uint32_t a, uint64_t b)
+{
+  uint64_t res = 0;
+  res += __arm_vcx1_u32 (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx1a_u32 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx2_u32 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx2a_u32 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3_u32 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3a_u32 (8, a, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx1d_u64 (8, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx1da_u64 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx2d_u64 (8, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx2da_u64 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3d_u64 (8, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3da_u64 (8, a, a, a, 0); /* { dg-error {coproc must be a constant immediate in range \[0-7\]} } */
+  return res;
+}
+
+uint64_t test_imm_range (uint32_t a, uint64_t b)
+{
+  uint64_t res = 0;
+  res += __arm_vcx1_u32 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */
+  res += __arm_vcx1a_u32 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */
+  res += __arm_vcx2_u32 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */
+  res += __arm_vcx2a_u32 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */
+  res += __arm_vcx3_u32 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3a_u32 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx1d_u64 (0, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */
+  res += __arm_vcx1da_u64 (0, a, 2048); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-2047\]} } */
+  res += __arm_vcx2d_u64 (0, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */
+  res += __arm_vcx2da_u64 (0, a, a, 64); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-63\]} } */
+  res += __arm_vcx3d_u64 (0, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */
+  res += __arm_vcx3da_u64 (0, a, a, a, 8); /* { dg-error {argument [2-5] must be a constant immediate in range \[0-7\]} } */
+  return res;
+}
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp1+fp")
+uint64_t test_coproc_match_1 (uint32_t a, uint64_t b)
+{
+  uint64_t res = 0;
+  res += __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx1a_u32 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx2_u32 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx2a_u32 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx3_u32 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx3a_u32 (0, a, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx1d_u64 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx1da_u64 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx2d_u64 (0, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx2da_u64 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx3d_u64 (0, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  res += __arm_vcx3da_u64 (0, a, a, a, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+  return res;
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp2+fp")
+uint32_t test_coproc_match_2 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp3+fp")
+uint32_t test_coproc_match_3 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp4+fp")
+uint32_t test_coproc_match_4 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp5+fp")
+uint32_t test_coproc_match_5 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp6+fp")
+uint32_t test_coproc_match_6 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp7+fp")
+uint32_t test_coproc_match_7 ()
+{
+  return __arm_vcx1_u32 (0, 0); /* { dg-error {coprocessor 0 is not enabled with \+cdecp0} } */
+}
+#pragma GCC pop_options
+
+#pragma GCC push_options
+#pragma GCC target ("arch=armv8-m.main+cdecp0+fp")
+uint32_t test_coproc_match_0 ()
+{
+  uint64_t res = 0;
+  res += __arm_vcx1_u32 (1, 0); /* { dg-error {coprocessor 1 is not enabled with \+cdecp1} } */
+  res += __arm_vcx1_u32 (2, 0); /* { dg-error {coprocessor 2 is not enabled with \+cdecp2} } */
+  res += __arm_vcx1_u32 (3, 0); /* { dg-error {coprocessor 3 is not enabled with \+cdecp3} } */
+  res += __arm_vcx1_u32 (4, 0); /* { dg-error {coprocessor 4 is not enabled with \+cdecp4} } */
+  res += __arm_vcx1_u32 (5, 0); /* { dg-error {coprocessor 5 is not enabled with \+cdecp5} } */
+  res += __arm_vcx1_u32 (6, 0); /* { dg-error {coprocessor 6 is not enabled with \+cdecp6} } */
+  res += __arm_vcx1_u32 (7, 0); /* { dg-error {coprocessor 7 is not enabled with \+cdecp7} } */
+  return res;
+}
+#pragma GCC pop_options
diff --git a/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c
new file mode 100644
index 0000000000000000000000000000000000000000..5140c3f521a628c4ccc4ca670876a0b0468efa37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c
@@ -0,0 +1,56 @@ 
+/* Test the CDE ACLE intrinsic.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_main_cde_mve_ok } */
+/* { dg-options "-save-temps -O2" } */
+/* { dg-add-options arm_v8_1m_main_cde_mve } */
+
+#include "arm_cde.h"
+
+#define TEST0(T, N, C, I) \
+T test_arm_##N##_##C##_##I () { \
+  return __arm_##N (C, I); \
+}
+
+#define TEST1(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, I); \
+}
+
+#define TEST2(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, a, I); \
+}
+
+#define TEST3(T, N, C, I) \
+T test_arm_##N##_##C##_##I (T a) { \
+  return __arm_##N (C, a, a, a, I); \
+}
+
+#define TEST_ALL(C) \
+TEST0 (uint32_t, vcx1_u32,	C, 0) \
+TEST1 (uint32_t, vcx1a_u32,	C, 0) \
+TEST1 (uint32_t, vcx2_u32,	C, 0) \
+TEST2 (uint32_t, vcx2a_u32,	C, 0) \
+TEST2 (uint32_t, vcx3_u32,	C, 0) \
+TEST3 (uint32_t, vcx3a_u32,	C, 0) \
+TEST0 (uint64_t, vcx1d_u64,	C, 0) \
+TEST1 (uint64_t, vcx1da_u64,	C, 0) \
+TEST1 (uint64_t, vcx2d_u64,	C, 0) \
+TEST2 (uint64_t, vcx2da_u64,	C, 0) \
+TEST2 (uint64_t, vcx3d_u64,	C, 0) \
+TEST3 (uint64_t, vcx3da_u64,	C, 0)
+
+TEST_ALL (0)
+
+/* { dg-final { scan-assembler-times {\tvcx1\tp0, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1a\tp0, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx2\tp0, s[0-9]+, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx2a\tp0, s[0-9]+, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx3\tp0, s[0-9]+, s[0-9]+, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx3a\tp0, s[0-9]+, s[0-9]+, s[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1\tp0, d[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx1a\tp0, d[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx2\tp0, d[0-9]+, d[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx2a\tp0, d[0-9]+, d[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx3\tp0, d[0-9]+, d[0-9]+, d[0-9]+, #0} 1 } } */
+/* { dg-final { scan-assembler-times {\tvcx3a\tp0, d[0-9]+, d[0-9]+, d[0-9]+, #0} 1 } } */