[PATCH][ARM][GCC][1/x]: MVE ACLE intrinsics framework patch.
Kyrill Tkachov
kyrylo.tkachov@foss.arm.com
Wed Dec 18 17:18:00 GMT 2019
On 11/14/19 7:12 PM, Srinath Parvathaneni wrote:
> Hello,
>
> This patch creates the required framework for MVE ACLE intrinsics.
>
> The following changes are done in this patch to support MVE ACLE
> intrinsics.
>
> Header file arm_mve.h is added to source code, which contains the
> definitions of MVE ACLE intrinsics
> and different data types used in MVE. Machine description file mve.md
> is also added which contains the
> RTL patterns defined for MVE.
>
> A new reigster "p0" is added which is used in by MVE predicated
> patterns. A new register class "VPR_REG"
> is added and its contents are defined in REG_CLASS_CONTENTS.
>
> The vec-common.md file is modified to support the standard move
> patterns. The prefix of neon functions
> which are also used by MVE is changed from "neon_" to "simd_".
> eg: neon_immediate_valid_for_move changed to
> simd_immediate_valid_for_move.
>
> In the patch standard patterns mve_move, mve_store and move_load for
> MVE are added and neon.md and vfp.md
> files are modified to support this common patterns.
>
> Please refer to Arm reference manual [1] for more details.
>
> [1]
> https://static.docs.arm.com/ddi0553/bh/DDI0553B_h_armv8m_arm.pdf?_ga=2.102521798.659307368.1572453718-1501600630.1548848914
>
> Regression tested on arm-none-eabi and found no regressions.
>
> Ok for trunk?
Ok.
Thanks,
Kyrill
>
> Thanks,
> Srinath
>
> gcc/ChangeLog:
>
> 2019-11-11Â Andre Vieira <andre.simoesdiasvieira@arm.com>
>            Mihail Ionescu <mihail.ionescu@arm.com>
> Â Â Â Â Â Â Â Â Â Â Â Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Â Â Â Â Â Â Â * config.gcc (arm_mve.h): Add header file.
> Â Â Â Â Â Â Â * config/arm/aout.h (p0): Add new register name.
> Â Â Â Â Â Â Â * config/arm-builtins.c (ARM_BUILTIN_SIMD_LANE_CHECK): Define.
> Â Â Â Â Â Â Â (ARM_BUILTIN_NEON_LANE_CHECK): Remove.
> Â Â Â Â Â Â Â (arm_init_simd_builtin_types): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_init_neon_builtins): Move a check to arm_init_builtins
> function.
> Â Â Â Â Â Â Â (arm_init_builtins): Move a check from arm_init_neon_builtins
> function.
> Â Â Â Â Â Â Â (mve_dereference_pointer): Add new function.
> Â Â Â Â Â Â Â (arm_expand_builtin_args): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_expand_neon_builtin): Move a check to arm_expand_builtin
> function.
> Â Â Â Â Â Â Â (arm_expand_builtin): Move a check from
> arm_expand_neon_builtin function.
> Â Â Â Â Â Â Â * config/arm/arm-c.c (arm_cpu_builtins): Define macros for MVE.
> Â Â Â Â Â Â Â * config/arm/arm-modes.def (INT_MODE): Add three new integer
> modes.
> Â Â Â Â Â Â Â * config/arm/arm-protos.h (neon_immediate_valid_for_move):
> Rename function.
> Â Â Â Â Â Â Â (simd_immediate_valid_for_move): Rename
> neon_immediate_valid_for_move function.
> Â Â Â Â Â Â Â * config/arm/arm.c
> (arm_options_perform_arch_sanity_checks):Enable mve isa bit.
> Â Â Â Â Â Â Â (use_return_insn): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (aapcs_vfp_allocate): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (aapcs_vfp_allocate_return_reg): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (thumb2_legitimate_address_p): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_rtx_costs_internal): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (neon_valid_immediate): Rename to simd_valid_immediate.
> Â Â Â Â Â Â Â (simd_valid_immediate): Rename from neon_valid_immediate.
> Â Â Â Â Â Â Â (neon_immediate_valid_for_move): Rename to
> simd_immediate_valid_for_move.
> Â Â Â Â Â Â Â (simd_immediate_valid_for_move): Rename from
> neon_immediate_valid_for_move.
> Â Â Â Â Â Â Â (neon_immediate_valid_for_logic): Modify call to
> neon_valid_immediate function.
> Â Â Â Â Â Â Â (neon_make_constant): Modify call to neon_valid_immediate
> function.
> Â Â Â Â Â Â Â (neon_vector_mem_operand): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (output_move_neon): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_compute_frame_layout): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_save_coproc_regs): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_print_operand): Add case 'E' to print memory operands.
> Â Â Â Â Â Â Â (arm_print_operand_address): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_hard_regno_mode_ok): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_modes_tieable_p): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_regno_class): Add VPR_REGNUM check.
> Â Â Â Â Â Â Â (arm_expand_epilogue_apcs_frame): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_expand_epilogue): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_vector_mode_supported_p): Add TARGET_HAVE_MVE check for
> MVE vector modes.
> Â Â Â Â Â Â Â (arm_array_mode_supported_p): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (arm_conditional_register_usage): For TARGET_HAVE_MVE enable
> VPR register.
> Â Â Â Â Â Â Â * config/arm/arm.h (IS_VPR_REGNUM): Macro to check for VPR
> register.
> Â Â Â Â Â Â Â (FIRST_PSEUDO_REGISTER): Modify.
> Â Â Â Â Â Â Â (VALID_MVE_MODE): Define.
> Â Â Â Â Â Â Â (VALID_MVE_SI_MODE): Define.
> Â Â Â Â Â Â Â (VALID_MVE_SF_MODE): Define.
> Â Â Â Â Â Â Â (VALID_MVE_STRUCT_MODE): Define.
> Â Â Â Â Â Â Â (REG_ALLOC_ORDER): Add VPR_REGNUM entry.
> Â Â Â Â Â Â Â (enum reg_class): Add VPR_REG entry.
> Â Â Â Â Â Â Â (REG_CLASS_NAMES): Add VPR_REG entry.
> Â Â Â Â Â Â Â * config/arm/arm.md (VPR_REGNUM): Define.
> Â Â Â Â Â Â Â (arm_movsf_soft_insn): Add TARGET_HAVE_MVE check to not allow MVE.
> Â Â Â Â Â Â Â (vfp_pop_multiple_with_writeback): Add TARGET_HAVE_MVE check
> to allow writeback.
> Â Â Â Â Â Â Â (include "mve.md"): Include mve.md file.
> Â Â Â Â Â Â Â * config/arm/arm_mve.h: New file.
> Â Â Â Â Â Â Â * config/arm/constraints.md (Up): Define.
> Â Â Â Â Â Â Â * config/arm/iterators.md (VNIM1): Define.
> Â Â Â Â Â Â Â (VNINOTM1): Define.
> Â Â Â Â Â Â Â (VSTRUCT): Modify.
> Â Â Â Â Â Â Â * config/arm/mve.md: New file.
> Â Â Â Â Â Â Â * config/arm/neon.md:
> Â Â Â Â Â Â Â (mov<mode>): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (movv4hf): Define.
> Â Â Â Â Â Â Â (neon_mov<mode>): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (define_split): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (vec_init<mode><V_elem_l>): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â * config/arm/predicates.md (vpr_register_operand): Define.
> Â Â Â Â Â Â Â * config/arm/t-arm: Add mve.md file.
> Â Â Â Â Â Â Â * config/arm/types.md: Add MVE instructions mve_move,
> mve_load, mve_store.
> Â Â Â Â Â Â Â * config/arm/vec-common.md (mov<mode>): Add TARGET_HAVE_MVE check.
> Â Â Â Â Â Â Â (mov<mode>): Modify iterator.
> Â Â Â Â Â Â Â (movv8hf): Define
>
> gcc/testsuite/ChangeLog:
>
> 2019-11-11Â Andre Vieira <andre.simoesdiasvieira@arm.com>
>            Mihail Ionescu <mihail.ionescu@arm.com>
> Â Â Â Â Â Â Â Â Â Â Â Srinath Parvathaneni <srinath.parvathaneni@arm.com>
>
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_float.c: New test.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_float1.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_float2.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_int.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_int1.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_int2.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_uint.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_uint1.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/intrinsics/mve_vector_uint2.c: Likewise.
> Â Â Â Â Â Â Â * gcc.target/arm/mve/mve.exp: New file.
>
>
> ###############    Attachment also inlined for ease of reply  Â
> ###############
>
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index
> 72f656408f11802c669c3de953bf3020020ca312..c4a7d984936c531d7dfcce347d56b5931913e68b
> 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -344,7 +344,7 @@ arc*-*-*)
> Â arm*-*-*)
> Â Â Â Â Â Â Â Â cpu_type=arm
> Â Â Â Â Â Â Â Â extra_objs="arm-builtins.o aarch-common.o"
> -Â Â Â Â Â Â extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h
> arm_cmse.h"
> +Â Â Â Â Â Â extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h
> arm_cmse.h arm_mve.h"
> Â Â Â Â Â Â Â Â target_type_format_char='%'
> Â Â Â Â Â Â Â Â c_target_objs="arm-c.o"
> Â Â Â Â Â Â Â Â cxx_target_objs="arm-c.o"
> diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
> index
> 72782758853a869bcb9a9d69f3fa0da979cd711f..28cde153f704748f35c84d072b59e9695a61e661
> 100644
> --- a/gcc/config/arm/aout.h
> +++ b/gcc/config/arm/aout.h
> @@ -53,7 +53,9 @@
>  /* The assembler's names for the registers. Note that the ?xx
> registers are
> Â Â Â there so that VFPv3/NEON registers D16-D31 have the same spacing
> as D0-D15
> Â Â Â (each of which is overlaid on two S registers), although there are no
> -  actual single-precision registers which correspond to D16-D31. */
> +Â Â actual single-precision registers which correspond to D16-D31.Â
> New register
> +  p0 is added which is used for MVE predicated cases. */
> +
> Â #ifndef REGISTER_NAMES
> Â #define REGISTER_NAMESÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â {Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> @@ -72,7 +74,7 @@
>   "wr8",  "wr9",  "wr10", "wr11",                          \
>   "wr12", "wr13", "wr14", "wr15",                          \
>   "wcgr0", "wcgr1", "wcgr2", "wcgr3",                         \
> -Â "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge"Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> +Â "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0"Â Â Â Â Â Â Â Â \
> Â }
> Â #endif
>
> diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
> index
> 650b22c7ad916d9abd587981e9ed5809755ee035..d4cb0ea3deb49b10266d1620c85e243ed34aee4d
> 100644
> --- a/gcc/config/arm/arm-builtins.c
> +++ b/gcc/config/arm/arm-builtins.c
> @@ -667,6 +667,7 @@ enum arm_builtins
> Â Â ARM_BUILTIN_SET_FPSCR,
>
> Â Â ARM_BUILTIN_CMSE_NONSECURE_CALLER,
> +Â ARM_BUILTIN_SIMD_LANE_CHECK,
>
> Â #undef CRYPTO1
> Â #undef CRYPTO2
> @@ -692,7 +693,6 @@ enum arm_builtins
> Â #include "arm_vfp_builtins.def"
>
> Â Â ARM_BUILTIN_NEON_BASE,
> -Â ARM_BUILTIN_NEON_LANE_CHECK = ARM_BUILTIN_NEON_BASE,
>
> Â #include "arm_neon_builtins.def"
>
> @@ -948,26 +948,35 @@ arm_init_simd_builtin_types (void)
> Â Â Â Â Â an entry in our mangling table, consequently, they get default
>      mangling. As a further gotcha, poly8_t and poly16_t are signed
>      types, poly64_t and poly128_t are unsigned types. */
> -Â arm_simd_polyQI_type_node
> -Â Â Â = build_distinct_type_copy (intQI_type_node);
> -Â (*lang_hooks.types.register_builtin_type) (arm_simd_polyQI_type_node,
> - "__builtin_neon_poly8");
> -Â arm_simd_polyHI_type_node
> -Â Â Â = build_distinct_type_copy (intHI_type_node);
> -Â (*lang_hooks.types.register_builtin_type) (arm_simd_polyHI_type_node,
> - "__builtin_neon_poly16");
> -Â arm_simd_polyDI_type_node
> -Â Â Â = build_distinct_type_copy (unsigned_intDI_type_node);
> -Â (*lang_hooks.types.register_builtin_type) (arm_simd_polyDI_type_node,
> - "__builtin_neon_poly64");
> -Â arm_simd_polyTI_type_node
> -Â Â Â = build_distinct_type_copy (unsigned_intTI_type_node);
> -Â (*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
> - "__builtin_neon_poly128");
> -Â /* Prevent front-ends from transforming poly vectors into string
> -    literals. */
> -Â TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
> -Â TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
> +Â if (!TARGET_HAVE_MVE)
> +Â Â Â {
> +Â Â Â Â Â arm_simd_polyQI_type_node
> +Â Â Â Â Â Â = build_distinct_type_copy (intQI_type_node);
> +Â Â Â Â Â (*lang_hooks.types.register_builtin_type)
> (arm_simd_polyQI_type_node,
> + "__builtin_neon_poly8");
> +Â Â Â Â Â arm_simd_polyHI_type_node
> +Â Â Â Â Â Â = build_distinct_type_copy (intHI_type_node);
> +Â Â Â Â Â (*lang_hooks.types.register_builtin_type)
> (arm_simd_polyHI_type_node,
> + "__builtin_neon_poly16");
> +Â Â Â Â Â arm_simd_polyDI_type_node
> +Â Â Â Â Â Â = build_distinct_type_copy (unsigned_intDI_type_node);
> +Â Â Â Â Â (*lang_hooks.types.register_builtin_type)
> (arm_simd_polyDI_type_node,
> + "__builtin_neon_poly64");
> +Â Â Â Â Â arm_simd_polyTI_type_node
> +Â Â Â Â Â Â = build_distinct_type_copy (unsigned_intTI_type_node);
> +Â Â Â Â Â (*lang_hooks.types.register_builtin_type)
> (arm_simd_polyTI_type_node,
> + "__builtin_neon_poly128");
> +     /* Init poly vector element types with scalar poly types. */
> +Â Â Â Â Â arm_simd_types[Poly8x8_t].eltype = arm_simd_polyQI_type_node;
> +Â Â Â Â Â arm_simd_types[Poly8x16_t].eltype = arm_simd_polyQI_type_node;
> +Â Â Â Â Â arm_simd_types[Poly16x4_t].eltype = arm_simd_polyHI_type_node;
> +Â Â Â Â Â arm_simd_types[Poly16x8_t].eltype = arm_simd_polyHI_type_node;
> +
> +Â Â Â Â Â /* Prevent front-ends from transforming poly vectors into string
> +       literals. */
> +Â Â Â Â Â TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
> +Â Â Â Â Â TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
> +Â Â Â }
>
>   /* Init all the element types built by the front-end. */
> Â Â arm_simd_types[Int8x8_t].eltype = intQI_type_node;
> @@ -985,11 +994,6 @@ arm_init_simd_builtin_types (void)
> Â Â arm_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
> Â Â arm_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
>
> - /* Init poly vector element types with scalar poly types. */
> -Â arm_simd_types[Poly8x8_t].eltype = arm_simd_polyQI_type_node;
> -Â arm_simd_types[Poly8x16_t].eltype = arm_simd_polyQI_type_node;
> -Â arm_simd_types[Poly16x4_t].eltype = arm_simd_polyHI_type_node;
> -Â arm_simd_types[Poly16x8_t].eltype = arm_simd_polyHI_type_node;
> Â Â /* Note: poly64x2_t is defined in arm_neon.h, to ensure it gets default
>      mangling. */
>
> @@ -1006,6 +1010,8 @@ arm_init_simd_builtin_types (void)
> Â Â Â Â Â Â tree eltype = arm_simd_types[i].eltype;
> Â Â Â Â Â Â machine_mode mode = arm_simd_types[i].mode;
>
> +Â Â Â Â Â if (eltype == NULL)
> +Â Â Â Â Â Â continue;
> Â Â Â Â Â Â if (arm_simd_types[i].itype == NULL)
> Â Â Â Â Â Â Â Â arm_simd_types[i].itype =
> Â Â Â Â Â Â Â Â Â Â build_distinct_type_copy
> @@ -1231,15 +1237,6 @@ arm_init_neon_builtins (void)
>      system. */
> Â Â arm_init_simd_builtin_scalar_types ();
>
> -Â tree lane_check_fpr = build_function_type_list (void_type_node,
> - intSI_type_node,
> - intSI_type_node,
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NULL);
> -Â arm_builtin_decls[ARM_BUILTIN_NEON_LANE_CHECK] =
> -Â Â Â Â Â add_builtin_function ("__builtin_arm_lane_check", lane_check_fpr,
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ARM_BUILTIN_NEON_LANE_CHECK, BUILT_IN_MD,
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NULL, NULL_TREE);
> -
> Â Â for (i = 0; i < ARRAY_SIZE (neon_builtin_data); i++, fcode++)
> Â Â Â Â {
> Â Â Â Â Â Â arm_builtin_datum *d = &neon_builtin_data[i];
> @@ -1956,6 +1953,15 @@ arm_init_builtins (void)
>
> Â Â if (TARGET_MAYBE_HARD_FLOAT)
> Â Â Â Â {
> +Â Â Â Â Â tree lane_check_fpr = build_function_type_list (void_type_node,
> + intSI_type_node,
> + intSI_type_node,
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NULL);
> +Â Â Â Â Â arm_builtin_decls[ARM_BUILTIN_SIMD_LANE_CHECK]
> +Â Â Â Â Â = add_builtin_function ("__builtin_arm_lane_check", lane_check_fpr,
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ARM_BUILTIN_SIMD_LANE_CHECK, BUILT_IN_MD,
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NULL, NULL_TREE);
> +
> Â Â Â Â Â Â arm_init_neon_builtins ();
> Â Â Â Â Â Â arm_init_vfp_builtins ();
> Â Â Â Â Â Â arm_init_crypto_builtins ();
> @@ -2201,6 +2207,47 @@ neon_dereference_pointer (tree exp, tree type,
> machine_mode mem_mode,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â build_int_cst (build_pointer_type (array_type),
> 0));
> Â }
>
> +/* EXP is a pointer argument to a vector scatter store intrinsics.
> +
> +Â Â Consider the following example:
> +Â Â Â Â Â Â VSTRW<v>.<dt> Qd, [Qm{, #+/-<imm>}]!
> +Â Â When <Qm> used as the base register for the target address,
> +Â Â this function is used to derive and return an expression for the
> +Â Â accessed memory.
> +
> +Â Â The intrinsic function operates on a block of registers that has mode
> +  REG_MODE. This block contains vectors of type TYPE_MODE. The
> function
> +  references the memory at EXP of type TYPE and in mode MEM_MODE. This
> +  mode may be BLKmode if no more suitable mode is available. */
> +
> +static tree
> +mve_dereference_pointer (tree exp, tree type, machine_mode reg_mode,
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â machine_mode vector_mode)
> +{
> +Â HOST_WIDE_INT reg_size, vector_size, nelems;
> +Â tree elem_type, upper_bound, array_type;
> +
> + /* Work out the size of each vector in bytes. */
> +Â vector_size = GET_MODE_SIZE (vector_mode);
> +
> + /* Work out the size of the register block in bytes. */
> +Â reg_size = GET_MODE_SIZE (reg_mode);
> +
> + /* Work out the type of each element. */
> +Â gcc_assert (POINTER_TYPE_P (type));
> +Â elem_type = TREE_TYPE (type);
> +
> +Â nelems = reg_size / vector_size;
> +
> + /* Create a type that describes the full access. */
> +Â upper_bound = build_int_cst (size_type_node, nelems - 1);
> +Â array_type = build_array_type (elem_type, build_index_type
> (upper_bound));
> +
> + /* Dereference EXP using that type. */
> +Â return fold_build2 (MEM_REF, array_type, exp,
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â build_int_cst (build_pointer_type (array_type), 0));
> +}
> +
>  /* Expand a builtin. */
> Â static rtx
> Â arm_expand_builtin_args (rtx target, machine_mode map_mode, int fcode,
> @@ -2239,10 +2286,17 @@ arm_expand_builtin_args (rtx target,
> machine_mode map_mode, int fcode,
> Â Â Â Â Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â machine_mode other_mode
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â = insn_data[icode].operand[1 - opno].mode;
> -Â Â Â Â Â Â Â Â Â Â Â Â Â arg[argc] = neon_dereference_pointer (arg[argc],
> +Â Â Â Â Â Â Â Â Â Â Â Â if (TARGET_HAVE_MVE && mode[argc] != other_mode)
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â arg[argc] = mve_dereference_pointer (arg[argc],
> TREE_VALUE (formals),
> - mode[argc], other_mode,
> - map_mode);
> + other_mode, map_mode);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â arg[argc] = neon_dereference_pointer (arg[argc],
> + TREE_VALUE (formals),
> + mode[argc], other_mode,
> + map_mode);
> Â Â Â Â Â Â Â Â Â Â Â Â }
>
> Â Â Â Â Â Â Â Â Â Â /* Use EXPAND_MEMORY for ARG_BUILTIN_MEMORY and
> @@ -2548,22 +2602,6 @@ arm_expand_neon_builtin (int fcode, tree exp,
> rtx target)
> Â Â Â Â Â Â return const0_rtx;
> Â Â Â Â }
>
> -Â if (fcode == ARM_BUILTIN_NEON_LANE_CHECK)
> -Â Â Â {
> -Â Â Â Â Â /* Builtin is only to check bounds of the lane passed to some
> intrinsics
> -Â Â Â Â Â Â Â that are implemented with gcc vector extensions in
> arm_neon.h. */
> -
> -Â Â Â Â Â tree nlanes = CALL_EXPR_ARG (exp, 0);
> -Â Â Â Â Â gcc_assert (TREE_CODE (nlanes) == INTEGER_CST);
> -Â Â Â Â Â rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 1));
> -Â Â Â Â Â if (CONST_INT_P (lane_idx))
> -Â Â Â Â Â Â neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp);
> -Â Â Â Â Â else
> -Â Â Â Â Â Â error ("%Klane index must be a constant immediate", exp);
> -     /* Don't generate any RTL. */
> -Â Â Â Â Â return const0_rtx;
> -Â Â Â }
> -
> Â Â arm_builtin_datum *d
> Â Â Â Â = &neon_builtin_data[fcode - ARM_BUILTIN_NEON_PATTERN_START];
>
> @@ -2625,6 +2663,22 @@ arm_expand_builtin (tree exp,
> Â Â int mask;
> Â Â int imm;
>
> +Â if (fcode == ARM_BUILTIN_SIMD_LANE_CHECK)
> +Â Â Â {
> +Â Â Â Â Â /* Builtin is only to check bounds of the lane passed to some
> intrinsics
> +Â Â Â Â Â Â Â that are implemented with gcc vector extensions in
> arm_neon.h. */
> +
> +Â Â Â Â Â tree nlanes = CALL_EXPR_ARG (exp, 0);
> +Â Â Â Â Â gcc_assert (TREE_CODE (nlanes) == INTEGER_CST);
> +Â Â Â Â Â rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 1));
> +Â Â Â Â Â if (CONST_INT_P (lane_idx))
> +Â Â Â Â Â Â neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp);
> +Â Â Â Â Â else
> +Â Â Â Â Â Â error ("%Klane index must be a constant immediate", exp);
> +     /* Don't generate any RTL. */
> +Â Â Â Â Â return const0_rtx;
> +Â Â Â }
> +
> Â Â if (fcode >= ARM_BUILTIN_ACLE_BASE)
> Â Â Â Â return arm_expand_acle_builtin (fcode, exp, target);
>
> diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
> index
> 34695fa0112e90e4bdf317da0b9fd1d3194bf0a2..0fe7d371c348818f25901c5d84be94589523c9a6
> 100644
> --- a/gcc/config/arm/arm-c.c
> +++ b/gcc/config/arm/arm-c.c
> @@ -79,6 +79,16 @@ arm_cpu_builtins (struct cpp_reader* pfile)
> Â Â def_or_undef_macro (pfile, "__ARM_FEATURE_COMPLEX", TARGET_COMPLEX);
> Â Â def_or_undef_macro (pfile, "__ARM_32BIT_STATE", TARGET_32BIT);
>
> +Â cpp_undef (pfile, "__ARM_FEATURE_MVE");
> +Â if (TARGET_HAVE_MVE && TARGET_HAVE_MVE_FLOAT)
> +Â Â Â {
> +Â Â Â Â Â builtin_define_with_int_value ("__ARM_FEATURE_MVE", 3);
> +Â Â Â }
> +Â else if (TARGET_HAVE_MVE)
> +Â Â Â {
> +Â Â Â Â Â builtin_define_with_int_value ("__ARM_FEATURE_MVE", 1);
> +Â Â Â }
> +
> Â Â cpp_undef (pfile, "__ARM_FEATURE_CMSE");
> Â Â if (arm_arch8 && !arm_arch_notm)
> Â Â Â Â {
> diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
> index
> 5b49049cc45c0bccfa9d67eac0940250fc5dd95a..d4612ae4553697989611d772f7bb0061a04b98b6
> 100644
> --- a/gcc/config/arm/arm-protos.h
> +++ b/gcc/config/arm/arm-protos.h
> @@ -85,7 +85,7 @@ extern bool ldm_stm_operation_p (rtx, bool,
> machine_mode mode,
> Â extern bool clear_operation_p (rtx, bool);
> Â extern int arm_const_double_rtx (rtx);
> Â extern int vfp3_const_double_rtx (rtx);
> -extern int neon_immediate_valid_for_move (rtx, machine_mode, rtx *,
> int *);
> +extern int simd_immediate_valid_for_move (rtx, machine_mode, rtx *,
> int *);
> Â extern int neon_immediate_valid_for_logic (rtx, machine_mode, int, rtx *,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int *);
> Â extern int neon_immediate_valid_for_shift (rtx, machine_mode, rtx *,
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index
> 8b07c423fb6b071642fccc48424fe244d97dcbc2..c755df420b52798773ee99f54faf6689d4a16215
> 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -751,7 +751,8 @@ extern int arm_arch_cmse;
> Â /*Â Â Â Â Â s0-s15Â Â Â Â Â Â Â Â Â VFP scratch (aka d0-d7).
> Â Â Â Â Â Â Â Â s16-s31Â Â Â Â Â Â SÂ VFP variable (aka d8-d15).
>         vfpcc          Not a real register. Represents the VFP
> condition
> -                      code flags. */
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â code flags.
> +      vpr            Used to represent MVE VPR predication. */
>
> Â /* The stack backtrace structure is as follows:
>   fp points to here: | save code pointer |     [fp]
> @@ -792,7 +793,7 @@ extern int arm_arch_cmse;
>   1,1,1,1,1,1,1,1,            \
>   1,1,1,1,                    \
>   /* Specials. */            \
> -Â 1,1,1,1,1,1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> +Â 1,1,1,1,1,1,1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â }
>
> Â /* 1 for registers not available across function calls.
> @@ -822,7 +823,7 @@ extern int arm_arch_cmse;
>   1,1,1,1,1,1,1,1,            \
>   1,1,1,1,                    \
>   /* Specials. */            \
> -Â 1,1,1,1,1,1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> +Â 1,1,1,1,1,1,1Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â }
>
> Â #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
> @@ -998,10 +999,10 @@ extern int arm_arch_cmse;
> Â Â Â && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
>
> Â /* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
> -  + 1 APSRQ + 1 APSRGE. */
> +  + 1 APSRQ + 1 APSRGE + 1 VPR. */
>  /* Intel Wireless MMX Technology registers add 16 + 4 more. */
>  /* VFP (VFP3) adds 32 (64) + 1 VFPCC. */
> -#define FIRST_PSEUDO_REGISTERÂ Â 106
> +#define FIRST_PSEUDO_REGISTERÂ Â 107
>
> Â #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
>
> @@ -1029,11 +1030,26 @@ extern int arm_arch_cmse;
> Â Â ((MODE) == V4SImode || (MODE) == V8HImode || (MODE) == V16QImode \
> Â Â Â || (MODE) == V8HFmode || (MODE) == V4SFmode || (MODE) == V2DImode)
>
> +#define VALID_MVE_MODE(MODE) \
> +Â ((MODE) == V2DImode ||(MODE) == V4SImode || (MODE) == V8HImode \
> +Â Â || (MODE) == V16QImode || (MODE) == V8HFmode || (MODE) == V4SFmode \
> +Â Â || (MODE) == V2DFmode)
> +
> +#define VALID_MVE_SI_MODE(MODE) \
> +Â ((MODE) == V2DImode ||(MODE) == V4SImode || (MODE) == V8HImode \
> +Â Â || (MODE) == V16QImode)
> +
> +#define VALID_MVE_SF_MODE(MODE) \
> +Â ((MODE) == V8HFmode || (MODE) == V4SFmode || (MODE) == V2DFmode)
> +
>  /* Structure modes valid for Neon registers. */
> Â #define VALID_NEON_STRUCT_MODE(MODE) \
> Â Â ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
> Â Â Â || (MODE) == CImode || (MODE) == XImode)
>
> +#define VALID_MVE_STRUCT_MODE(MODE) \
> +Â ((MODE) == TImode || (MODE) == OImode || (MODE) == XImode)
> +
> Â /* The register numbers in sequence, for passing to
> arm_gen_load_multiple. */
> Â extern int arm_regs_in_sequence[];
>
> @@ -1085,9 +1101,13 @@ extern int arm_regs_in_sequence[];
>   /* Registers not for general use. */               \
>   CC_REGNUM, VFPCC_REGNUM,                    \
>   FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,   \
> -Â SP_REGNUM, PC_REGNUM, APSRQ_REGNUM, APSRGE_REGNUMÂ Â Â \
> + SP_REGNUM, PC_REGNUM, APSRQ_REGNUM, APSRGE_REGNUM,  \
> +Â VPR_REGNUMÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
> Â }
>
> +#define IS_VPR_REGNUM(REGNUM) \
> +Â ((REGNUM) == VPR_REGNUM)
> +
>  /* Use different register alloc ordering for Thumb. */
> Â #define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
>
> @@ -1124,6 +1144,7 @@ enum reg_class
> Â Â VFPCC_REG,
> Â Â SFP_REG,
> Â Â AFP_REG,
> +Â VPR_REG,
> Â Â ALL_REGS,
> Â Â LIM_REG_CLASSES
> Â };
> @@ -1131,7 +1152,7 @@ enum reg_class
> Â #define N_REG_CLASSESÂ (int) LIM_REG_CLASSES
>
>  /* Give names of register classes as strings for dump file. */
> -#define REG_CLASS_NAMESÂ \
> +#define REG_CLASS_NAMES \
> Â {Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â \
>   "NO_REGS",          \
>   "LO_REGS",          \
> @@ -1151,6 +1172,7 @@ enum reg_class
>   "VFPCC_REG",        \
>   "SFP_REG",          \
>   "AFP_REG",          \
> + "VPR_REG",          \
> Â Â "ALL_REGS"Â Â Â Â Â Â Â Â Â Â \
> Â }
>
> @@ -1177,7 +1199,8 @@ enum reg_class
> Â Â { 0x00000000, 0x00000000, 0x00000000, 0x00000020 }, /* VFPCC_REG */Â \
> Â Â { 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */Â Â Â \
> Â Â { 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */Â Â Â \
> -Â { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F }Â /* ALL_REGS */Â Â \
> + { 0x00000000, 0x00000000, 0x00000000, 0x00000100 }, /* VPR_REG. */ \
> + { 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000010F } /* ALL_REGS. */ \
> Â }
>
> Â #define FP_SYSREGS \
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index
> 883c2a9179d7e6d69225f8d104228d15702ecef7..6faed76206b93c1a9dea048e2f693dc16ee58072
> 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -3759,7 +3759,8 @@ arm_options_perform_arch_sanity_checks (void)
> Â Â Â Â Â Â else if (TARGET_HARD_FLOAT_ABI)
> Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â arm_pcs_default = ARM_PCS_AAPCS_VFP;
> -Â Â Â Â Â Â Â Â if (!bitmap_bit_p (arm_active_target.isa, isa_bit_vfpv2))
> +Â Â Â Â Â Â Â Â if (!bitmap_bit_p (arm_active_target.isa, isa_bit_vfpv2)
> +Â Â Â Â Â Â Â Â Â Â Â Â && !bitmap_bit_p (arm_active_target.isa, isa_bit_mve))
> Â Â Â Â Â Â Â Â Â Â Â Â error ("%<-mfloat-abi=hard%>: selected processor lacks an
> FPU");
> Â Â Â Â Â Â Â Â }
> Â Â Â Â Â Â else
> @@ -4230,7 +4231,7 @@ use_return_insn (int iscond, rtx sibling)
>
> Â Â /* Can't be done if any of the VFP regs are pushed,
>      since this also requires an insn. */
> -Â if (TARGET_HARD_FLOAT)
> +Â if (TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â for (regno = FIRST_VFP_REGNUM; regno <= LAST_VFP_REGNUM; regno++)
>   ��   if (df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p
> (regno))
> Â Â Â Â Â Â Â Â return 0;
> @@ -6289,7 +6290,7 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum,
> machine_mode mode,
> Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â pcum->aapcs_vfp_reg_alloc = mask << regno;
> Â Â Â Â Â Â Â Â if (mode == BLKmode
> -Â Â Â Â Â Â Â Â Â Â || (mode == TImode && ! TARGET_NEON)
> +Â Â Â Â Â Â Â Â Â Â || (mode == TImode && ! (TARGET_NEON || TARGET_HAVE_MVE))
> Â Â Â Â Â Â Â Â Â Â Â Â || ! arm_hard_regno_mode_ok (FIRST_VFP_REGNUM + regno, mode))
> Â Â Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â Â Â int i;
> @@ -6297,7 +6298,7 @@ aapcs_vfp_allocate (CUMULATIVE_ARGS *pcum,
> machine_mode mode,
> Â Â Â Â Â Â Â Â Â Â Â Â int rshift = shift;
> Â Â Â Â Â Â Â Â Â Â Â Â machine_mode rmode = pcum->aapcs_vfp_rmode;
> Â Â Â Â Â Â Â Â Â Â Â Â rtx par;
> -Â Â Â Â Â Â Â Â Â Â if (!TARGET_NEON)
> +Â Â Â Â Â Â Â Â Â Â if (!(TARGET_NEON || TARGET_HAVE_MVE))
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* Avoid using unsupported vector modes. */
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (rmode == V2SImode)
> @@ -6343,7 +6344,7 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs
> pcs_variant ATTRIBUTE_UNUSED,
> Â Â if (mode == BLKmode
> Â Â Â Â Â Â || (GET_MODE_CLASS (mode) == MODE_INT
> Â Â Â Â Â Â Â Â Â Â && GET_MODE_SIZE (mode) >= GET_MODE_SIZE (TImode)
> -Â Â Â Â Â Â Â Â && !TARGET_NEON))
> +Â Â Â Â Â Â Â Â && !(TARGET_NEON || TARGET_HAVE_MVE)))
> Â Â Â Â {
> Â Â Â Â Â Â int count;
> Â Â Â Â Â Â machine_mode ag_mode;
> @@ -6354,7 +6355,7 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs
> pcs_variant ATTRIBUTE_UNUSED,
> Â Â Â Â Â Â aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &ag_mode, &count);
>
> -Â Â Â Â Â if (!TARGET_NEON)
> +Â Â Â Â Â if (!(TARGET_NEON || TARGET_HAVE_MVE))
> Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â if (ag_mode == V2SImode)
> Â Â Â Â Â Â Â Â Â Â Â Â ag_mode = DImode;
> @@ -8253,7 +8254,9 @@ thumb2_legitimate_address_p (machine_mode mode,
> rtx x, int strict_p)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â && CONST_INT_P (XEXP (XEXP (x, 0), 1)))))
> Â Â Â Â return 1;
>
> -Â else if (mode == TImode || (TARGET_NEON && VALID_NEON_STRUCT_MODE
> (mode)))
> +Â else if (mode == TImode
> +Â Â Â Â Â Â Â Â Â || (TARGET_NEON && VALID_NEON_STRUCT_MODE (mode))
> +Â Â Â Â Â Â Â Â Â || (TARGET_HAVE_MVE && VALID_MVE_STRUCT_MODE (mode)))
> Â Â Â Â return 0;
>
> Â Â else if (code == PLUS)
> @@ -9800,7 +9803,7 @@ arm_rtx_costs_internal (rtx x, enum rtx_code
> code, enum rtx_code outer_code,
> Â Â Â Â Â Â Â Â Â Â /* Assume that most copies can be done with a single insn,
> Â Â Â Â Â Â Â Â Â Â Â Â Â unless we don't have HW FP, in which case everything
> Â Â Â Â Â Â Â Â Â Â Â Â Â larger than word mode will require two insns. */
> -Â Â Â Â Â Â Â Â *cost = COSTS_N_INSNS (((!TARGET_HARD_FLOAT
> +Â Â Â Â Â Â Â Â *cost = COSTS_N_INSNS (((!(TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â && GET_MODE_SIZE (mode) > 4)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â || mode == DImode)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ? 2 : 1);
> @@ -11281,10 +11284,10 @@ arm_rtx_costs_internal (rtx x, enum rtx_code
> code, enum rtx_code outer_code,
>
> Â Â Â Â case CONST_VECTOR:
>       /* Fixme. */
> -Â Â Â Â Â if (TARGET_NEON
> -Â Â Â Â Â Â Â Â && TARGET_HARD_FLOAT
> -Â Â Â Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
> -Â Â Â Â Â Â Â Â && neon_immediate_valid_for_move (x, mode, NULL, NULL))
> +Â Â Â Â Â if (((TARGET_NEON && TARGET_HARD_FLOAT
> +Â Â Â Â Â Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE
> (mode)))
> +Â Â Â Â Â Â Â Â Â || TARGET_HAVE_MVE)
> +Â Â Â Â Â Â Â Â && simd_immediate_valid_for_move (x, mode, NULL, NULL))
> Â Â Â Â Â Â Â Â *cost = COSTS_N_INSNS (1);
> Â Â Â Â Â Â else
> Â Â Â Â Â Â Â Â *cost = COSTS_N_INSNS (4);
> @@ -12328,8 +12331,8 @@ vfp3_const_double_rtx (rtx x)
> Â Â return vfp3_const_double_index (x) != -1;
> Â }
>
> -/* Recognize immediates which can be used in various Neon
> instructions. Legal
> -Â Â immediates are described by the following table (for VMVN
> variants, the
> +/* Recognize immediates which can be used in various Neon and MVE
> instructions.
> +Â Â Legal immediates are described by the following table (for VMVN
> variants, the
> Â Â Â bitwise inverse of the constant shown is recognized. In either
> case, VMOV
> Â Â Â is output and the correct instruction to use for a given constant
> is chosen
> Â Â Â by the assembler). The constant shown is replicated across all
> elements of
> @@ -12380,7 +12383,7 @@ vfp3_const_double_rtx (rtx x)
> Â Â Â -1 if the given value doesn't match any of the listed patterns.
> Â */
> Â static int
> -neon_valid_immediate (rtx op, machine_mode mode, int inverse,
> +simd_valid_immediate (rtx op, machine_mode mode, int inverse,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â rtx *modconst, int *elementwidth)
> Â {
> Â #define CHECK(STRIDE, ELSIZE, CLASS, TEST)Â Â Â Â Â \
> @@ -12412,6 +12415,10 @@ neon_valid_immediate (rtx op, machine_mode
> mode, int inverse,
>
> Â Â innersize = GET_MODE_UNIT_SIZE (mode);
>
> + /* Only support 128-bit vectors for MVE. */
> +Â if (TARGET_HAVE_MVE && (!vector || n_elts * innersize != 16))
> +Â Â Â return -1;
> +
>   /* Vectors of float constants. */
> Â Â if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
> Â Â Â Â {
> @@ -12560,18 +12567,19 @@ neon_valid_immediate (rtx op, machine_mode
> mode, int inverse,
> Â #undef CHECK
> Â }
>
> -/* Return TRUE if rtx X is legal for use as either a Neon VMOV (or,
> implicitly,
> -Â Â VMVN) immediate. Write back width per element to *ELEMENTWIDTH (or
> zero for
> -Â Â float elements), and a modified constant (whatever should be
> output for a
> -  VMOV) in *MODCONST. */
> -
> +/* Return TRUE if rtx X is legal for use as either a Neon or MVE VMOV
> (or,
> +  implicitly, VMVN) immediate. Write back width per element to
> *ELEMENTWIDTH
> +Â Â (or zero for float elements), and a modified constant (whatever
> should be
> +Â Â output for a VMOV) in *MODCONST. "neon_immediate_valid_for_move"
> function is
> +Â Â modified to "simd_immediate_valid_for_move" as this function will
> be used
> +  both by neon and mve. */
> Â int
> -neon_immediate_valid_for_move (rtx op, machine_mode mode,
> +simd_immediate_valid_for_move (rtx op, machine_mode mode,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â rtx *modconst, int *elementwidth)
> Â {
> Â Â rtx tmpconst;
> Â Â int tmpwidth;
> -Â int retval = neon_valid_immediate (op, mode, 0, &tmpconst, &tmpwidth);
> +Â int retval = simd_valid_immediate (op, mode, 0, &tmpconst, &tmpwidth);
>
> Â Â if (retval == -1)
> Â Â Â Â return 0;
> @@ -12588,7 +12596,7 @@ neon_immediate_valid_for_move (rtx op,
> machine_mode mode,
> Â /* Return TRUE if rtx X is legal for use in a VORR or VBIC
> instruction. If
> Â Â Â the immediate is valid, write a constant suitable for using as an
> operand
> Â Â Â to VORR/VBIC/VAND/VORN to *MODCONST and the corresponding element
> width to
> -Â Â *ELEMENTWIDTH. See neon_valid_immediate for description of
> INVERSE. */
> +  *ELEMENTWIDTH. See simd_valid_immediate for description of
> INVERSE. */
>
> Â int
> Â neon_immediate_valid_for_logic (rtx op, machine_mode mode, int inverse,
> @@ -12596,7 +12604,7 @@ neon_immediate_valid_for_logic (rtx op,
> machine_mode mode, int inverse,
> Â {
> Â Â rtx tmpconst;
> Â Â int tmpwidth;
> -Â int retval = neon_valid_immediate (op, mode, inverse, &tmpconst,
> &tmpwidth);
> +Â int retval = simd_valid_immediate (op, mode, inverse, &tmpconst,
> &tmpwidth);
>
> Â Â if (retval < 0 || retval > 5)
> Â Â Â Â return 0;
> @@ -12803,7 +12811,7 @@ neon_make_constant (rtx vals)
> Â Â Â Â gcc_unreachable ();
>
> Â Â if (const_vec != NULL
> -Â Â Â Â Â && neon_immediate_valid_for_move (const_vec, mode, NULL, NULL))
> +Â Â Â Â Â && simd_immediate_valid_for_move (const_vec, mode, NULL, NULL))
>     /* Load using VMOV. On Cortex-A8 this takes one cycle. */
> Â Â Â Â return const_vec;
> Â Â else if ((target = neon_vdup_constant (vals)) != NULL_RTX)
> @@ -13080,6 +13088,15 @@ neon_vector_mem_operand (rtx op, int type,
> bool strict)
> Â Â Â Â Â Â && (INTVAL (XEXP (ind, 1)) & 3) == 0)
> Â Â Â Â return TRUE;
>
> +Â if (type == 1 && TARGET_HAVE_MVE
> +Â Â Â Â Â && (GET_CODE (ind) == POST_INC || GET_CODE (ind) == PRE_DEC))
> +Â Â Â {
> +Â Â Â Â Â rtx ind1 = XEXP (ind, 0);
> +Â Â Â Â Â if (!REG_P (ind1))
> +Â Â Â Â Â Â return 0;
> +Â Â Â Â Â return NEON_REGNO_OK_FOR_QUAD (REGNO (ind1));
> +Â Â Â }
> +
> Â Â return FALSE;
> Â }
>
> @@ -19936,7 +19953,7 @@ output_move_neon (rtx *operands)
> Â Â Â Â {
> Â Â Â Â case POST_INC:
> Â Â Â Â Â Â /* We have to use vldm / vstm for too-large modes. */
> -Â Â Â Â Â if (nregs > 4)
> +Â Â Â Â Â if (nregs > 4 || (TARGET_HAVE_MVE && nregs >= 2))
> Â Â Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â Â Â templ = "v%smia%%?\t%%0!, %%h1";
> Â Â Â Â Â Â Â Â Â Â ops[0] = XEXP (addr, 0);
> @@ -19965,7 +19982,7 @@ output_move_neon (rtx *operands)
> Â Â Â Â Â Â /* We have to use vldm / vstm for too-large modes. */
> Â Â Â Â Â Â if (nregs > 1)
> Â Â Â Â Â Â Â Â {
> -Â Â Â Â Â Â Â Â if (nregs > 4)
> +Â Â Â Â Â Â Â Â if (nregs > 4 || (TARGET_HAVE_MVE && nregs >= 2))
> Â Â Â Â Â Â Â Â Â Â Â Â templ = "v%smia%%?\t%%m0, %%h1";
> Â Â Â Â Â Â Â Â Â Â else
> Â Â Â Â Â Â Â Â Â Â Â Â templ = "v%s1.64\t%%h1, %%A0";
> @@ -19980,29 +19997,40 @@ output_move_neon (rtx *operands)
> Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â int i;
> Â Â Â Â Â Â Â Â int overlap = -1;
> -Â Â Â Â Â Â for (i = 0; i < nregs; i++)
> +Â Â Â Â Â Â if (TARGET_HAVE_MVE && !BYTES_BIG_ENDIAN)
> Â Â Â Â Â Â Â Â Â Â {
> -Â Â Â Â Â Â Â Â Â Â /* We're only using DImode here because it's a convenient
> size. */
> -Â Â Â Â Â Â Â Â Â Â ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * i);
> -Â Â Â Â Â Â Â Â Â Â ops[1] = adjust_address (mem, DImode, 8 * i);
> -Â Â Â Â Â Â Â Â Â Â if (reg_overlap_mentioned_p (ops[0], mem))
> +Â Â Â Â Â Â Â Â Â Â sprintf (buff, "v%srw.32\t%%q0, %%1", load ? "ld" : "st");
> +Â Â Â Â Â Â Â Â Â Â ops[0] = reg;
> +Â Â Â Â Â Â Â Â Â Â ops[1] = mem;
> +Â Â Â Â Â Â Â Â Â Â output_asm_insn (buff, ops);
> +Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â for (i = 0; i < nregs; i++)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â gcc_assert (overlap == -1);
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â overlap = i;
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* We're only using DImode here because it's a convenient
> +                 size. */
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * i);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â ops[1] = adjust_address (mem, DImode, 8 * i);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (reg_overlap_mentioned_p (ops[0], mem))
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â gcc_assert (overlap == -1);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â overlap = i;
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" :
> "st");
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â output_asm_insn (buff, ops);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
> -Â Â Â Â Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â Â Â if (overlap != -1)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * overlap);
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â ops[1] = adjust_address (mem, SImode, 8 * overlap);
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st");
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â output_asm_insn (buff, ops);
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â }
> Â Â Â Â Â Â Â Â Â Â }
> -Â Â Â Â Â Â if (overlap != -1)
> -Â Â Â Â Â Â Â Â {
> -Â Â Â Â Â Â Â Â Â Â ops[0] = gen_rtx_REG (DImode, REGNO (reg) + 2 * overlap);
> -Â Â Â Â Â Â Â Â Â Â ops[1] = adjust_address (mem, SImode, 8 * overlap);
> -Â Â Â Â Â Â Â Â Â Â sprintf (buff, "v%sr%%?\t%%P0, %%1", load ? "ld" : "st");
> -Â Â Â Â Â Â Â Â Â Â output_asm_insn (buff, ops);
> -Â Â Â Â Â Â Â Â }
>
> Â Â Â Â Â Â Â Â return "";
> Â Â Â Â Â Â }
> @@ -22223,7 +22251,7 @@ arm_compute_frame_layout (void)
> Â Â Â Â Â Â func_type = arm_current_func_type ();
>       /* Space for saved VFP registers. */
> Â Â Â Â Â Â if (! IS_VOLATILE (func_type)
> -Â Â Â Â Â Â Â Â && TARGET_HARD_FLOAT)
> +Â Â Â Â Â Â Â Â && (TARGET_HARD_FLOAT || TARGET_HAVE_MVE))
> Â Â Â Â Â Â Â Â saved += arm_get_vfp_saved_size ();
>
> Â Â Â Â Â Â /* Allocate space for saving/restoring FPCXTNS in Armv8.1-M
> Mainline
> @@ -22447,7 +22475,7 @@ arm_save_coproc_regs(void)
> Â Â Â Â Â Â Â Â saved_size += 8;
> Â Â Â Â Â Â }
>
> -Â if (TARGET_HARD_FLOAT)
> +Â if (TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â {
> Â Â Â Â Â Â start_reg = FIRST_VFP_REGNUM;
>
> @@ -23749,6 +23777,53 @@ arm_print_operand (FILE *stream, rtx x, int code)
> Â Â Â Â Â Â }
> Â Â Â Â Â Â return;
>
> +Â Â Â /* To print the memory operand with "Us" constraint. Based on the
> rtx_code
> +Â Â Â Â Â Â the memory operands output looks like following.
> +Â Â Â Â Â Â 1. [Rn], #+/-<imm>
> +Â Â Â Â Â Â 2. [Rn, #+/-<imm>]!
> +      3. [Rn]. */
> +Â Â Â case 'E':
> +Â Â Â Â Â {
> +Â Â Â Â Â Â rtx addr;
> +Â Â Â Â Â Â rtx postinc_reg = NULL;
> +Â Â Â Â Â Â unsigned inc_val = 0;
> +Â Â Â Â Â Â enum rtx_code code;
> +
> +Â Â Â Â Â Â gcc_assert (MEM_P (x));
> +Â Â Â Â Â Â addr = XEXP (x, 0);
> +Â Â Â Â Â Â code = GET_CODE (addr);
> +Â Â Â Â Â Â if (code == POST_INC || code == POST_DEC || code == PRE_INC
> +          || code == PRE_DEC)
> +Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r", REGNO (XEXP (addr, 0)));
> +Â Â Â Â Â Â Â Â Â Â inc_val = GET_MODE_SIZE (GET_MODE (x));
> +Â Â Â Â Â Â Â Â Â Â if (code == POST_INC || code == POST_DEC)
> +Â Â Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "], #%s%d",(code == POST_INC)
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ? "": "-", inc_val);
> +Â Â Â Â Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, ", #%s%d]!",(code == PRE_INC)
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ? "": "-", inc_val);
> +Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â else if (code == POST_MODIFY || code == PRE_MODIFY)
> +Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r", REGNO (XEXP (addr, 0)));
> +Â Â Â Â Â Â Â Â Â Â postinc_reg = XEXP ( XEXP (x, 1), 1);
> +Â Â Â Â Â Â Â Â Â Â if (postinc_reg && CONST_INT_P (postinc_reg))
> +Â Â Â Â Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (code == POST_MODIFY)
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "], #%wd",INTVAL (postinc_reg));
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, ", #%wd]!",INTVAL (postinc_reg));
> +Â Â Â Â Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â Â else
> +Â Â Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â Â Â gcc_assert (REG_P (addr));
> +Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r]",REGNO (addr));
> +Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â }
> +Â Â Â Â Â return;
> +
> Â Â Â Â case 'C':
> Â Â Â Â Â Â {
> Â Â Â Â Â Â Â Â rtx addr;
> @@ -23926,9 +24001,10 @@ arm_print_operand_address (FILE *stream,
> machine_mode mode, rtx x)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â REGNO (XEXP (x, 0)),
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â GET_CODE (x) == PRE_DEC ? "-" : "",
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â GET_MODE_SIZE (mode));
> +Â Â Â Â Â Â Â Â else if (TARGET_HAVE_MVE && (mode == OImode || mode == XImode))
> +Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r]!", REGNO (XEXP (x,0)));
> Â Â Â Â Â Â Â Â Â Â else
> -Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r], #%s%d",
> -Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â REGNO (XEXP (x, 0)),
> +Â Â Â Â Â Â Â Â Â Â asm_fprintf (stream, "[%r], #%s%d", REGNO (XEXP (x, 0)),
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â GET_CODE (x) == POST_DEC ? "-" : "",
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â GET_MODE_SIZE (mode));
> Â Â Â Â Â Â Â Â }
> @@ -24773,12 +24849,15 @@ arm_hard_regno_mode_ok (unsigned int regno,
> machine_mode mode)
> Â {
> Â Â if (GET_MODE_CLASS (mode) == MODE_CC)
> Â Â Â Â return (regno == CC_REGNUM
> -Â Â Â Â Â Â Â Â Â Â || (TARGET_HARD_FLOAT
> +Â Â Â Â Â Â Â Â Â Â || ((TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â && regno == VFPCC_REGNUM));
>
> Â Â if (regno == CC_REGNUM && GET_MODE_CLASS (mode) != MODE_CC)
> Â Â Â Â return false;
>
> +Â if (IS_VPR_REGNUM (regno))
> +Â Â Â return true;
> +
> Â Â if (TARGET_THUMB1)
> Â Â Â Â /* For the Thumb we only allow values bigger than SImode in
> Â Â Â Â Â Â Â registers 0 - 6, so that there is always a second low
> @@ -24787,7 +24866,7 @@ arm_hard_regno_mode_ok (unsigned int regno,
> machine_mode mode)
>        start of an even numbered register pair. */
> Â Â Â Â return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
>
> -Â if (TARGET_HARD_FLOAT && IS_VFP_REGNUM (regno))
> +Â if ((TARGET_HARD_FLOAT || TARGET_HAVE_MVE) && IS_VFP_REGNUM (regno))
> Â Â Â Â {
> Â Â Â Â Â Â if (mode == SFmode || mode == SImode)
> Â Â Â Â Â Â Â Â return VFP_REGNO_OK_FOR_SINGLE (regno);
> @@ -24811,6 +24890,10 @@ arm_hard_regno_mode_ok (unsigned int regno,
> machine_mode mode)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â || (mode == OImode && NEON_REGNO_OK_FOR_NREGS (regno, 4))
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â || (mode == CImode && NEON_REGNO_OK_FOR_NREGS (regno, 6))
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â || (mode == XImode && NEON_REGNO_OK_FOR_NREGS (regno, 8));
> +Â Â Â Â if (TARGET_HAVE_MVE)
> +Â Â Â Â Â Â return ((VALID_MVE_MODE (mode) && NEON_REGNO_OK_FOR_QUAD (regno))
> +Â Â Â Â Â Â Â Â Â Â Â Â Â || (mode == OImode && NEON_REGNO_OK_FOR_NREGS (regno, 4))
> +Â Â Â Â Â Â Â Â Â Â Â Â Â || (mode == XImode && NEON_REGNO_OK_FOR_NREGS (regno, 8)));
>
> Â Â Â Â Â Â return false;
> Â Â Â Â }
> @@ -24859,13 +24942,18 @@ arm_modes_tieable_p (machine_mode mode1,
> machine_mode mode2)
> Â Â /* We specifically want to allow elements of "structure" modes to
>      be tieable to the structure. This more general condition allows
>      other rarer situations too. */
> -Â if (TARGET_NEON
> -Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode1)
> -Â Â Â Â Â Â Â Â || VALID_NEON_QREG_MODE (mode1)
> -Â Â Â Â Â Â Â Â || VALID_NEON_STRUCT_MODE (mode1))
> -Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode2)
> -Â Â Â Â Â Â Â Â || VALID_NEON_QREG_MODE (mode2)
> -Â Â Â Â Â Â Â Â || VALID_NEON_STRUCT_MODE (mode2)))
> +Â if ((TARGET_NEON
> +Â Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode1)
> +Â Â Â Â Â Â Â Â Â || VALID_NEON_QREG_MODE (mode1)
> +Â Â Â Â Â Â Â Â Â || VALID_NEON_STRUCT_MODE (mode1))
> +Â Â Â Â Â Â && (VALID_NEON_DREG_MODE (mode2)
> +Â Â Â Â Â Â Â Â Â || VALID_NEON_QREG_MODE (mode2)
> +Â Â Â Â Â Â Â Â Â || VALID_NEON_STRUCT_MODE (mode2)))
> +Â Â Â Â Â || (TARGET_HAVE_MVE
> +Â Â Â Â Â Â Â Â && (VALID_MVE_MODE (mode1)
> +Â Â Â Â Â Â Â Â Â Â Â Â || VALID_MVE_STRUCT_MODE (mode1))
> +Â Â Â Â Â Â Â Â && (VALID_MVE_MODE (mode2)
> +Â Â Â Â Â Â Â Â Â Â Â Â || VALID_MVE_STRUCT_MODE (mode2))))
> Â Â Â Â return true;
>
> Â Â return false;
> @@ -24880,6 +24968,9 @@ arm_regno_class (int regno)
> Â Â if (regno == PC_REGNUM)
> Â Â Â Â return NO_REGS;
>
> +Â if (IS_VPR_REGNUM (regno))
> +Â Â Â return VPR_REG;
> +
> Â Â if (TARGET_THUMB1)
> Â Â Â Â {
> Â Â Â Â Â Â if (regno == STACK_POINTER_REGNUM)
> @@ -26731,7 +26822,7 @@ arm_expand_epilogue_apcs_frame (bool
> really_return)
> Â Â Â Â Â Â Â Â floats_from_frame += 4;
> Â Â Â Â Â Â }
>
> -Â if (TARGET_HARD_FLOAT)
> +Â if (TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â {
> Â Â Â Â Â Â int start_reg;
> Â Â Â Â Â Â rtx ip_rtx = gen_rtx_REG (SImode, IP_REGNUM);
> @@ -26977,7 +27068,7 @@ arm_expand_epilogue (bool really_return)
> Â Â Â Â Â Â Â Â }
> Â Â Â Â }
>
> -Â if (TARGET_HARD_FLOAT)
> +Â if (TARGET_HARD_FLOAT || TARGET_HAVE_MVE)
> Â Â Â Â {
>       /* Generate VFP register multi-pop. */
> Â Â Â Â Â Â int end_reg = LAST_VFP_REGNUM + 1;
> @@ -27148,7 +27239,7 @@ arm_expand_epilogue (bool really_return)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â GEN_INT
> (FPCXTNS_ENUM)));
> Â Â Â Â Â Â Â Â Â Â RTX_FRAME_RELATED_P (insn) = 1;
> Â Â Â Â Â Â Â Â }
> -Â Â Â Â Â }
> +Â Â Â }
>
> Â Â if (!really_return)
> Â Â Â Â return;
> @@ -28370,6 +28461,15 @@ arm_vector_mode_supported_p (machine_mode mode)
> Â Â Â Â Â Â || mode == V2HAmode))
> Â Â Â Â return true;
>
> +Â if (TARGET_HAVE_MVE
> +Â Â Â Â Â && (mode == V2DImode || mode == V4SImode || mode == V8HImode
> +Â Â Â Â Â Â Â Â || mode == V16QImode))
> +Â Â Â Â Â return true;
> +
> +Â if (TARGET_HAVE_MVE_FLOAT
> +Â Â Â Â Â && (mode == V2DFmode || mode == V4SFmode || mode == V8HFmode))
> +Â Â Â Â Â return true;
> +
> Â Â return false;
> Â }
>
> @@ -28387,6 +28487,10 @@ arm_array_mode_supported_p (machine_mode mode,
> Â Â Â Â Â Â && (nelems >= 2 && nelems <= 4))
> Â Â Â Â return true;
>
> +Â if (TARGET_HAVE_MVE && !BYTES_BIG_ENDIAN
> +Â Â Â Â Â && VALID_MVE_MODE (mode) && (nelems == 2 || nelems == 4))
> +Â Â Â return true;
> +
> Â Â return false;
> Â }
>
> @@ -29435,7 +29539,7 @@ arm_conditional_register_usage (void)
> Â Â if (TARGET_THUMB1)
> Â Â Â Â fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1;
>
> -Â if (TARGET_32BIT && TARGET_HARD_FLOAT)
> +Â if (TARGET_32BIT && (TARGET_HARD_FLOAT || TARGET_HAVE_MVE))
> Â Â Â Â {
> Â Â Â Â Â Â /* VFPv3 registers are disabled when earlier VFP
> Â Â Â Â Â Â Â Â Â versions are selected due to the definition of
> @@ -29447,6 +29551,8 @@ arm_conditional_register_usage (void)
> Â Â Â Â Â Â Â Â Â Â call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16
> Â Â Â Â Â Â Â Â Â Â Â Â || regno >= FIRST_VFP_REGNUM + 32;
> Â Â Â Â Â Â Â Â }
> +Â Â Â Â Â if (TARGET_HAVE_MVE)
> +Â Â Â Â Â Â fixed_regs[VPR_REGNUM] = 0;
> Â Â Â Â }
>
> Â Â if (TARGET_REALLY_IWMMXT && !TARGET_GENERAL_REGS_ONLY)
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index
> c62ad1b360ebecd5368e90ea5634488eef22f2fc..689baa0b0ff63ef90f47d2fd844cb98c9a1457a0
> 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -41,6 +41,7 @@
> Â Â Â (VFPCC_REGNUMÂ Â Â 101)Â Â Â Â Â Â ; VFP Condition code pseudo register
> Â Â Â (APSRQ_REGNUMÂ Â Â 104)Â Â Â Â Â Â ; Q bit pseudo register
> Â Â Â (APSRGE_REGNUMÂ Â 105)Â Â Â Â Â Â ; GE bits pseudo register
> +Â Â (VPR_REGNUMÂ Â Â Â Â 106)Â Â Â Â Â Â ; Vector Predication Register - MVE
> register.
> Â Â ]
> Â )
> Â ;; 3rd operand to select_dominance_cc_mode
> @@ -7293,7 +7294,7 @@
> Â Â [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
> Â Â Â Â Â Â Â Â (match_operand:SF 1 "general_operand"Â "r,mE,r"))]
> Â Â "TARGET_32BIT
> -Â Â && TARGET_SOFT_FLOAT
> +Â Â && TARGET_SOFT_FLOAT && !TARGET_HAVE_MVE
> Â Â Â && (!MEM_P (operands[0])
> Â Â Â Â Â Â Â || register_operand (operands[1], SFmode))"
> Â {
> @@ -7416,8 +7417,8 @@
>
> Â (define_insn "*movdf_soft_insn"
> Â Â [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
> -Â Â Â Â Â Â (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
> -Â "TARGET_32BIT && TARGET_SOFT_FLOAT
> +Â Â Â Â Â Â (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
> +Â "TARGET_32BIT && TARGET_SOFT_FLOAT && !TARGET_HAVE_MVE
> Â Â Â && (Â Â register_operand (operands[0], DFmode)
> Â Â Â Â Â Â Â || register_operand (operands[1], DFmode))"
> Â Â "*
> @@ -11681,7 +11682,7 @@
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (match_operand:SI 2 "const_int_I_operand" "I")))
> Â Â Â Â Â (set (match_operand:DF 3 "vfp_hard_register_operand" "")
> Â Â Â Â Â Â Â Â Â Â (mem:DF (match_dup 1)))])]
> -Â "TARGET_32BIT && TARGET_HARD_FLOAT"
> +Â "TARGET_32BIT && (TARGET_HARD_FLOAT || TARGET_HAVE_MVE)"
> Â Â "*
> Â Â {
> Â Â Â Â int num_regs = XVECLEN (operands[0], 0);
> @@ -12624,7 +12625,7 @@
> Â Â Â (set_attr "length" "8")]
> Â )
>
> -;; Vector bits common to IWMMXT and Neon
> +;; Vector bits common to IWMMXT, Neon and MVE
> Â (include "vec-common.md")
> Â ;; Load the Intel Wireless Multimedia Extension patterns
> Â (include "iwmmxt.md")
> @@ -12642,3 +12643,5 @@
> Â (include "sync.md")
> Â ;; Fixed-point patterns
> Â (include "arm-fixed.md")
> +;; M-profile Vector Extensions
> +(include "mve.md")
> diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..5ffb466596b5d8fc330616a6fcc7ee37d3e28def
> --- /dev/null
> +++ b/gcc/config/arm/arm_mve.h
> @@ -0,0 +1,59 @@
> +/* Arm MVE intrinsics include file.
> +
> +Â Â Copyright (C) 2019 Free Software Foundation, Inc.
> +Â Â Contributed by Arm.
> +
> +Â Â This file is part of GCC.
> +
> +Â Â GCC is free software; you can redistribute it and/or modify it
> +Â Â under the terms of the GNU General Public License as published
> +Â Â by the Free Software Foundation; either version 3, or (at your
> +Â Â option) any later version.
> +
> +Â Â GCC is distributed in the hope that it will be useful, but WITHOUT
> +Â Â ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> +Â Â License for more details.
> +
> +Â Â You should have received a copy of the GNU General Public License
> +  along with GCC; see the file COPYING3. If not see
> +Â Â <http://www.gnu.org/licenses/>. */
> +
> +#ifndef _GCC_ARM_MVE_H
> +#define _GCC_ARM_MVE_H
> +
> +#if !__ARM_FEATURE_MVE
> +#error "MVE feature not supported"
> +#endif
> +
> +#include <stdint.h>
> +#ifndef __cplusplus
> +#include <stdbool.h>
> +#endif
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#if (__ARM_FEATURE_MVE & 2) /* MVE Floating point. */
> +typedef __fp16 float16_t;
> +typedef float float32_t;
> +typedef __simd128_float16_t float16x8_t;
> +typedef __simd128_float32_t float32x4_t;
> +#endif
> +
> +typedef uint16_t mve_pred16_t;
> +typedef __simd128_uint8_t uint8x16_t;
> +typedef __simd128_uint16_t uint16x8_t;
> +typedef __simd128_uint32_t uint32x4_t;
> +typedef __simd128_uint64_t uint64x2_t;
> +typedef __simd128_int8_t int8x16_t;
> +typedef __simd128_int16_t int16x8_t;
> +typedef __simd128_int32_t int32x4_t;
> +typedef __simd128_int64_t int64x2_t;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _GCC_ARM_MVE_H. */
> diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
> index
> 6f309b95cc1874ac7bc69e435781070e0c9cb70a..f77084a0efd489491372bb1dafbc0cd585f0f518
> 100644
> --- a/gcc/config/arm/constraints.md
> +++ b/gcc/config/arm/constraints.md
> @@ -44,6 +44,8 @@
> Â ;; in Thumb state: Uu, Uw
> Â ;; in all states: Q
>
> +(define_register_constraint "Up" "TARGET_HAVE_MVE ? VPR_REG : NO_REGS"
> +Â "MVE VPR register")
>
> Â (define_register_constraint "t" "TARGET_32BIT ? VFP_LO_REGS : NO_REGS"
> Â "The VFP registers @code{s0}-@code{s31}.")
> diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
> index
> c412851843f4468c2c18bce264288705e076ac50..e30325bc1652d378be2544fa32269c5c4294d7e9
> 100644
> --- a/gcc/config/arm/iterators.md
> +++ b/gcc/config/arm/iterators.md
> @@ -62,6 +62,12 @@
> Â ;; Integer and float modes supported by Neon and IWMMXT.
> Â (define_mode_iterator VALL [V2DI V2SI V4HI V8QI V2SF V4SI V8HI V16QI
> V4SF])
>
> +;; Integer and float modes supported by Neon, IWMMXT and MVE.
> +(define_mode_iterator VNIM1 [V16QI V8HI V4SI V4SF V2DI])
> +
> +;; Integer and float modes supported by Neon and IWMMXT but not MVE.
> +(define_mode_iterator VNINOTM1 [V2SI V4HI V8QI V2SF])
> +
> Â ;; Integer and float modes supported by Neon and IWMMXT, except V2DI.
> Â (define_mode_iterator VALLW [V2SI V4HI V8QI V2SF V4SI V8HI V16QI V4SF])
>
> @@ -105,7 +111,8 @@
> Â (define_mode_iterator VQXMOV [V16QI V8HI V8HF V4SI V4SF V2DI TI])
>
> Â ;; Opaque structure types wider than TImode.
> -(define_mode_iterator VSTRUCT [EI OI CI XI])
> +(define_mode_iterator VSTRUCT [(EI "!TARGET_HAVE_MVE") OI
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (CI "!TARGET_HAVE_MVE") XI])
>
> Â ;; Opaque structure types used in table lookups (except vtbl1/vtbx1).
> Â (define_mode_iterator VTAB [TI EI OI])
> diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..53334c6d329dedd482615b996232e85ded7a34f8
> --- /dev/null
> +++ b/gcc/config/arm/mve.md
> @@ -0,0 +1,78 @@
> +;; Arm M-profile Vector Extension Machine Description
> +;; Copyright (C) 2019 Free Software Foundation, Inc.
> +;;
> +;; This file is part of GCC.
> +;;
> +;; GCC is free software; you can redistribute it and/or modify it
> +;; under the terms of the GNU General Public License as published by
> +;; the Free Software Foundation; either version 3, or (at your option)
> +;; any later version.
> +;;
> +;; GCC is distributed in the hope that it will be useful, but
> +;; WITHOUT ANY WARRANTY; without even the implied warranty of
> +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +;; General Public License for more details.
> +;;
> +;; You should have received a copy of the GNU General Public License
> +;; along with GCC; see the file COPYING3. If not see
> +;; <http://www.gnu.org/licenses/>.
> +
> +(define_mode_iterator MVE_types [V16QI V8HI V4SI V2DI TI V8HF V4SF V2DF])
> +(define_mode_attr V_sz_elem2 [(V16QI "s8") (V8HI "u16") (V4SI "u32")
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (V2DI "u64")])
> +
> +(define_insn "*mve_mov<mode>"
> +Â [(set (match_operand:MVE_types 0 "s_register_operand" "=w,w,r,w,w,r,w")
> +Â Â Â Â Â Â (match_operand:MVE_types 1 "general_operand"
> "w,r,w,Dn,Usi,r,Dm"))]
> +Â "TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT"
> +{
> +Â if (which_alternative == 3 || which_alternative == 6)
> +Â Â Â {
> +Â Â Â Â Â int width, is_valid;
> +Â Â Â Â Â static char templ[40];
> +
> +Â Â Â Â Â is_valid = simd_immediate_valid_for_move (operands[1], <MODE>mode,
> +Â Â Â Â Â Â &operands[1], &width);
> +
> +Â Â Â Â Â gcc_assert (is_valid != 0);
> +
> +Â Â Â Â Â if (width == 0)
> +Â Â Â Â Â Â return "vmov.f32\t%q0, %1Â @ <mode>";
> +Â Â Â Â Â else
> +Â Â Â Â Â Â sprintf (templ, "vmov.i%d\t%%q0, %%x1Â @ <mode>", width);
> +Â Â Â Â Â return templ;
> +Â Â Â }
> +Â switch (which_alternative)
> +Â Â Â {
> +Â Â Â case 0:
> +Â Â Â Â Â return "vmov\t%q0, %q1";
> +Â Â Â case 1:
> +Â Â Â Â Â return "vmov\t%e0, %Q1, %R1Â @ <mode>\;vmov\t%f0, %J1, %K1";
> +Â Â Â case 2:
> +Â Â Â Â Â return "vmov\t%Q0, %R0, %e1Â @ <mode>\;vmov\t%J0, %K0, %f1";
> +Â Â Â case 4:
> +Â Â Â Â Â if ((TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE (<MODE>mode))
> +Â Â Â Â Â Â Â Â || (MEM_P (operands[1])
> +Â Â Â Â Â Â Â Â Â Â Â Â && GET_CODE (XEXP (operands[1], 0)) == LABEL_REF))
> +Â Â Â Â Â Â return output_move_neon (operands);
> +Â Â Â Â Â else
> +Â Â Â Â Â Â return "vldrb.<V_sz_elem2> %q0, %E1";
> +Â Â Â case 5:
> +Â Â Â Â Â return output_move_neon (operands);
> +Â Â Â case 6:
> +Â Â Â default:
> +Â Â Â Â Â gcc_unreachable ();
> +Â Â Â Â Â return "";
> +Â Â Â }
> +}
> +Â [(set_attr "type"
> "mve_move,mve_move,mve_move,mve_move,mve_load,mve_move,mve_move")
> +Â Â (set_attr "length" "4,8,8,4,8,8,4")
> +Â Â (set_attr "thumb2_pool_range" "*,*,*,*,1018,*,*")
> +Â Â (set_attr "neg_pool_range" "*,*,*,*,996,*,*")])
> +
> +(define_insn "*mve_vstr<mode>"
> +Â [(set (match_operand:MVE_types 0 "memory_operand" "=Us")
> +Â Â Â Â Â Â (match_operand:MVE_types 1 "s_register_operand" "w"))]
> +Â "TARGET_HAVE_MVE"
> +Â "vstrb.<V_sz_elem> %q1, %E0"
> +Â [(set_attr "type" "mve_store")])
> diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
> index
> 6a0ee28efc9aa9f1fba7b5ae031564f40aa095fe..c23783e0ed914ec21a92828388ada58ada3c6132
> 100644
> --- a/gcc/config/arm/neon.md
> +++ b/gcc/config/arm/neon.md
> @@ -35,9 +35,9 @@
>
> Â (define_insn "*neon_mov<mode>"
> Â Â [(set (match_operand:VDX 0 "nonimmediate_operand"
> -        "=w,Un,w, w, w, ?r,?w,?r, ?Us,*r")
> +      "=w,Un,w, w, w, ?r,?w,?r, ?Us,*r")
> Â Â Â Â Â Â Â Â (match_operand:VDX 1 "general_operand"
> -Â Â Â Â Â Â Â Â " w,w, Dm,Dn,Uni, w, r, Usi,r,*r"))]
> +Â Â Â Â Â Â " w,w, Dm,Dn,Uni, w, r, Usi,r,*r"))]
> Â Â "TARGET_NEON
> Â Â Â && (register_operand (operands[0], <MODE>mode)
> Â Â Â Â Â Â Â || register_operand (operands[1], <MODE>mode))"
> @@ -47,7 +47,7 @@
> Â Â Â Â Â Â int width, is_valid;
> Â Â Â Â Â Â static char templ[40];
>
> -Â Â Â Â Â is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
> +Â Â Â Â Â is_valid = simd_immediate_valid_for_move (operands[1], <MODE>mode,
> Â Â Â Â Â Â Â Â &operands[1], &width);
>
> Â Â Â Â Â Â gcc_assert (is_valid != 0);
> @@ -94,7 +94,7 @@
> Â Â Â Â Â Â int width, is_valid;
> Â Â Â Â Â Â static char templ[40];
>
> -Â Â Â Â Â is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode,
> +Â Â Â Â Â is_valid = simd_immediate_valid_for_move (operands[1], <MODE>mode,
> Â Â Â Â Â Â Â Â &operands[1], &width);
>
> Â Â Â Â Â Â gcc_assert (is_valid != 0);
> @@ -147,9 +147,9 @@
> Â })
>
> Â (define_expand "mov<mode>"
> -Â [(set (match_operand:VSTRUCT 0 "nonimmediate_operand")
> -Â Â Â Â Â Â (match_operand:VSTRUCT 1 "general_operand"))]
> -Â "TARGET_NEON"
> +Â [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
> +Â Â Â Â Â Â (match_operand:VSTRUCT 1 "general_operand" ""))]
> +Â "TARGET_NEON || TARGET_HAVE_MVE"
> Â {
> Â Â gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
> Â Â gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
> @@ -160,24 +160,28 @@
> Â Â Â Â }
> Â })
>
> -(define_expand "mov<mode>"
> -Â [(set (match_operand:VH 0 "s_register_operand")
> -Â Â Â Â Â Â (match_operand:VH 1 "s_register_operand"))]
> +;; The pattern mov<mode> where mode is v4hf and v8hf is split into
> +;; movv4hf and movv8hf. The pattern movv8hf is common for MVE and
> +;; NEON, so it is moved into vec-common.md file.
> +(define_expand "movv4hf"
> +Â [(set (match_operand:V4HF 0 "s_register_operand")
> +Â Â Â Â Â Â (match_operand:V4HF 1 "s_register_operand"))]
> Â Â "TARGET_NEON"
> Â {
> -Â gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
> -Â gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
> +Â gcc_checking_assert (aligned_operand (operands[0], E_V4HFmode));
> +Â gcc_checking_assert (aligned_operand (operands[1], E_V4HFmode));
> Â Â if (can_create_pseudo_p ())
> Â Â Â Â {
> Â Â Â Â Â Â if (!REG_P (operands[0]))
> -Â Â Â Â Â Â operands[1] = force_reg (<MODE>mode, operands[1]);
> +Â Â Â Â Â Â operands[1] = force_reg (E_V4HFmode, operands[1]);
> Â Â Â Â }
> Â })
>
> +
> Â (define_insn "*neon_mov<mode>"
> Â Â [(set (match_operand:VSTRUCT 0 "nonimmediate_operand"Â Â Â Â Â Â Â "=w,Ut,w")
> Â Â Â Â Â Â Â Â (match_operand:VSTRUCT 1 "general_operand"Â Â Â Â Â " w,w, Ut"))]
> -Â "TARGET_NEON
> +Â "(TARGET_NEON || TARGET_HAVE_MVE)
> Â Â Â && (register_operand (operands[0], <MODE>mode)
> Â Â Â Â Â Â Â || register_operand (operands[1], <MODE>mode))"
> Â {
> @@ -213,7 +217,7 @@
> Â (define_split
> Â Â [(set (match_operand:OI 0 "s_register_operand" "")
> Â Â Â Â Â Â Â Â (match_operand:OI 1 "s_register_operand" ""))]
> -Â "TARGET_NEON && reload_completed"
> +Â "(TARGET_NEON || TARGET_HAVE_MVE) && reload_completed"
> Â Â [(set (match_dup 0) (match_dup 1))
> Â Â Â (set (match_dup 2) (match_dup 3))]
> Â {
> @@ -254,7 +258,7 @@
> Â (define_split
> Â Â [(set (match_operand:XI 0 "s_register_operand" "")
> Â Â Â Â Â Â Â Â (match_operand:XI 1 "s_register_operand" ""))]
> -Â "TARGET_NEON && reload_completed"
> +Â "(TARGET_NEON || TARGET_HAVE_MVE) && reload_completed"
> Â Â [(set (match_dup 0) (match_dup 1))
> Â Â Â (set (match_dup 2) (match_dup 3))
> Â Â Â (set (match_dup 4) (match_dup 5))
> @@ -489,7 +493,7 @@
> Â (define_expand "vec_init<mode><V_elem_l>"
> Â Â [(match_operand:VDQ 0 "s_register_operand")
> Â Â Â (match_operand 1 "" "")]
> -Â "TARGET_NEON"
> +Â "TARGET_NEON || TARGET_HAVE_MVE"
> Â {
> Â Â neon_expand_vector_init (operands[0], operands[1]);
> Â Â DONE;
> diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
> index
> 2f0f532edf40d475e4199aa41bd7803fac8d6143..9d74165fe065b03c77918fe9e4611967799535f1
> 100644
> --- a/gcc/config/arm/predicates.md
> +++ b/gcc/config/arm/predicates.md
> @@ -48,6 +48,16 @@
> Â Â return guard_addr_operand (XEXP (op, 0), mode);
> Â })
>
> +(define_predicate "vpr_register_operand"
> +Â (match_code "reg,subreg")
> +{
> +Â if (GET_CODE (op) == SUBREG)
> +Â Â Â op = SUBREG_REG (op);
> +Â return REG_P (op)
> +Â Â Â Â Â Â Â Â && (REGNO (op) >= FIRST_PSEUDO_REGISTER
> +Â Â Â Â Â Â Â Â Â Â Â Â || IS_VPR_REGNUM (REGNO (op)));
> +})
> +
> Â (define_predicate "imm_for_neon_inv_logic_operand"
> Â Â (match_code "const_vector")
> Â {
> @@ -706,7 +716,7 @@
> Â (define_predicate "imm_for_neon_mov_operand"
> Â Â (match_code "const_vector,const_int")
> Â {
> -Â return neon_immediate_valid_for_move (op, mode, NULL, NULL);
> +Â return simd_immediate_valid_for_move (op, mode, NULL, NULL);
> Â })
>
> Â (define_predicate "imm_for_neon_lshift_operand"
> diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
> index
> af60c8fc285bb536afeb9ec5c21771a4379755fc..fda5e84355b56a20eb9a22919ab1c786120cc8f1
> 100644
> --- a/gcc/config/arm/t-arm
> +++ b/gcc/config/arm/t-arm
> @@ -55,6 +55,7 @@ MD_INCLUDES= $(srcdir)/config/arm/arm1020e.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/ldmstm.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/ldrdstrd.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/marvell-f-iwmmxt.md \
> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/mve.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/neon.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/predicates.md \
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â $(srcdir)/config/arm/sync.md \
> diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md
> index
> 60faad6597935607ed3c5593f941a04bbc924252..c99b846ab387bac633be8b1631f0e40b3c827850
> 100644
> --- a/gcc/config/arm/types.md
> +++ b/gcc/config/arm/types.md
> @@ -550,6 +550,11 @@
> Â ; The classification below is for TME instructions
> Â ;
> Â ; tme
> +; The classification below is for M-profile Vector Extension instructions
> +;
> +; mve_move
> +; mve_store
> +; mve_load
>
> Â (define_attr "type"
> Â "adc_imm,\
> @@ -1096,7 +1101,11 @@
> Â Â crypto_sm3,\
> Â Â crypto_sm4,\
> Â Â coproc,\
> -Â tme"
> +Â tme,\
> +\
> +Â mve_move,\
> +Â mve_store,\
> +Â mve_load"
> Â Â Â (const_string "untyped"))
>
> Â ; Is this an (integer side) multiply with a 32-bit (or smaller) result?
> diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
> index
> 33ff5627284d7cc898074b562179938982ecc420..5f5c113cf95afafbb733e1bfd2a7c7b8a55651a2
> 100644
> --- a/gcc/config/arm/vec-common.md
> +++ b/gcc/config/arm/vec-common.md
> @@ -21,8 +21,31 @@
> Â ;; Vector Moves
>
> Â (define_expand "mov<mode>"
> -Â [(set (match_operand:VALL 0 "nonimmediate_operand")
> -Â Â Â Â Â Â (match_operand:VALL 1 "general_operand"))]
> +Â [(set (match_operand:VNIM1 0 "nonimmediate_operand")
> +Â Â Â Â Â Â (match_operand:VNIM1 1 "general_operand"))]
> +Â "TARGET_NEON
> +Â Â || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))
> +Â Â || (TARGET_HAVE_MVE && VALID_MVE_SI_MODE (<MODE>mode))
> +Â Â || (TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE (<MODE>mode))"
> +Â Â {
> +Â gcc_checking_assert (aligned_operand (operands[0], <MODE>mode));
> +Â gcc_checking_assert (aligned_operand (operands[1], <MODE>mode));
> +Â if (can_create_pseudo_p ())
> +Â Â Â {
> +Â Â Â Â Â if (!REG_P (operands[0]))
> +Â Â Â Â Â Â operands[1] = force_reg (<MODE>mode, operands[1]);
> +Â Â Â Â Â else if ((TARGET_NEON || TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT)
> +Â Â Â Â Â Â Â Â Â Â Â Â Â && (CONSTANT_P (operands[1])))
> +Â Â Â Â Â Â {
> +Â Â Â Â Â Â Â Â operands[1] = neon_make_constant (operands[1]);
> +Â Â Â Â Â Â Â Â gcc_assert (operands[1] != NULL_RTX);
> +Â Â Â Â Â Â }
> +Â Â Â }
> +})
> +
> +(define_expand "mov<mode>"
> +Â [(set (match_operand:VNINOTM1 0 "nonimmediate_operand")
> +Â Â Â Â Â Â (match_operand:VNINOTM1 1 "general_operand"))]
> Â Â "TARGET_NEON
> Â Â Â || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
> Â {
> @@ -40,6 +63,20 @@
> Â Â Â Â }
> Â })
>
> +(define_expand "movv8hf"
> +Â [(set (match_operand:V8HF 0 "s_register_operand")
> +Â Â Â Â Â Â (match_operand:V8HF 1 "s_register_operand"))]
> +Â Â "TARGET_NEON || TARGET_HAVE_MVE_FLOAT"
> +{
> +Â gcc_checking_assert (aligned_operand (operands[0], E_V8HFmode));
> +Â gcc_checking_assert (aligned_operand (operands[1], E_V8HFmode));
> +Â Â if (can_create_pseudo_p ())
> +Â Â Â Â {
> +Â Â Â Â Â Â if (!REG_P (operands[0]))
> +Â Â Â Â Â Â Â operands[1] = force_reg (E_V8HFmode, operands[1]);
> +Â Â Â Â }
> +})
> +
> Â ;; Vector arithmetic. Expanders are blank, then unnamed insns implement
> Â ;; patterns separately for IWMMXT and Neon.
>
> diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
> index
> 573db164f01b4ac9ee4a9ee7414872fb93c9e2ca..6349c0570540ec25a599166f5d427fcbdbf2af68
> 100644
> --- a/gcc/config/arm/vfp.md
> +++ b/gcc/config/arm/vfp.md
> @@ -311,7 +311,7 @@
> Â Â Â && (Â Â register_operand (operands[0], DImode)
> Â Â Â Â Â Â Â || register_operand (operands[1], DImode))
> Â Â Â && !(TARGET_NEON && CONST_INT_P (operands[1])
> -Â Â Â Â Â Â Â && neon_immediate_valid_for_move (operands[1], DImode, NULL,
> NULL))"
> +Â Â Â Â Â Â && simd_immediate_valid_for_move (operands[1], DImode, NULL,
> NULL))"
> Â Â "*
> Â Â switch (which_alternative)
> Â Â Â Â {
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..c3f81546c9f14f2491c6fb134170f17bcba16069
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float.c
> @@ -0,0 +1,27 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve.fp
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +float32x4_t
> +foo32 (float32x4_t value)
> +{
> +Â float32x4_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldmia.*" }Â } */
> +
> +float16x8_t
> +foo16 (float16x8_t value)
> +{
> +Â float16x8_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldmia.*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float1.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float1.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..ebee0d2f1ad03b66d044d93bf901e0ce78eccba9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float1.c
> @@ -0,0 +1,31 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve.fp
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +float32x4_t value;
> +
> +float32x4_t
> +foo32 ()
> +{
> +Â float32x4_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldmia.*" }Â } */
> +
> +float16x8_t value1;
> +
> +float16x8_t
> +foo16 ()
> +{
> +Â float16x8_t b = value1;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldmia.*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float2.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float2.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9b9c84d66ef8fd585a42be1ac7585d8bc6c529bb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_float2.c
> @@ -0,0 +1,27 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve.fp
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +float32x4_t
> +foo32 ()
> +{
> +Â float32x4_t b = {10.0, 12.0, 14.0, 16.0};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32*" }Â } */
> +
> +float16x8_t
> +foo16 ()
> +{
> +Â float16x8_t b = {32.01};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..6b54c3c61f32cf8e0af30272df63f261def0b8c5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int.c
> @@ -0,0 +1,49 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +int8x16_t
> +foo8 (int8x16_t value)
> +{
> +Â int8x16_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.s8*" }Â } */
> +
> +int16x8_t
> +foo16 (int16x8_t value)
> +{
> +Â int16x8_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u16*" }Â } */
> +
> +int32x4_t
> +foo32 (int32x4_t value)
> +{
> +Â int32x4_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u32*" }Â } */
> +
> +int64x2_t
> +foo64 (int64x2_t value)
> +{
> +Â int64x2_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u64*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int1.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int1.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..748ddecbd4011bb24058c27cd6a09d66f71ce581
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int1.c
> @@ -0,0 +1,54 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +int8x16_t value1;
> +int16x8_t value2;
> +int32x4_t value3;
> +int64x2_t value4;
> +
> +int8x16_t
> +foo8 ()
> +{
> +Â int8x16_t b = value1;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u8*" }Â } */
> +
> +int16x8_t
> +foo16 ()
> +{
> +Â int16x8_t b = value2;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u16*" }Â } */
> +
> +int32x4_t
> +foo32 ()
> +{
> +Â int32x4_t b = value3;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u32" }Â } */
> +
> +int64x2_t
> +foo64 ()
> +{
> +Â int64x2_t b = value4;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u64" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int2.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int2.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..376ec9ee7fc04ddde98719d2605319a378f9a6bb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_int2.c
> @@ -0,0 +1,49 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +int8x16_t
> +foo8 ()
> +{
> +Â int8x16_t b = {1, 2, 3, 4};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +int16x8_t
> +foo16 (int16x8_t value)
> +{
> +Â int16x8_t b = {1, 2, 3};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +int32x4_t
> +foo32 (int32x4_t value)
> +{
> +Â int32x4_t b = {1, 2};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +int64x2_t
> +foo64 (int64x2_t value)
> +{
> +Â int64x2_t b = {1};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..f001d14f9ca4c851ed4b3371ae9599d23d2b62ce
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint.c
> @@ -0,0 +1,49 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +uint8x16_t
> +foo8 (uint8x16_t value)
> +{
> +Â uint8x16_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.s8*" }Â } */
> +
> +uint16x8_t
> +foo16 (uint16x8_t value)
> +{
> +Â uint16x8_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u16*" }Â } */
> +
> +uint32x4_t
> +foo32 (uint32x4_t value)
> +{
> +Â uint32x4_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u32*" }Â } */
> +
> +uint64x2_t
> +foo64 (uint64x2_t value)
> +{
> +Â uint64x2_t b = value;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u64*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint1.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint1.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..56d40668d63ba0b24c08944981c415054494c37d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint1.c
> @@ -0,0 +1,54 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +uint8x16_t value1;
> +uint16x8_t value2;
> +uint32x4_t value3;
> +uint64x2_t value4;
> +
> +uint8x16_t
> +foo8 ()
> +{
> +Â uint8x16_t b = value1;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.s8*" }Â } */
> +
> +uint16x8_t
> +foo16 ()
> +{
> +Â uint16x8_t b = value2;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u16*" }Â } */
> +
> +uint32x4_t
> +foo32 ()
> +{
> +Â uint32x4_t b = value3;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u32*" }Â } */
> +
> +uint64x2_t
> +foo64 ()
> +{
> +Â uint64x2_t b = value4;
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrb.u64*" }Â } */
> diff --git
> a/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint2.c
> b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint2.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9ff9b67993ac83cf398880cb65510604a37de6a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/mve_vector_uint2.c
> @@ -0,0 +1,49 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.1-m.main+mve
> -mfloat-abi=hard"Â }Â */
> +/* { dg-skip-if "Skip if not auto" {*-*-*} {"-mfpu=*"} {"-mcpu=auto"}
> } */
> +
> +#include "arm_mve.h"
> +
> +uint8x16_t
> +foo8 (uint8x16_t value)
> +{
> +Â uint8x16_t b = {1, 2, 3, 4};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +uint16x8_t
> +foo16 (uint16x8_t value)
> +{
> +Â uint16x8_t b = {1, 2, 3};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +uint32x4_t
> +foo32 (uint32x4_t value)
> +{
> +Â uint32x4_t b = {1, 2};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> +
> +uint64x2_t
> +foo64 (uint64x2_t value)
> +{
> +Â uint64x2_t b = {1};
> +Â return b;
> +}
> +
> +/* { dg-final { scan-assembler "vmov\\tq\[0-7\], q\[0-7\]" }Â } */
> +/* { dg-final { scan-assembler "vstrb.*" }Â } */
> +/* { dg-final { scan-assembler "vldrw.32.*" }Â } */
> diff --git a/gcc/testsuite/gcc.target/arm/mve/mve.exp
> b/gcc/testsuite/gcc.target/arm/mve/mve.exp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..77ae3fa292b2892fb22c2f89223ca19dc16ccc99
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/arm/mve/mve.exp
> @@ -0,0 +1,47 @@
> +# Copyright (C) 2019 Free Software Foundation, Inc.
> +
> +# This program 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 of the License, or
> +# (at your option) any later version.
> +#
> +# This program 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/>.
> +
> +# GCC testsuite that uses the `dg.exp' driver.
> +
> +# Exit immediately if this isn't an ARM target.
> +if ![istarget arm*-*-*] then {
> +Â return
> +}
> +
> +# Load support procs.
> +load_lib gcc-dg.exp
> +
> +# If a testcase doesn't have special options, use these.
> +global DEFAULT_CFLAGS
> +if ![info exists DEFAULT_CFLAGS] then {
> +Â Â Â set DEFAULT_CFLAGS " -ansi -pedantic-errors"
> +}
> +
> +# This variable should only apply to tests called in this exp file.
> +global dg_runtest_extra_prunes
> +set dg_runtest_extra_prunes ""
> +lappend dg_runtest_extra_prunes "warning: switch -m(cpu|arch)=.*
> conflicts with -m(cpu|arch)=.* switch"
> +
> +# Initialize `dg'.
> +dg-init
> +
> +# Main loop.
> +dg-runtest [lsort [glob -nocomplain
> $srcdir/$subdir/intrinsics/*.\[cCS\]]] \
> +Â Â Â Â Â Â "" $DEFAULT_CFLAGS
> +
> +# All done.
> +set dg_runtest_extra_prunes ""
> +dg-finish
>
More information about the Gcc-patches
mailing list