Commit 07b9bfd0 by Dennis Zhang

arm: CDE intrinsics using FPU/MVE S/D registers

This patch 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 also enables DImode for VFP
to support CDE with FPU.

gcc/ChangeLog:
2020-04-08  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-08  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.
parent 12f55e03
2020-04-08 Dennis Zhang <dennis.zhang@arm.com> 2020-04-08 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.
2020-04-08 Dennis Zhang <dennis.zhang@arm.com>
* config.gcc: Add arm_cde.h. * config.gcc: Add arm_cde.h.
* config/arm/arm-c.c (arm_cpu_builtins): Define or undefine * config/arm/arm-c.c (arm_cpu_builtins): Define or undefine
......
...@@ -305,6 +305,35 @@ arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS] ...@@ -305,6 +305,35 @@ arm_mrrc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
#define MRRC_QUALIFIERS \ #define MRRC_QUALIFIERS \
(arm_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, /* The first argument (return type) of a store should be void type,
which we represent with qualifier_void. Their first operand will be which we represent with qualifier_void. Their first operand will be
a DImode pointer to the location to store to, so we must use a DImode pointer to the location to store to, so we must use
...@@ -928,7 +957,23 @@ static arm_builtin_datum acle_builtin_data[] = ...@@ -928,7 +957,23 @@ static arm_builtin_datum acle_builtin_data[] =
}; };
#undef VAR1 #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) \ #define VAR1(T, N, X) \
ARM_BUILTIN_NEON_##N##X, ARM_BUILTIN_NEON_##N##X,
...@@ -1224,6 +1269,14 @@ enum arm_builtins ...@@ -1224,6 +1269,14 @@ enum arm_builtins
#include "arm_acle_builtins.def" #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, ARM_BUILTIN_MVE_BASE,
#undef VAR1 #undef VAR1
...@@ -1246,6 +1299,12 @@ enum arm_builtins ...@@ -1246,6 +1299,12 @@ enum arm_builtins
#define ARM_BUILTIN_ACLE_PATTERN_START \ #define ARM_BUILTIN_ACLE_PATTERN_START \
(ARM_BUILTIN_ACLE_BASE + 1) (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 CF
#undef VAR1 #undef VAR1
#undef VAR2 #undef VAR2
...@@ -1774,6 +1833,15 @@ arm_init_acle_builtins (void) ...@@ -1774,6 +1833,15 @@ arm_init_acle_builtins (void)
arm_builtin_datum *d = &acle_builtin_data[i]; arm_builtin_datum *d = &acle_builtin_data[i];
arm_init_builtin (fcode, d, "__builtin_arm"); 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. */ /* Set up all the MVE builtins mentioned in arm_mve_builtins.def file. */
...@@ -2966,8 +3034,29 @@ constant_arg: ...@@ -2966,8 +3034,29 @@ constant_arg:
if (!(*insn_data[icode].operand[opno].predicate) if (!(*insn_data[icode].operand[opno].predicate)
(op[argc], mode[argc])) (op[argc], mode[argc]))
{ {
error ("%Kargument %d must be a constant immediate", if (IN_RANGE (fcode, ARM_BUILTIN_CDE_PATTERN_START,
exp, argc + 1); 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 /* We have failed to expand the pattern, and are safely
in to invalid code. But the mid-end will still try to in to invalid code. But the mid-end will still try to
build an assignment for this node while it expands, build an assignment for this node while it expands,
...@@ -3192,8 +3281,12 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target) ...@@ -3192,8 +3281,12 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target)
/* Don't generate any RTL. */ /* Don't generate any RTL. */
return const0_rtx; return const0_rtx;
} }
gcc_assert (fcode != ARM_BUILTIN_CDE_BASE);
arm_builtin_datum *d 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); return arm_expand_builtin_1 (fcode, exp, target, d);
} }
......
...@@ -25013,7 +25013,7 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode) ...@@ -25013,7 +25013,7 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (TARGET_VFP_BASE && IS_VFP_REGNUM (regno)) if (TARGET_VFP_BASE && IS_VFP_REGNUM (regno))
{ {
if (mode == DFmode) if (mode == DFmode || mode == DImode)
return VFP_REGNO_OK_FOR_DOUBLE (regno); return VFP_REGNO_OK_FOR_DOUBLE (regno);
if (mode == HFmode || mode == BFmode || mode == HImode if (mode == HFmode || mode == BFmode || mode == HImode
......
...@@ -575,6 +575,10 @@ extern int arm_arch_bf16; ...@@ -575,6 +575,10 @@ extern int arm_arch_bf16;
extern int arm_arch_cde; extern int arm_arch_cde;
extern int arm_arch_cde_coproc; extern int arm_arch_cde_coproc;
extern const int arm_arch_cde_coproc_bits[]; 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 #ifndef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_APCS_FRAME) #define TARGET_DEFAULT (MASK_APCS_FRAME)
......
...@@ -33,6 +33,77 @@ extern "C" { ...@@ -33,6 +33,77 @@ extern "C" {
#include <stdint.h> #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 #ifdef __cplusplus
} }
#endif #endif
......
/* 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
...@@ -632,7 +632,7 @@ ...@@ -632,7 +632,7 @@
(V2SI "P") (V4SI "q") (V2SI "P") (V4SI "q")
(V2SF "P") (V4SF "q") (V2SF "P") (V4SF "q")
(DI "P") (V2DI "q") (DI "P") (V2DI "q")
(V2HF "") (SF "") (V2HF "") (SF "") (SI "")
(DF "P") (HF "")]) (DF "P") (HF "")])
;; Output template to select the high VFP register of a mult-register value. ;; Output template to select the high VFP register of a mult-register value.
......
...@@ -226,6 +226,23 @@ ...@@ -226,6 +226,23 @@
(and (match_operand 0 "const_int_operand") (and (match_operand 0 "const_int_operand")
(match_test "satisfies_constraint_M (op)"))) (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 ;; This doesn't have to do much because the constant is already checked
;; in the shift_operator predicate. ;; in the shift_operator predicate.
(define_predicate "shift_amount_operand" (define_predicate "shift_amount_operand"
......
...@@ -154,6 +154,8 @@ ...@@ -154,6 +154,8 @@
UNSPEC_SMUADX ; Represent the SMUADX operation. UNSPEC_SMUADX ; Represent the SMUADX operation.
UNSPEC_SSAT16 ; Represent the SSAT16 operation. UNSPEC_SSAT16 ; Represent the SSAT16 operation.
UNSPEC_USAT16 ; Represent the USAT16 operation. UNSPEC_USAT16 ; Represent the USAT16 operation.
UNSPEC_VCDE ; Custom Datapath Extension instruction.
UNSPEC_VCDEA ; Custom Datapath Extension instruction.
]) ])
......
...@@ -2165,3 +2165,74 @@ ...@@ -2165,3 +2165,74 @@
DONE; 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")]
)
2020-04-08 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.
2020-04-08 Patrick Palka <ppalka@redhat.com> 2020-04-08 Patrick Palka <ppalka@redhat.com>
Core issues 1001 and 1322 Core issues 1001 and 1322
......
/* 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 } } */
/* 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
/* 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 } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment