Projects
openEuler:24.03:SP1:Everything
gcc
_service:tar_scm:0174-Backport-SME-aarch64-Add-...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch of Package gcc
From 70b732b4518dd0e44b9e6bfaaad78492b8db8f29 Mon Sep 17 00:00:00 2001 From: Richard Sandiford <richard.sandiford@arm.com> Date: Tue, 5 Dec 2023 10:11:23 +0000 Subject: [PATCH 075/157] [Backport][SME] aarch64: Add arm_streaming(_compatible) attributes Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2c9a54b4238308b127c3b60b01a591363131e7db This patch adds support for recognising the SME arm::streaming and arm::streaming_compatible attributes. These attributes respectively describe whether the processor is definitely in "streaming mode" (PSTATE.SM==1), whether the processor is definitely not in streaming mode (PSTATE.SM==0), or whether we don't know at compile time either way. As far as the compiler is concerned, this effectively creates three ISA submodes: streaming mode enables things that are not available in non-streaming mode, non-streaming mode enables things that not available in streaming mode, and streaming-compatible mode has to stick to the common subset. This means that some instructions are conditional on PSTATE.SM==1 and some are conditional on PSTATE.SM==0. I wondered about recording the streaming state in a new variable. However, the set of available instructions is also influenced by PSTATE.ZA (added later), so I think it makes sense to view this as an instance of a more general mechanism. Also, keeping the PSTATE.SM state in the same flag variable as the other ISA features makes it possible to sum up the requirements of an ACLE function in a single value. The patch therefore adds a new set of feature flags called "ISA modes". Unlike the other two sets of flags (optional features and architecture- level features), these ISA modes are not controlled directly by command-line parameters or "target" attributes. arm::streaming and arm::streaming_compatible are function type attributes rather than function declaration attributes. This means that we need to find somewhere to copy the type information across to a function's target options. The patch does this in aarch64_set_current_function. We also need to record which ISA mode a callee expects/requires to be active on entry. (The same mode is then active on return.) The patch extends the current UNSPEC_CALLEE_ABI cookie to include this information, as well as the PCS variant that it recorded previously. The attributes can also be written __arm_streaming and __arm_streaming_compatible. This has two advantages: it triggers an error on compilers that don't understand the attributes, and it eases use on C, where [[...]] attributes were only added in C23. gcc/ * config/aarch64/aarch64-isa-modes.def: New file. * config/aarch64/aarch64.h: Include it in the feature enumerations. (AARCH64_FL_SM_STATE, AARCH64_FL_ISA_MODES): New constants. (AARCH64_FL_DEFAULT_ISA_MODE): Likewise. (AARCH64_ISA_MODE): New macro. (CUMULATIVE_ARGS): Add an isa_mode field. * config/aarch64/aarch64-protos.h (aarch64_gen_callee_cookie): Declare. (aarch64_tlsdesc_abi_id): Return an arm_pcs. * config/aarch64/aarch64.cc (attr_streaming_exclusions) (aarch64_gnu_attributes, aarch64_gnu_attribute_table) (aarch64_arm_attributes, aarch64_arm_attribute_table): New tables. (aarch64_attribute_table): Redefine to include the gnu and arm attributes. (aarch64_fntype_pstate_sm, aarch64_fntype_isa_mode): New functions. (aarch64_fndecl_pstate_sm, aarch64_fndecl_isa_mode): Likewise. (aarch64_gen_callee_cookie, aarch64_callee_abi): Likewise. (aarch64_insn_callee_cookie, aarch64_insn_callee_abi): Use them. (aarch64_function_arg, aarch64_output_mi_thunk): Likewise. (aarch64_init_cumulative_args): Initialize the isa_mode field. (aarch64_output_mi_thunk): Use aarch64_gen_callee_cookie to get the ABI cookie. (aarch64_override_options): Add the ISA mode to the feature set. (aarch64_temporary_target::copy_from_fndecl): Likewise. (aarch64_fndecl_options, aarch64_handle_attr_arch): Likewise. (aarch64_set_current_function): Maintain the correct ISA mode. (aarch64_tlsdesc_abi_id): Return an arm_pcs. (aarch64_comp_type_attributes): Handle arm::streaming and arm::streaming_compatible. * config/aarch64/aarch64-c.cc (aarch64_define_unconditional_macros): Define __arm_streaming and __arm_streaming_compatible. * config/aarch64/aarch64.md (tlsdesc_small_<mode>): Use aarch64_gen_callee_cookie to get the ABI cookie. * config/aarch64/t-aarch64 (TM_H): Add all feature-related .def files. gcc/testsuite/ * gcc.target/aarch64/sme/aarch64-sme.exp: New harness. * gcc.target/aarch64/sme/streaming_mode_1.c: New test. * gcc.target/aarch64/sme/streaming_mode_2.c: Likewise. * gcc.target/aarch64/sme/keyword_macros_1.c: Likewise. * g++.target/aarch64/sme/aarch64-sme.exp: New harness. * g++.target/aarch64/sme/streaming_mode_1.C: New test. * g++.target/aarch64/sme/streaming_mode_2.C: Likewise. * g++.target/aarch64/sme/keyword_macros_1.C: Likewise. * gcc.target/aarch64/auto-init-1.c: Only expect the call insn to contain 1 (const_int 0), not 2. --- gcc/config/aarch64/aarch64-c.cc | 14 ++ gcc/config/aarch64/aarch64-isa-modes.def | 35 +++ gcc/config/aarch64/aarch64-protos.h | 3 +- gcc/config/aarch64/aarch64.cc | 233 +++++++++++++++--- gcc/config/aarch64/aarch64.h | 24 +- gcc/config/aarch64/aarch64.md | 3 +- gcc/config/aarch64/t-aarch64 | 5 +- .../g++.target/aarch64/sme/aarch64-sme.exp | 40 +++ .../g++.target/aarch64/sme/keyword_macros_1.C | 4 + .../g++.target/aarch64/sme/streaming_mode_1.C | 142 +++++++++++ .../g++.target/aarch64/sme/streaming_mode_2.C | 25 ++ .../gcc.target/aarch64/auto-init-1.c | 3 +- .../gcc.target/aarch64/sme/aarch64-sme.exp | 40 +++ .../gcc.target/aarch64/sme/keyword_macros_1.c | 4 + .../gcc.target/aarch64/sme/streaming_mode_1.c | 130 ++++++++++ .../gcc.target/aarch64/sme/streaming_mode_2.c | 25 ++ 16 files changed, 685 insertions(+), 45 deletions(-) create mode 100644 gcc/config/aarch64/aarch64-isa-modes.def create mode 100644 gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp create mode 100644 gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C create mode 100644 gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C create mode 100644 gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 4085ad840..397745fbd 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -72,6 +72,20 @@ aarch64_define_unconditional_macros (cpp_reader *pfile) builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8); builtin_define ("__GCC_ASM_FLAG_OUTPUTS__"); + + /* Define keyword attributes like __arm_streaming as macros that expand + to the associated [[...]] attribute. Use __extension__ in the attribute + for C, since the [[...]] syntax was only added in C23. */ +#define DEFINE_ARM_KEYWORD_MACRO(NAME) \ + builtin_define_with_value ("__arm_" NAME, \ + lang_GNU_CXX () \ + ? "[[arm::" NAME "]]" \ + : "[[__extension__ arm::" NAME "]]", 0); + + DEFINE_ARM_KEYWORD_MACRO ("streaming"); + DEFINE_ARM_KEYWORD_MACRO ("streaming_compatible"); + +#undef DEFINE_ARM_KEYWORD_MACRO } /* Undefine/redefine macros that depend on the current backend state and may diff --git a/gcc/config/aarch64/aarch64-isa-modes.def b/gcc/config/aarch64/aarch64-isa-modes.def new file mode 100644 index 000000000..5915c98a8 --- /dev/null +++ b/gcc/config/aarch64/aarch64-isa-modes.def @@ -0,0 +1,35 @@ +/* Copyright (C) 2023 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/>. */ + +/* This file defines a set of "ISA modes"; in other words, it defines + various bits of runtime state that control the set of available + instructions or that affect the semantics of instructions in some way. + + Before using #include to read this file, define a macro: + + DEF_AARCH64_ISA_MODE(NAME) + + where NAME is the name of the mode. */ + +/* Indicates that PSTATE.SM is known to be 1 or 0 respectively. These + modes are mutually exclusive. If neither mode is active then the state + of PSTATE.SM is not known at compile time. */ +DEF_AARCH64_ISA_MODE(SM_ON) +DEF_AARCH64_ISA_MODE(SM_OFF) + +#undef DEF_AARCH64_ISA_MODE diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 14a568140..9b03410dc 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -772,6 +772,7 @@ bool aarch64_constant_address_p (rtx); bool aarch64_emit_approx_div (rtx, rtx, rtx); bool aarch64_emit_approx_sqrt (rtx, rtx, bool); tree aarch64_vector_load_decl (tree); +rtx aarch64_gen_callee_cookie (aarch64_feature_flags, arm_pcs); void aarch64_expand_call (rtx, rtx, rtx, bool); bool aarch64_expand_cpymem (rtx *); bool aarch64_expand_setmem (rtx *); @@ -851,7 +852,7 @@ bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT); bool aarch64_use_return_insn_p (void); const char *aarch64_output_casesi (rtx *); -unsigned int aarch64_tlsdesc_abi_id (); +arm_pcs aarch64_tlsdesc_abi_id (); enum aarch64_symbol_type aarch64_classify_symbol (rtx, HOST_WIDE_INT); enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx); enum reg_class aarch64_regno_regclass (unsigned); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 114252a3c..904166b21 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -2985,8 +2985,18 @@ handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree, gcc_unreachable (); } +/* Mutually-exclusive function type attributes for controlling PSTATE.SM. */ +static const struct attribute_spec::exclusions attr_streaming_exclusions[] = +{ + /* Attribute name exclusion applies to: + function, type, variable */ + { "streaming", false, true, false }, + { "streaming_compatible", false, true, false }, + { NULL, false, false, false } +}; + /* Table of machine attributes. */ -TARGET_GNU_ATTRIBUTES (aarch64_attribute_table, +static const attribute_spec aarch64_gnu_attributes[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, affects_type_identity, handler, exclude } */ @@ -2998,7 +3008,31 @@ TARGET_GNU_ATTRIBUTES (aarch64_attribute_table, { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL }, { "SVE type", 3, 3, false, true, false, true, NULL, NULL }, { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL } -}); +}; + +static const scoped_attribute_specs aarch64_gnu_attribute_table = +{ + "gnu", aarch64_gnu_attributes +}; + +static const attribute_spec aarch64_arm_attributes[] = +{ + { "streaming", 0, 0, false, true, true, true, + NULL, attr_streaming_exclusions }, + { "streaming_compatible", 0, 0, false, true, true, true, + NULL, attr_streaming_exclusions }, +}; + +static const scoped_attribute_specs aarch64_arm_attribute_table = +{ + "arm", aarch64_arm_attributes +}; + +static const scoped_attribute_specs *const aarch64_attribute_table[] = +{ + &aarch64_gnu_attribute_table, + &aarch64_arm_attribute_table +}; /* An ISA extension in the co-processor and main instruction set space. */ struct aarch64_option_extension @@ -4301,6 +4335,48 @@ aarch64_fntype_abi (const_tree fntype) return default_function_abi; } +/* Return the state of PSTATE.SM on entry to functions of type FNTYPE. */ + +static aarch64_feature_flags +aarch64_fntype_pstate_sm (const_tree fntype) +{ + if (lookup_attribute ("arm", "streaming", TYPE_ATTRIBUTES (fntype))) + return AARCH64_FL_SM_ON; + + if (lookup_attribute ("arm", "streaming_compatible", + TYPE_ATTRIBUTES (fntype))) + return 0; + + return AARCH64_FL_SM_OFF; +} + +/* Return the ISA mode on entry to functions of type FNTYPE. */ + +static aarch64_feature_flags +aarch64_fntype_isa_mode (const_tree fntype) +{ + return aarch64_fntype_pstate_sm (fntype); +} + +/* Return the state of PSTATE.SM when compiling the body of + function FNDECL. This might be different from the state of + PSTATE.SM on entry. */ + +static aarch64_feature_flags +aarch64_fndecl_pstate_sm (const_tree fndecl) +{ + return aarch64_fntype_pstate_sm (TREE_TYPE (fndecl)); +} + +/* Return the ISA mode that should be used to compile the body of + function FNDECL. */ + +static aarch64_feature_flags +aarch64_fndecl_isa_mode (const_tree fndecl) +{ + return aarch64_fndecl_pstate_sm (fndecl); +} + /* Implement TARGET_COMPATIBLE_VECTOR_TYPES_P. */ static bool @@ -4363,17 +4439,46 @@ aarch64_reg_save_mode (unsigned int regno) gcc_unreachable (); } -/* Implement TARGET_INSN_CALLEE_ABI. */ +/* Given the ISA mode on entry to a callee and the ABI of the callee, + return the CONST_INT that should be placed in an UNSPEC_CALLEE_ABI rtx. */ -const predefined_function_abi & -aarch64_insn_callee_abi (const rtx_insn *insn) +rtx +aarch64_gen_callee_cookie (aarch64_feature_flags isa_mode, arm_pcs pcs_variant) +{ + return gen_int_mode ((unsigned int) isa_mode + | (unsigned int) pcs_variant << AARCH64_NUM_ISA_MODES, + DImode); +} + +/* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return the + callee's ABI. */ + +static const predefined_function_abi & +aarch64_callee_abi (rtx cookie) +{ + return function_abis[UINTVAL (cookie) >> AARCH64_NUM_ISA_MODES]; +} + +/* INSN is a call instruction. Return the CONST_INT stored in its + UNSPEC_CALLEE_ABI rtx. */ + +static rtx +aarch64_insn_callee_cookie (const rtx_insn *insn) { rtx pat = PATTERN (insn); gcc_assert (GET_CODE (pat) == PARALLEL); rtx unspec = XVECEXP (pat, 0, 1); gcc_assert (GET_CODE (unspec) == UNSPEC && XINT (unspec, 1) == UNSPEC_CALLEE_ABI); - return function_abis[INTVAL (XVECEXP (unspec, 0, 0))]; + return XVECEXP (unspec, 0, 0); +} + +/* Implement TARGET_INSN_CALLEE_ABI. */ + +const predefined_function_abi & +aarch64_insn_callee_abi (const rtx_insn *insn) +{ + return aarch64_callee_abi (aarch64_insn_callee_cookie (insn)); } /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. The callee only saves @@ -8117,7 +8222,7 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) || pcum->pcs_variant == ARM_PCS_SVE); if (arg.end_marker_p ()) - return gen_int_mode (pcum->pcs_variant, DImode); + return aarch64_gen_callee_cookie (pcum->isa_mode, pcum->pcs_variant); aarch64_layout_arg (pcum_v, arg); return pcum->aapcs_reg; @@ -8138,9 +8243,15 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, pcum->aapcs_nextnvrn = 0; pcum->aapcs_nextnprn = 0; if (fntype) - pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id (); + { + pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id (); + pcum->isa_mode = aarch64_fntype_isa_mode (fntype); + } else - pcum->pcs_variant = ARM_PCS_AAPCS64; + { + pcum->pcs_variant = ARM_PCS_AAPCS64; + pcum->isa_mode = AARCH64_FL_DEFAULT_ISA_MODE; + } pcum->aapcs_reg = NULL_RTX; pcum->aapcs_arg_processed = false; pcum->aapcs_stack_words = 0; @@ -10627,7 +10738,9 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, } funexp = XEXP (DECL_RTL (function), 0); funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); - rtx callee_abi = gen_int_mode (fndecl_abi (function).id (), DImode); + auto isa_mode = aarch64_fntype_isa_mode (TREE_TYPE (function)); + auto pcs_variant = arm_pcs (fndecl_abi (function).id ()); + rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, pcs_variant); insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi)); SIBLING_CALL_P (insn) = 1; @@ -18618,6 +18731,7 @@ aarch64_override_options (void) SUBTARGET_OVERRIDE_OPTIONS; #endif + auto isa_mode = AARCH64_FL_DEFAULT_ISA_MODE; if (cpu && arch) { /* If both -mcpu and -march are specified, warn if they are not @@ -18630,25 +18744,25 @@ aarch64_override_options (void) } selected_arch = arch->arch; - aarch64_set_asm_isa_flags (arch_isa); + aarch64_set_asm_isa_flags (arch_isa | isa_mode); } else if (cpu) { selected_arch = cpu->arch; - aarch64_set_asm_isa_flags (cpu_isa); + aarch64_set_asm_isa_flags (cpu_isa | isa_mode); } else if (arch) { cpu = &all_cores[arch->ident]; selected_arch = arch->arch; - aarch64_set_asm_isa_flags (arch_isa); + aarch64_set_asm_isa_flags (arch_isa | isa_mode); } else { /* No -mcpu or -march specified, so use the default CPU. */ cpu = &all_cores[TARGET_CPU_DEFAULT]; selected_arch = cpu->arch; - aarch64_set_asm_isa_flags (cpu->flags); + aarch64_set_asm_isa_flags (cpu->flags | isa_mode); } selected_tune = tune ? tune->ident : cpu->ident; @@ -18821,6 +18935,21 @@ aarch64_save_restore_target_globals (tree new_tree) TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); } +/* Return the target_option_node for FNDECL, or the current options + if FNDECL is null. */ + +static tree +aarch64_fndecl_options (tree fndecl) +{ + if (!fndecl) + return target_option_current_node; + + if (tree options = DECL_FUNCTION_SPECIFIC_TARGET (fndecl)) + return options; + + return target_option_default_node; +} + /* Implement TARGET_SET_CURRENT_FUNCTION. Unpack the codegen decisions like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET of the function, if such exists. This function may be called multiple @@ -18830,25 +18959,24 @@ aarch64_save_restore_target_globals (tree new_tree) static void aarch64_set_current_function (tree fndecl) { - if (!fndecl || fndecl == aarch64_previous_fndecl) - return; - - tree old_tree = (aarch64_previous_fndecl - ? DECL_FUNCTION_SPECIFIC_TARGET (aarch64_previous_fndecl) - : NULL_TREE); - - tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + tree old_tree = aarch64_fndecl_options (aarch64_previous_fndecl); + tree new_tree = aarch64_fndecl_options (fndecl); - /* If current function has no attributes but the previous one did, - use the default node. */ - if (!new_tree && old_tree) - new_tree = target_option_default_node; + auto new_isa_mode = (fndecl + ? aarch64_fndecl_isa_mode (fndecl) + : AARCH64_FL_DEFAULT_ISA_MODE); + auto isa_flags = TREE_TARGET_OPTION (new_tree)->x_aarch64_isa_flags; /* If nothing to do, return. #pragma GCC reset or #pragma GCC pop to the default have been handled by aarch64_save_restore_target_globals from aarch64_pragma_target_parse. */ - if (old_tree == new_tree) - return; + if (old_tree == new_tree + && (!fndecl || aarch64_previous_fndecl) + && (isa_flags & AARCH64_FL_ISA_MODES) == new_isa_mode) + { + gcc_assert (AARCH64_ISA_MODE == new_isa_mode); + return; + } aarch64_previous_fndecl = fndecl; @@ -18856,7 +18984,28 @@ aarch64_set_current_function (tree fndecl) cl_target_option_restore (&global_options, &global_options_set, TREE_TARGET_OPTION (new_tree)); + /* The ISA mode can vary based on function type attributes and + function declaration attributes. Make sure that the target + options correctly reflect these attributes. */ + if ((isa_flags & AARCH64_FL_ISA_MODES) != new_isa_mode) + { + auto base_flags = (aarch64_asm_isa_flags & ~AARCH64_FL_ISA_MODES); + aarch64_set_asm_isa_flags (base_flags | new_isa_mode); + + aarch64_override_options_internal (&global_options); + new_tree = build_target_option_node (&global_options, + &global_options_set); + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree; + + tree new_optimize = build_optimization_node (&global_options, + &global_options_set); + if (new_optimize != optimization_default_node) + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; + } + aarch64_save_restore_target_globals (new_tree); + + gcc_assert (AARCH64_ISA_MODE == new_isa_mode); } /* Enum describing the various ways we can handle attributes. @@ -18906,7 +19055,7 @@ aarch64_handle_attr_arch (const char *str) { gcc_assert (tmp_arch); selected_arch = tmp_arch->arch; - aarch64_set_asm_isa_flags (tmp_flags); + aarch64_set_asm_isa_flags (tmp_flags | AARCH64_ISA_MODE); return true; } @@ -18947,7 +19096,7 @@ aarch64_handle_attr_cpu (const char *str) gcc_assert (tmp_cpu); selected_tune = tmp_cpu->ident; selected_arch = tmp_cpu->arch; - aarch64_set_asm_isa_flags (tmp_flags); + aarch64_set_asm_isa_flags (tmp_flags | AARCH64_ISA_MODE); return true; } @@ -19047,7 +19196,7 @@ aarch64_handle_attr_isa_flags (char *str) features if the user wants to handpick specific features. */ if (strncmp ("+nothing", str, 8) == 0) { - isa_flags = 0; + isa_flags = AARCH64_ISA_MODE; str += 8; } @@ -19552,7 +19701,7 @@ aarch64_can_inline_p (tree caller, tree callee) /* Return the ID of the TLDESC ABI, initializing the descriptor if hasn't been already. */ -unsigned int +arm_pcs aarch64_tlsdesc_abi_id () { predefined_function_abi &tlsdesc_abi = function_abis[ARM_PCS_TLSDESC]; @@ -19566,7 +19715,7 @@ aarch64_tlsdesc_abi_id () SET_HARD_REG_BIT (full_reg_clobbers, regno); tlsdesc_abi.initialize (ARM_PCS_TLSDESC, full_reg_clobbers); } - return tlsdesc_abi.id (); + return ARM_PCS_TLSDESC; } /* Return true if SYMBOL_REF X binds locally. */ @@ -27270,22 +27419,26 @@ aarch64_simd_clone_usable (struct cgraph_node *node) static int aarch64_comp_type_attributes (const_tree type1, const_tree type2) { - auto check_attr = [&](const char *name) { - tree attr1 = lookup_attribute (name, TYPE_ATTRIBUTES (type1)); - tree attr2 = lookup_attribute (name, TYPE_ATTRIBUTES (type2)); + auto check_attr = [&](const char *ns, const char *name) { + tree attr1 = lookup_attribute (ns, name, TYPE_ATTRIBUTES (type1)); + tree attr2 = lookup_attribute (ns, name, TYPE_ATTRIBUTES (type2)); if (!attr1 && !attr2) return true; return attr1 && attr2 && attribute_value_equal (attr1, attr2); }; - if (!check_attr ("aarch64_vector_pcs")) + if (!check_attr ("gnu", "aarch64_vector_pcs")) + return 0; + if (!check_attr ("gnu", "Advanced SIMD type")) + return 0; + if (!check_attr ("gnu", "SVE type")) return 0; - if (!check_attr ("Advanced SIMD type")) + if (!check_attr ("gnu", "SVE sizeless type")) return 0; - if (!check_attr ("SVE type")) + if (!check_attr ("arm", "streaming")) return 0; - if (!check_attr ("SVE sizeless type")) + if (!check_attr ("arm", "streaming_compatible")) return 0; return 1; } diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 19b82b4f3..84215c8c3 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -157,10 +157,13 @@ #ifndef USED_FOR_TARGET -/* Define an enum of all features (architectures and extensions). */ +/* Define an enum of all features (ISA modes, architectures and extensions). + The ISA modes must come first. */ enum class aarch64_feature : unsigned char { +#define DEF_AARCH64_ISA_MODE(IDENT) IDENT, #define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) IDENT, #define AARCH64_ARCH(A, B, IDENT, D, E) IDENT, +#include "aarch64-isa-modes.def" #include "aarch64-option-extensions.def" #include "aarch64-arches.def" }; @@ -169,16 +172,34 @@ enum class aarch64_feature : unsigned char { #define HANDLE(IDENT) \ constexpr auto AARCH64_FL_##IDENT \ = aarch64_feature_flags (1) << int (aarch64_feature::IDENT); +#define DEF_AARCH64_ISA_MODE(IDENT) HANDLE (IDENT) #define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) HANDLE (IDENT) #define AARCH64_ARCH(A, B, IDENT, D, E) HANDLE (IDENT) +#include "aarch64-isa-modes.def" #include "aarch64-option-extensions.def" #include "aarch64-arches.def" #undef HANDLE +constexpr auto AARCH64_FL_SM_STATE = AARCH64_FL_SM_ON | AARCH64_FL_SM_OFF; + +constexpr unsigned int AARCH64_NUM_ISA_MODES = (0 +#define DEF_AARCH64_ISA_MODE(IDENT) + 1 +#include "aarch64-isa-modes.def" +); + +/* The mask of all ISA modes. */ +constexpr auto AARCH64_FL_ISA_MODES + = (aarch64_feature_flags (1) << AARCH64_NUM_ISA_MODES) - 1; + +/* The default ISA mode, for functions with no attributes that specify + something to the contrary. */ +constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF; + #endif /* Macros to test ISA flags. */ +#define AARCH64_ISA_MODE (aarch64_isa_flags & AARCH64_FL_ISA_MODES) #define AARCH64_ISA_CRC (aarch64_isa_flags & AARCH64_FL_CRC) #define AARCH64_ISA_CRYPTO (aarch64_isa_flags & AARCH64_FL_CRYPTO) #define AARCH64_ISA_FP (aarch64_isa_flags & AARCH64_FL_FP) @@ -904,6 +925,7 @@ enum arm_pcs typedef struct { enum arm_pcs pcs_variant; + aarch64_feature_flags isa_mode; int aapcs_arg_processed; /* No need to lay out this argument again. */ int aapcs_ncrn; /* Next Core register number. */ int aapcs_nextncrn; /* Next next core register number. */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index c0977a3da..29a665e45 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7017,7 +7017,8 @@ { if (TARGET_SVE) { - rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode); + rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE, + aarch64_tlsdesc_abi_id ()); rtx_insn *call = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi)); RTL_CONST_CALL_P (call) = 1; diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 index 6a21a248f..10cd8f093 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -20,7 +20,10 @@ TM_H += $(srcdir)/config/aarch64/aarch64-fusion-pairs.def \ $(srcdir)/config/aarch64/aarch64-tuning-flags.def \ - $(srcdir)/config/aarch64/aarch64-option-extensions.def + $(srcdir)/config/aarch64/aarch64-option-extensions.def \ + $(srcdir)/config/aarch64/aarch64-cores.def \ + $(srcdir)/config/aarch64/aarch64-isa-modes.def \ + $(srcdir)/config/aarch64/aarch64-arches.def OPTIONS_H_EXTRA += $(srcdir)/config/aarch64/aarch64-cores.def \ $(srcdir)/config/aarch64/aarch64-arches.def diff --git a/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp new file mode 100644 index 000000000..72fcd0bd9 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp @@ -0,0 +1,40 @@ +# Specific regression driver for AArch64 SME. +# Copyright (C) 2009-2023 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/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't an AArch64 target. +if {![istarget aarch64*-*-*] } { + return +} + +# Load support procs. +load_lib g++-dg.exp + +# Initialize `dg'. +dg-init + +aarch64-with-arch-dg-options "" { + # Main loop. + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" "" +} + +# All done. +dg-finish diff --git a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C new file mode 100644 index 000000000..032485adf --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C @@ -0,0 +1,4 @@ +/* { dg-options "-std=c++11 -pedantic-errors" } */ + +void f1 () __arm_streaming; +void f2 () __arm_streaming_compatible; diff --git a/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C new file mode 100644 index 000000000..c3de726e7 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C @@ -0,0 +1,142 @@ +// { dg-options "" } + +void sc_a () [[arm::streaming_compatible]]; +void sc_a (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } } + +void sc_b (); +void sc_b () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" } + +void sc_c () [[arm::streaming_compatible]]; +void sc_c () {} // Inherits attribute from declaration (confusingly). + +void sc_d (); +void sc_d () [[arm::streaming_compatible]] {} // { dg-error "ambiguating new declaration" } + +void sc_e () [[arm::streaming_compatible]] {} +void sc_e (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } } + +void sc_f () {} +void sc_f () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" } + +extern void (*sc_g) (); +extern void (*sc_g) () [[arm::streaming_compatible]]; // { dg-error "conflicting declaration" } + +extern void (*sc_h) () [[arm::streaming_compatible]]; +extern void (*sc_h) (); // { dg-error "conflicting declaration" } + +//---------------------------------------------------------------------------- + +void s_a () [[arm::streaming]]; +void s_a (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } } + +void s_b (); +void s_b () [[arm::streaming]]; // { dg-error "ambiguating new declaration" } + +void s_c () [[arm::streaming]]; +void s_c () {} // Inherits attribute from declaration (confusingly). + +void s_d (); +void s_d () [[arm::streaming]] {} // { dg-error "ambiguating new declaration" } + +void s_e () [[arm::streaming]] {} +void s_e (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } } + +void s_f () {} +void s_f () [[arm::streaming]]; // { dg-error "ambiguating new declaration" } + +extern void (*s_g) (); +extern void (*s_g) () [[arm::streaming]]; // { dg-error "conflicting declaration" } + +extern void (*s_h) () [[arm::streaming]]; +extern void (*s_h) (); // { dg-error "conflicting declaration" } + +//---------------------------------------------------------------------------- + +void mixed_a () [[arm::streaming]]; +void mixed_a () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" } + +void mixed_b () [[arm::streaming_compatible]]; +void mixed_b () [[arm::streaming]]; // { dg-error "ambiguating new declaration" } + +void mixed_c () [[arm::streaming]]; +void mixed_c () [[arm::streaming_compatible]] {} // { dg-error "ambiguating new declaration" } + +void mixed_d () [[arm::streaming_compatible]]; +void mixed_d () [[arm::streaming]] {} // { dg-error "ambiguating new declaration" } + +void mixed_e () [[arm::streaming]] {} +void mixed_e () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" } + +void mixed_f () [[arm::streaming_compatible]] {} +void mixed_f () [[arm::streaming]]; // { dg-error "ambiguating new declaration" } + +extern void (*mixed_g) () [[arm::streaming_compatible]]; +extern void (*mixed_g) () [[arm::streaming]]; // { dg-error "conflicting declaration" } + +extern void (*mixed_h) () [[arm::streaming]]; +extern void (*mixed_h) () [[arm::streaming_compatible]]; // { dg-error "conflicting declaration" } + +//---------------------------------------------------------------------------- + +void contradiction_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +void contradiction_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +int [[arm::streaming_compatible]] int_attr; // { dg-warning "attribute ignored" } +void [[arm::streaming_compatible]] ret_attr (); // { dg-warning "attribute ignored" } +void *[[arm::streaming]] ptr_attr; // { dg-warning "only applies to function types" } + +typedef void s_callback () [[arm::streaming]]; +typedef void sc_callback () [[arm::streaming_compatible]]; + +typedef void contradiction_callback_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +typedef void contradiction_callback_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +struct s { + void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } + void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } +}; + +//---------------------------------------------------------------------------- + +void keyword_ok_1 () __arm_streaming; +void keyword_ok_1 () __arm_streaming; + +void keyword_ok_2 () __arm_streaming; +void keyword_ok_2 () [[arm::streaming]]; + +void keyword_ok_3 () [[arm::streaming]]; +void keyword_ok_3 () __arm_streaming; + +void keyword_ok_4 () __arm_streaming [[arm::streaming]]; + +void keyword_ok_5 () __arm_streaming_compatible; +void keyword_ok_5 () [[arm::streaming_compatible]]; + +//---------------------------------------------------------------------------- + +void keyword_contradiction_1 () __arm_streaming; +void keyword_contradiction_1 (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } } + +void keyword_contradiction_2 (); +void keyword_contradiction_2 () __arm_streaming; // { dg-error "ambiguating new declaration" } + +void keyword_contradiction_3 () __arm_streaming; +void keyword_contradiction_3 () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" } + +void keyword_contradiction_4 () [[arm::streaming_compatible]]; +void keyword_contradiction_4 () __arm_streaming; // { dg-error "ambiguating new declaration" } + +//---------------------------------------------------------------------------- + +struct s1 +{ + virtual void f () [[arm::streaming]]; +}; + +struct s2 : public s1 +{ + void f () override; // { dg-error "conflicting type attributes" } +}; diff --git a/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C new file mode 100644 index 000000000..f2dd2db9b --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C @@ -0,0 +1,25 @@ +// { dg-options "" } + +void sc_fn () [[arm::streaming_compatible]]; +void s_fn () [[arm::streaming]]; +void ns_fn (); + +void (*sc_fn_ptr) () [[arm::streaming_compatible]]; +void (*s_fn_ptr) () [[arm::streaming]]; +void (*ns_fn_ptr) (); + +void +f () +{ + sc_fn_ptr = sc_fn; + sc_fn_ptr = s_fn; // { dg-error "invalid conversion" } + sc_fn_ptr = ns_fn; // { dg-error "invalid conversion" } + + s_fn_ptr = sc_fn; // { dg-error "invalid conversion" } + s_fn_ptr = s_fn; + s_fn_ptr = ns_fn; // { dg-error "invalid conversion" } + + ns_fn_ptr = sc_fn; // { dg-error "invalid conversion" } + ns_fn_ptr = s_fn; // { dg-error "invalid conversion" } + ns_fn_ptr = ns_fn; +} diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c index 0fa470880..45bb02561 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c @@ -29,4 +29,5 @@ void foo() return; } -/* { dg-final { scan-rtl-dump-times "const_int 0" 11 "expand" } } */ +/* Includes 1 for the call instruction and 1 for a nop. */ +/* { dg-final { scan-rtl-dump-times "const_int 0" 10 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp new file mode 100644 index 000000000..c990e5924 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp @@ -0,0 +1,40 @@ +# Specific regression driver for AArch64 SME. +# Copyright (C) 2009-2023 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/>. */ + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't an AArch64 target. +if {![istarget aarch64*-*-*] } { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# Initialize `dg'. +dg-init + +aarch64-with-arch-dg-options "" { + # Main loop. + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" "" +} + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c new file mode 100644 index 000000000..8f1b83676 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c @@ -0,0 +1,4 @@ +/* { dg-options "-std=c90 -pedantic-errors" } */ + +void f1 () __arm_streaming; +void f2 () __arm_streaming_compatible; diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c new file mode 100644 index 000000000..8874b05b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c @@ -0,0 +1,130 @@ +// { dg-options "" } + +void sc_a () [[arm::streaming_compatible]]; +void sc_a (); // { dg-error "conflicting types" } + +void sc_b (); +void sc_b () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +void sc_c () [[arm::streaming_compatible]]; +void sc_c () {} // Inherits attribute from declaration (confusingly). + +void sc_d (); +void sc_d () [[arm::streaming_compatible]] {} // { dg-error "conflicting types" } + +void sc_e () [[arm::streaming_compatible]] {} +void sc_e (); // { dg-error "conflicting types" } + +void sc_f () {} +void sc_f () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +extern void (*sc_g) (); +extern void (*sc_g) () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +extern void (*sc_h) () [[arm::streaming_compatible]]; +extern void (*sc_h) (); // { dg-error "conflicting types" } + +//---------------------------------------------------------------------------- + +void s_a () [[arm::streaming]]; +void s_a (); // { dg-error "conflicting types" } + +void s_b (); +void s_b () [[arm::streaming]]; // { dg-error "conflicting types" } + +void s_c () [[arm::streaming]]; +void s_c () {} // Inherits attribute from declaration (confusingly). + +void s_d (); +void s_d () [[arm::streaming]] {} // { dg-error "conflicting types" } + +void s_e () [[arm::streaming]] {} +void s_e (); // { dg-error "conflicting types" } + +void s_f () {} +void s_f () [[arm::streaming]]; // { dg-error "conflicting types" } + +extern void (*s_g) (); +extern void (*s_g) () [[arm::streaming]]; // { dg-error "conflicting types" } + +extern void (*s_h) () [[arm::streaming]]; +extern void (*s_h) (); // { dg-error "conflicting types" } + +//---------------------------------------------------------------------------- + +void mixed_a () [[arm::streaming]]; +void mixed_a () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +void mixed_b () [[arm::streaming_compatible]]; +void mixed_b () [[arm::streaming]]; // { dg-error "conflicting types" } + +void mixed_c () [[arm::streaming]]; +void mixed_c () [[arm::streaming_compatible]] {} // { dg-error "conflicting types" } + +void mixed_d () [[arm::streaming_compatible]]; +void mixed_d () [[arm::streaming]] {} // { dg-error "conflicting types" } + +void mixed_e () [[arm::streaming]] {} +void mixed_e () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +void mixed_f () [[arm::streaming_compatible]] {} +void mixed_f () [[arm::streaming]]; // { dg-error "conflicting types" } + +extern void (*mixed_g) () [[arm::streaming_compatible]]; +extern void (*mixed_g) () [[arm::streaming]]; // { dg-error "conflicting types" } + +extern void (*mixed_h) () [[arm::streaming]]; +extern void (*mixed_h) () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +//---------------------------------------------------------------------------- + +void contradiction_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +void contradiction_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +int [[arm::streaming_compatible]] int_attr; // { dg-warning "only applies to function types" } +void [[arm::streaming_compatible]] ret_attr (); // { dg-warning "only applies to function types" } +void *[[arm::streaming]] ptr_attr; // { dg-warning "only applies to function types" } + +typedef void s_callback () [[arm::streaming]]; +typedef void sc_callback () [[arm::streaming_compatible]]; + +typedef void contradiction_callback_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +typedef void contradiction_callback_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } +void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } + +struct s { + void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" } + void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" } +}; + +//---------------------------------------------------------------------------- + +void keyword_ok_1 () __arm_streaming; +void keyword_ok_1 () __arm_streaming; + +void keyword_ok_2 () __arm_streaming; +void keyword_ok_2 () [[arm::streaming]]; + +void keyword_ok_3 () [[arm::streaming]]; +void keyword_ok_3 () __arm_streaming; + +void keyword_ok_4 () __arm_streaming [[arm::streaming]]; + +void keyword_ok_5 () __arm_streaming_compatible; +void keyword_ok_5 () [[arm::streaming_compatible]]; + +//---------------------------------------------------------------------------- + +void keyword_contradiction_1 () __arm_streaming; +void keyword_contradiction_1 (); // { dg-error "conflicting types" } + +void keyword_contradiction_2 (); +void keyword_contradiction_2 () __arm_streaming; // { dg-error "conflicting types" } + +void keyword_contradiction_3 () __arm_streaming; +void keyword_contradiction_3 () [[arm::streaming_compatible]]; // { dg-error "conflicting types" } + +void keyword_contradiction_4 () [[arm::streaming_compatible]]; +void keyword_contradiction_4 () __arm_streaming; // { dg-error "conflicting types" } diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c new file mode 100644 index 000000000..e8be0f821 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c @@ -0,0 +1,25 @@ +// { dg-options "" } + +void sc_fn () [[arm::streaming_compatible]]; +void s_fn () [[arm::streaming]]; +void ns_fn (); + +void (*sc_fn_ptr) () [[arm::streaming_compatible]]; +void (*s_fn_ptr) () [[arm::streaming]]; +void (*ns_fn_ptr) (); + +void +f () +{ + sc_fn_ptr = sc_fn; + sc_fn_ptr = s_fn; // { dg-error "incompatible pointer type" } + sc_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" } + + s_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" } + s_fn_ptr = s_fn; + s_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" } + + ns_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" } + ns_fn_ptr = s_fn; // { dg-error "incompatible pointer type" } + ns_fn_ptr = ns_fn; +} -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2