From 07b9bfd02b88cad2f6b3f50ad610dd75cb989ed3 Mon Sep 17 00:00:00 2001 From: Dennis Zhang Date: Wed, 8 Apr 2020 15:33:40 +0100 Subject: [PATCH] arm: CDE intrinsics using FPU/MVE S/D registers This patch enables the ACLE intrinsics calling VCX1, VCX2, and VCX3 instructions who work with FPU/MVE 32-bit/64-bit registers. This patch also enables DImode for VFP to support CDE with FPU. gcc/ChangeLog: 2020-04-08 Dennis Zhang Matthew Malcomson * 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): New entry. (arm_vcx1a, arm_vcx2, arm_vcx2a): Likewise. (arm_vcx3, arm_vcx3a): Likewise. gcc/testsuite/ChangeLog: 2020-04-08 Dennis Zhang * 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. --- gcc/ChangeLog | 30 +++++ gcc/config/arm/arm-builtins.c | 99 +++++++++++++- gcc/config/arm/arm.c | 2 +- gcc/config/arm/arm.h | 4 + gcc/config/arm/arm_cde.h | 71 ++++++++++ gcc/config/arm/arm_cde_builtins.def | 33 +++++ gcc/config/arm/iterators.md | 2 +- gcc/config/arm/predicates.md | 17 +++ gcc/config/arm/unspecs.md | 2 + gcc/config/arm/vfp.md | 71 ++++++++++ gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.target/arm/acle/cde_v_1.c | 94 +++++++++++++ .../gcc.target/arm/acle/cde_v_1_err.c | 127 ++++++++++++++++++ .../gcc.target/arm/acle/cde_v_1_mve.c | 56 ++++++++ 14 files changed, 609 insertions(+), 5 deletions(-) create mode 100644 gcc/config/arm/arm_cde_builtins.def create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1_err.c create mode 100644 gcc/testsuite/gcc.target/arm/acle/cde_v_1_mve.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff5c1c5e2a5..ffd4679e4ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2020-04-08 Dennis Zhang + Matthew Malcomson + + * 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): New entry. + (arm_vcx1a, arm_vcx2, arm_vcx2a): Likewise. + (arm_vcx3, arm_vcx3a): Likewise. + 2020-04-08 Dennis Zhang * config.gcc: Add arm_cde.h. diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 832b9107424..a8bad7b1ae5 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 @@ -928,7 +957,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, @@ -1224,6 +1269,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_MVE_BASE, #undef VAR1 @@ -1246,6 +1299,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 @@ -1774,6 +1833,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 MVE builtins mentioned in arm_mve_builtins.def file. */ @@ -2966,8 +3034,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", 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, @@ -3192,8 +3281,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.c b/gcc/config/arm/arm.c index da0bfbc3550..4dada07c588 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -25013,7 +25013,7 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (TARGET_VFP_BASE && IS_VFP_REGNUM (regno)) { - if (mode == DFmode) + if (mode == DFmode || mode == DImode) return VFP_REGNO_OK_FOR_DOUBLE (regno); if (mode == HFmode || mode == BFmode || mode == HImode diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 343235d0cbc..ca36a74cd1f 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -575,6 +575,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 f975754632f..4c9f7ebeed4 100644 --- a/gcc/config/arm/arm_cde.h +++ b/gcc/config/arm/arm_cde.h @@ -33,6 +33,77 @@ extern "C" { #include +#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 00000000000..a9fea937b96 --- /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 + . */ + +#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 e6b66eef372..c94198772f2 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -632,7 +632,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 bb302ed5b42..59cf5b67f8a 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -226,6 +226,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 a7575871da7..1645c32dfb2 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 dfb1031431a..ef83b504ff6 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -2165,3 +2165,74 @@ DONE; } ) + +;; CDE instructions using FPU/MVE S/D registers + +(define_insn "arm_vcx1" + [(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, %0, #%c2" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx1a" + [(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, %0, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2" + [(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, %0, %2, #%c3" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx2a" + [(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, %0, %3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3" + [(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, %0, %2, %3, #%c4" + [(set_attr "type" "coproc")] +) + +(define_insn "arm_vcx3a" + [(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, %0, %3, %4, #%c5" + [(set_attr "type" "coproc")] +) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 40597ed3658..9b2d1f62721 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-04-08 Dennis Zhang + + * 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. + 2020-04-08 Patrick Palka Core issues 1001 and 1322 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 00000000000..3104db4ae60 --- /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 00000000000..023fab4ef9b --- /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 00000000000..5140c3f521a --- /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 } } */ -- 2.30.2