From: Andrew Carlotti Date: Wed, 31 Jan 2024 16:28:12 +0000 (+0000) Subject: aarch64: Fix function multiversioning mangling X-Git-Tag: basepoints/gcc-15~1310 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8ec2f1922a14ee3636840d1ebc1c40d26e6043a4;p=thirdparty%2Fgcc.git aarch64: Fix function multiversioning mangling It would be neater if the middle end for target_clones used a target hook for version name mangling, so we only do version name mangling once. However, that would require more intrusive refactoring that will have to wait till Stage 1. gcc/ChangeLog: * config/aarch64/aarch64.cc (aarch64_mangle_decl_assembler_name): Move before new caller, and add ".default" suffix. (get_suffixed_assembler_name): New. (make_resolver_func): Use get_suffixed_assembler_name. (aarch64_generate_version_dispatcher_body): Redo name mangling. gcc/testsuite/ChangeLog: * g++.target/aarch64/mv-symbols1.C: New test. * g++.target/aarch64/mv-symbols2.C: Ditto. * g++.target/aarch64/mv-symbols3.C: Ditto. * g++.target/aarch64/mv-symbols4.C: Ditto. * g++.target/aarch64/mv-symbols5.C: Ditto. * g++.target/aarch64/mvc-symbols1.C: Ditto. * g++.target/aarch64/mvc-symbols2.C: Ditto. * g++.target/aarch64/mvc-symbols3.C: Ditto. * g++.target/aarch64/mvc-symbols4.C: Ditto. --- diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index bdbfe2afb69a..32eae49d4e95 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -19872,6 +19872,62 @@ build_ifunc_arg_type () return pointer_type; } +/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME, to add function multiversioning + suffixes. */ + +tree +aarch64_mangle_decl_assembler_name (tree decl, tree id) +{ + /* For function version, add the target suffix to the assembler name. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_FUNCTION_VERSIONED (decl)) + { + aarch64_fmv_feature_mask feature_mask = get_feature_mask_for_version (decl); + + std::string name = IDENTIFIER_POINTER (id); + + /* For the default version, append ".default". */ + if (feature_mask == 0ULL) + { + name += ".default"; + return get_identifier (name.c_str()); + } + + name += "._"; + + for (int i = 0; i < FEAT_MAX; i++) + { + if (feature_mask & aarch64_fmv_feature_data[i].feature_mask) + { + name += "M"; + name += aarch64_fmv_feature_data[i].name; + } + } + + if (DECL_ASSEMBLER_NAME_SET_P (decl)) + SET_DECL_RTL (decl, NULL); + + id = get_identifier (name.c_str()); + } + return id; +} + +/* Return an identifier for the base assembler name of a versioned function. + This is computed by taking the default version's assembler name, and + stripping off the ".default" suffix if it's already been appended. */ + +static tree +get_suffixed_assembler_name (tree default_decl, const char *suffix) +{ + std::string name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (default_decl)); + + auto size = name.size (); + if (size >= 8 && name.compare (size - 8, 8, ".default") == 0) + name.resize (size - 8); + name += suffix; + return get_identifier (name.c_str()); +} + /* Make the resolver function decl to dispatch the versions of a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is ifunc alias that will point to the created resolver. Create an @@ -19885,8 +19941,9 @@ make_resolver_func (const tree default_decl, { tree decl, type, t; - /* Create resolver function name based on default_decl. */ - tree decl_name = clone_function_name (default_decl, "resolver"); + /* Create resolver function name based on default_decl. We need to remove an + existing ".default" suffix if this has already been appended. */ + tree decl_name = get_suffixed_assembler_name (default_decl, ".resolver"); const char *resolver_name = IDENTIFIER_POINTER (decl_name); /* The resolver function should have signature @@ -20233,6 +20290,28 @@ aarch64_generate_version_dispatcher_body (void *node_p) dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb); cgraph_edge::rebuild_edges (); pop_cfun (); + + /* Fix up symbol names. First we need to obtain the base name, which may + have already been mangled. */ + tree base_name = get_suffixed_assembler_name (default_ver_decl, ""); + + /* We need to redo the version mangling on the non-default versions for the + target_clones case. Redoing the mangling for the target_version case is + redundant but does no harm. We need to skip the default version, because + expand_clones will append ".default" later; fortunately that suffix is the + one we want anyway. */ + for (versn_info = node_version_info->next->next; versn_info; + versn_info = versn_info->next) + { + tree version_decl = versn_info->this_node->decl; + tree name = aarch64_mangle_decl_assembler_name (version_decl, + base_name); + symtab->change_decl_assembler_name (version_decl, name); + } + + /* We also need to use the base name for the ifunc declaration. */ + symtab->change_decl_assembler_name (node->decl, base_name); + return resolver_decl; } @@ -20345,42 +20424,6 @@ aarch64_common_function_versions (tree fn1, tree fn2) return (aarch64_compare_version_priority (fn1, fn2) != 0); } -/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME, to add function multiversioning - suffixes. */ - -tree -aarch64_mangle_decl_assembler_name (tree decl, tree id) -{ - /* For function version, add the target suffix to the assembler name. */ - if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_FUNCTION_VERSIONED (decl)) - { - aarch64_fmv_feature_mask feature_mask = get_feature_mask_for_version (decl); - - /* No suffix for the default version. */ - if (feature_mask == 0ULL) - return id; - - std::string name = IDENTIFIER_POINTER (id); - name += "._"; - - for (int i = 0; i < FEAT_MAX; i++) - { - if (feature_mask & aarch64_fmv_feature_data[i].feature_mask) - { - name += "M"; - name += aarch64_fmv_feature_data[i].name; - } - } - - if (DECL_ASSEMBLER_NAME_SET_P (decl)) - SET_DECL_RTL (decl, NULL); - - id = get_identifier (name.c_str()); - } - return id; -} - /* Implement TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. Use an opt-out rather than an opt-in list. */ diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols1.C b/gcc/testsuite/g++.target/aarch64/mv-symbols1.C new file mode 100644 index 000000000000..53e0abcd9b43 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols1.C @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +int foo () +{ + return 1; +} + +__attribute__((target_version("dotprod"))) +int foo () +{ + return 3; +} +__attribute__((target_version("sve+sve2"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("sve+sve2"))) +int foo (int) +{ + return 6; +} + +__attribute__((target_version("dotprod"))) +int foo (int) +{ + return 4; +} + +int foo (int) +{ + return 2; +} + + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols2.C b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C new file mode 100644 index 000000000000..f0c7967a97ab --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_version("default"))) +int foo () +{ + return 1; +} + +__attribute__((target_version("dotprod"))) +int foo () +{ + return 3; +} +__attribute__((target_version("sve+sve2"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("sve+sve2"))) +int foo (int) +{ + return 6; +} + +__attribute__((target_version("dotprod"))) +int foo (int) +{ + return 4; +} + +__attribute__((target_version("default"))) +int foo (int) +{ + return 2; +} + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols3.C b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C new file mode 100644 index 000000000000..3d30e27deb8b --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_version("default"))) +int foo (); + +__attribute__((target_version("dotprod"))) +int foo (); + +__attribute__((target_version("sve+sve2"))) +int foo (); + +__attribute__((target_version("default"))) +int foo (int); + +__attribute__((target_version("dotprod"))) +int foo (int); + +__attribute__((target_version("sve+sve2"))) +int foo (int); + +int bar() +{ + return foo (); +} + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols4.C b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C new file mode 100644 index 000000000000..73e3279ec314 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_version("default"))) +int foo () +{ + return 1; +} + +__attribute__((target_version("dotprod"))) +int foo (); + +__attribute__((target_version("sve+sve2"))) +int foo (); + +__attribute__((target_version("default"))) +int foo (int) +{ + return 2; +} + +__attribute__((target_version("dotprod"))) +int foo (int); + +__attribute__((target_version("sve+sve2"))) +int foo (int); + + +int bar() +{ + return foo (); +} + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols5.C b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C new file mode 100644 index 000000000000..05d1379f53ec --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_version("default"))) +int foo (); + +__attribute__((target_version("dotprod"))) +int foo () +{ + return 3; +} +__attribute__((target_version("sve+sve2"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("default"))) +int foo (int); + +__attribute__((target_version("dotprod"))) +int foo (int) +{ + return 4; +} + +__attribute__((target_version("sve+sve2"))) +int foo (int) +{ + return 6; +} + + +int bar() +{ + return foo (); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols1.C b/gcc/testsuite/g++.target/aarch64/mvc-symbols1.C new file mode 100644 index 000000000000..2dd7c79f16cf --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols1.C @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_clones("default", "dotprod", "sve+sve2"))) +int foo () +{ + return 1; +} + +__attribute__((target_clones("sve+sve2", "dotprod", "default"))) +int foo (int) +{ + return 2; +} + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols2.C b/gcc/testsuite/g++.target/aarch64/mvc-symbols2.C new file mode 100644 index 000000000000..75b9c126dd8c --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols2.C @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_clones("default", "dotprod", "sve+sve2"))) +int foo () +{ + return 1; +} + +__attribute__((target_clones("sve+sve2", "dotprod", "default"))) +int foo (int) +{ + return 2; +} + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C new file mode 100644 index 000000000000..82e777c8fc6e --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_clones("default", "dotprod", "sve+sve2"))) +int foo (); + +__attribute__((target_clones("sve+sve2", "dotprod", "default"))) +int foo (int); + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tbl\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols4.C b/gcc/testsuite/g++.target/aarch64/mvc-symbols4.C new file mode 100644 index 000000000000..6c86ae61e5fa --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols4.C @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +__attribute__((target_clones("default", "dotprod", "sve+sve2"))) +int foo (); + +__attribute__((target_clones("sve+sve2", "dotprod", "default"))) +int foo (int); + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._Mdotprod:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\._MsveMsve2:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, %gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */