Alfie Richards <[email protected]> writes:
> This changes behavior of target_clones and target_version attributes
> to be inline with what is specified in the Arm C Language Extension.
>
> Notably this changes the scope and signature of multiversioned functions
> to that of the default version, and changes the resolver to be
> created at the implementation of the default version.
>
> This is achieved by changing the C++ front end to no longer resolve any
> non-default version decls in lookup, and by moving dipatching
> for default_target sets to reuse the dispatching logic for target_clones
> in multiple_target.cc.
>
> The dispatching in create_dispatcher_calls is changed for the case of
> a lone annotated default function to change the dispatched symbol to
> be an alias for the mangled default function.
Heh, nice trick. I agree that conceptually it's also a a very clean
solution, but I don't know the cgraph internals well enough to know
whether there might be dragons.
The gcc/*.cc changes look good to me as far as I can review them.
Thanks,
Richard
>
> gcc/ChangeLog:
>
> * cgraphunit.cc (analyze_functions): Add logic for target version
> dependencies.
> * ipa.cc (symbol_table::remove_unreachable_nodes): Ditto.
> * multiple_target.cc (create_dispatcher_calls): Change to support
> target version semantics.
> (ipa_target_clone): Change to dispatch all function sets in
> target_version semantics.
>
> gcc/cp/ChangeLog:
>
> * call.cc (add_candidates): Change to not resolve non-default versions
> in
> target_version semantics.
> * class.cc (resolve_address_of_overloaded_function): Ditto.
> * cp-gimplify.cc (cp_genericize_r): Change logic to not apply for
> target_version semantics.
> * decl.cc (start_decl): Change to mark and therefore mangle all
> target_version decls.
> (start_preparsed_function): Ditto.
> * typeck.cc (cp_build_function_call_vec): Add error for calling
> unresolvable
> non-default node in target_version semantics.
>
> gcc/testsuite/ChangeLog:
>
> * g++.target/aarch64/mv-1.C: Change for target_version semantics.
> * 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-symbols3.C: Ditto.
> * g++.target/riscv/mv-symbols2.C: Ditto.
> * g++.target/riscv/mv-symbols3.C: Ditto.
> * g++.target/riscv/mv-symbols4.C: Ditto.
> * g++.target/riscv/mv-symbols5.C: Ditto.
> * g++.target/riscv/mvc-symbols3.C: Ditto.
> * g++.target/aarch64/mv-symbols10.C: New test.
> * g++.target/aarch64/mv-symbols11.C: New test.
> * g++.target/aarch64/mv-symbols12.C: New test.
> * g++.target/aarch64/mv-symbols13.C: New test.
> * g++.target/aarch64/mv-symbols6.C: New test.
> * g++.target/aarch64/mv-symbols7.C: New test.
> * g++.target/aarch64/mv-symbols8.C: New test.
> * g++.target/aarch64/mv-symbols9.C: New test.
> ---
> gcc/cgraphunit.cc | 9 +++
> gcc/cp/call.cc | 10 +++
> gcc/cp/class.cc | 13 +++-
> gcc/cp/cp-gimplify.cc | 11 ++-
> gcc/cp/decl.cc | 14 ++++
> gcc/cp/typeck.cc | 10 +++
> gcc/ipa.cc | 11 +++
> gcc/multiple_target.cc | 73 ++++++++++++++++---
> gcc/testsuite/g++.target/aarch64/mv-1.C | 4 +
> .../g++.target/aarch64/mv-symbols10.C | 27 +++++++
> .../g++.target/aarch64/mv-symbols11.C | 30 ++++++++
> .../g++.target/aarch64/mv-symbols12.C | 28 +++++++
> .../g++.target/aarch64/mv-symbols13.C | 28 +++++++
> .../g++.target/aarch64/mv-symbols2.C | 12 +--
> .../g++.target/aarch64/mv-symbols3.C | 6 +-
> .../g++.target/aarch64/mv-symbols4.C | 6 +-
> .../g++.target/aarch64/mv-symbols5.C | 6 +-
> .../g++.target/aarch64/mv-symbols6.C | 25 +++++++
> .../g++.target/aarch64/mv-symbols7.C | 48 ++++++++++++
> .../g++.target/aarch64/mv-symbols8.C | 46 ++++++++++++
> .../g++.target/aarch64/mv-symbols9.C | 43 +++++++++++
> .../g++.target/aarch64/mvc-symbols3.C | 12 +--
> gcc/testsuite/g++.target/riscv/mv-symbols2.C | 12 +--
> gcc/testsuite/g++.target/riscv/mv-symbols3.C | 6 +-
> gcc/testsuite/g++.target/riscv/mv-symbols4.C | 6 +-
> gcc/testsuite/g++.target/riscv/mv-symbols5.C | 6 +-
> gcc/testsuite/g++.target/riscv/mvc-symbols3.C | 12 +--
> 27 files changed, 456 insertions(+), 58 deletions(-)
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols10.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols11.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols12.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols13.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols6.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols7.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols8.C
> create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols9.C
>
> diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
> index 82f205488e9..876f5b907bd 100644
> --- a/gcc/cgraphunit.cc
> +++ b/gcc/cgraphunit.cc
> @@ -1264,6 +1264,15 @@ analyze_functions (bool first_time)
> if (!cnode->analyzed)
> cnode->analyze ();
>
> + /* A reference to a default node in a function set implies a
> + reference to all versions in the set. */
> + cgraph_function_version_info *node_v = cnode->function_version ();
> + if (node_v && is_function_default_version (node->decl))
> + for (cgraph_function_version_info *fvi = node_v->next;
> + fvi;
> + fvi = fvi->next)
> + enqueue_node (fvi->this_node);
> +
> for (edge = cnode->callees; edge; edge = edge->next_callee)
> if (edge->callee->definition
> && (!DECL_EXTERNAL (edge->callee->decl)
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 03130f80f86..cc8f2b17297 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -6847,6 +6847,16 @@ add_candidates (tree fns, tree first_arg, const
> vec<tree, va_gc> *args,
> continue;
> }
>
> + /* Do not resolve any non-default function. Only the default version
> + is resolvable (for the target_version attribute semantics.) */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && TREE_CODE (fn) == FUNCTION_DECL
> + && !is_function_default_version (fn))
> + {
> + add_ignored_candidate (candidates, fn);
> + continue;
> + }
> +
> if (TREE_CODE (fn) == TEMPLATE_DECL)
> add_template_candidate (candidates,
> fn,
> diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
> index df67ec34273..ea19604ede2 100644
> --- a/gcc/cp/class.cc
> +++ b/gcc/cp/class.cc
> @@ -8845,6 +8845,13 @@ resolve_address_of_overloaded_function (tree
> target_type,
> if (!constraints_satisfied_p (fn))
> continue;
>
> + /* For target_version semantics, never resolve a non-default
> + version. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && TREE_CODE (fn) == FUNCTION_DECL
> + && !is_function_default_version (fn))
> + continue;
> +
> if (undeduced_auto_decl (fn))
> {
> /* Force instantiation to do return type deduction. */
> @@ -9070,8 +9077,10 @@ resolve_address_of_overloaded_function (tree
> target_type,
> /* If a pointer to a function that is multi-versioned is requested, the
> pointer to the dispatcher function is returned instead. This works
> well because indirectly calling the function will dispatch the right
> - function version at run-time. */
> - if (DECL_FUNCTION_VERSIONED (fn))
> + function version at run-time.
> + This is done at multiple_target.cc for target_version semantics. */
> +
> + if (DECL_FUNCTION_VERSIONED (fn) && TARGET_HAS_FMV_TARGET_ATTRIBUTE)
> {
> fn = get_function_version_dispatcher (fn);
> if (fn == NULL)
> diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> index 45f4e27b8b7..9310205378f 100644
> --- a/gcc/cp/cp-gimplify.cc
> +++ b/gcc/cp/cp-gimplify.cc
> @@ -2157,13 +2157,16 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees,
> void *data)
> returns the function with the highest target priority, that is,
> the version that will checked for dispatching first. If this
> version is inlinable, a direct call to this version can be made
> - otherwise the call should go through the dispatcher. */
> + otherwise the call should go through the dispatcher.
> + This is done at multiple_target.cc for target_version semantics. */
> {
> tree fn = cp_get_callee_fndecl_nofold (stmt);
> - if (fn && DECL_FUNCTION_VERSIONED (fn)
> + if (TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && fn
> + && DECL_FUNCTION_VERSIONED (fn)
> && (current_function_decl == NULL
> - || !targetm.target_option.can_inline_p (current_function_decl,
> - fn)))
> + || !targetm.target_option.can_inline_p
> + (current_function_decl, fn)))
> if (tree dis = get_function_version_dispatcher (fn))
> {
> mark_versions_used (dis);
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 4edf5435c35..18a03a88aa4 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -6163,6 +6163,13 @@ start_decl (const cp_declarator *declarator,
>
> was_public = TREE_PUBLIC (decl);
>
> + /* For target_version semantics, mark any annotated function as versioned
> + so that it gets mangled even when on its own in a TU. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && TREE_CODE (decl) == FUNCTION_DECL
> + && lookup_attribute ("target_version", DECL_ATTRIBUTES (decl)))
> + maybe_mark_function_versioned (decl);
> +
> if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL)
> && current_function_decl)
> {
> @@ -18782,6 +18789,13 @@ start_preparsed_function (tree decl1, tree attrs,
> int flags)
> if (!DECL_OMP_DECLARE_REDUCTION_P (decl1))
> start_lambda_scope (decl1);
>
> + /* For target_version semantics, mark any annotated function as versioned
> + so that it gets mangled even when on its own in a TU. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && TREE_CODE (decl1) == FUNCTION_DECL
> + && lookup_attribute ("target_version", DECL_ATTRIBUTES (decl1)))
> + maybe_mark_function_versioned (decl1);
> +
> return true;
> }
>
> diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> index a9c32ff930d..ce95273f176 100644
> --- a/gcc/cp/typeck.cc
> +++ b/gcc/cp/typeck.cc
> @@ -4439,6 +4439,16 @@ cp_build_function_call_vec (tree function, vec<tree,
> va_gc> **params,
> return error_mark_node;
> fndecl = function;
>
> + /* For target_version semantics, the funciton set cannot be called
> + if there is no default version in scope. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && !is_function_default_version (fndecl))
> + {
> + if (complain & tf_error)
> + error ("no default version in scope");
> + return error_mark_node;
> + }
> +
> /* Convert anything with function type to a pointer-to-function. */
> if (DECL_MAIN_P (function))
> {
> diff --git a/gcc/ipa.cc b/gcc/ipa.cc
> index 8a7b067a526..dea22ea0b49 100644
> --- a/gcc/ipa.cc
> +++ b/gcc/ipa.cc
> @@ -433,6 +433,17 @@ symbol_table::remove_unreachable_nodes (FILE *file)
> e, &first, &reachable);
> }
> }
> +
> + /* A reference to the default node implies use of all the other
> + versions (they get used in the function resolver made later
> + in multiple_target.cc) */
> + cgraph_function_version_info *node_v = cnode->function_version ();
> + if (node_v && is_function_default_version (node->decl))
> + for (cgraph_function_version_info *fvi = node_v->next;
> + fvi;
> + fvi = fvi->next)
> + enqueue_node (fvi->this_node, &first, &reachable);
> +
> for (e = cnode->callees; e; e = e->next_callee)
> {
> symtab_node *body = e->callee->function_symbol ();
> diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc
> index cd7570a9aad..839c6a4906a 100644
> --- a/gcc/multiple_target.cc
> +++ b/gcc/multiple_target.cc
> @@ -58,8 +58,15 @@ replace_function_decl (tree *op, int *walk_subtrees, void
> *data)
> return NULL;
> }
>
> -/* If the call in NODE has multiple target attribute with multiple fields,
> - replace it with dispatcher call and create dispatcher (once). */
> +/* In target FMV attributes, if the call in NODE has multiple target
> attribute
> + with multiple fields, replace it with calls to the dispatched symbol and
> + create the disptacher body (once).
> +
> + In target_version semantics, if it is a lone annotated default, then
> + the dispatched symbol is changed to be an alias and no resolver is
> + required. Otherwise, redirect all calls and references to the dispatched
> + symbol, but only create the resolver body if the default version is
> + implemented. */
>
> static void
> create_dispatcher_calls (struct cgraph_node *node)
> @@ -90,13 +97,48 @@ create_dispatcher_calls (struct cgraph_node *node)
>
> cgraph_node *inode = cgraph_node::get (idecl);
> gcc_assert (inode);
> - tree resolver_decl = targetm.generate_version_dispatcher_body (inode);
> -
> - /* Update aliases. */
> - inode->alias = true;
> - inode->alias_target = resolver_decl;
> - if (!inode->analyzed)
> - inode->resolve_alias (cgraph_node::get (resolver_decl));
> + cgraph_function_version_info *inode_info = inode->function_version ();
> + gcc_assert (inode_info);
> +
> + tree resolver_decl = NULL;
> +
> + /* For target_version semantics, if there is a lone default declaration
> + it needs to be mangled, with an alias from the dispatched symbol to the
> + default version. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
> + && TREE_STATIC (node->decl)
> + && inode_info->next
> + && !inode_info->next->next)
> + {
> + inode->alias = true;
> + inode->alias_target = inode_info->next->this_node->decl;
> + inode->externally_visible = true;
> + if (!inode->analyzed)
> + inode->resolve_alias
> + (cgraph_node::get (inode_info->next->this_node->decl));
> +
> + DECL_ATTRIBUTES (idecl)
> + = make_attribute ("alias",
> + IDENTIFIER_POINTER
> + (DECL_ASSEMBLER_NAME
> + (inode_info->next->this_node->decl)),
> + DECL_ATTRIBUTES (node->decl));
> + TREE_USED (idecl) = true;
> + DECL_EXTERNAL (idecl) = false;
> + TREE_STATIC (idecl) = true;
> + return;
> + }
> + /* In target_version semantics, only create the resolver if the
> + default node is implemented. */
> + else if (TARGET_HAS_FMV_TARGET_ATTRIBUTE || TREE_STATIC (node->decl))
> + {
> + resolver_decl = targetm.generate_version_dispatcher_body (inode);
> + /* Update aliases. */
> + inode->alias = true;
> + inode->alias_target = resolver_decl;
> + if (!inode->analyzed)
> + inode->resolve_alias (cgraph_node::get (resolver_decl));
> + }
>
> auto_vec<cgraph_edge *> edges_to_redirect;
> /* We need to capture the references by value rather than just pointers to
> them
> @@ -426,9 +468,20 @@ ipa_target_clone (void)
> auto_vec<cgraph_node *> to_dispatch;
>
> FOR_EACH_FUNCTION (node)
> - if (expand_target_clones (node, node->definition))
> + /* Expand all target versions. */
> + if (expand_target_clones (node, node->definition)
> + && TARGET_HAS_FMV_TARGET_ATTRIBUTE)
> + /* In non target_version semantics, dispatch all target clone sets. */
> to_dispatch.safe_push (node);
>
> + /* In target_version semantics dispatch all FMV function sets with a
> default
> + implementation. */
> + if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE)
> + FOR_EACH_FUNCTION (node)
> + if (is_function_default_version (node->decl)
> + && DECL_FUNCTION_VERSIONED (node->decl))
> + to_dispatch.safe_push (node);
> +
> for (unsigned i = 0; i < to_dispatch.length (); i++)
> create_dispatcher_calls (to_dispatch[i]);
>
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-1.C
> b/gcc/testsuite/g++.target/aarch64/mv-1.C
> index b10037f1b9b..93b8a136587 100644
> --- a/gcc/testsuite/g++.target/aarch64/mv-1.C
> +++ b/gcc/testsuite/g++.target/aarch64/mv-1.C
> @@ -37,3 +37,7 @@ int bar()
> /* { dg-final { scan-assembler-times "\n_Z3foov\._Mrng:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\._MrngMflagm:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\._Mflagm:\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols10.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols10.C
> new file mode 100644
> index 00000000000..92d4ab617d8
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols10.C
> @@ -0,0 +1,27 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +__attribute__ ((target_version ("default"))) void
> +foo (int a = 3);
> +
> +__attribute__ ((target_version ("sve"))) void
> +foo (int a = 4);
> +
> +void bar() {
> + foo();
> +}
> +
> +__attribute__ ((target_version ("sve"))) void
> +foo2 (int a = 6);
> +
> +__attribute__ ((target_version ("default"))) void
> +foo2 (int a = 5);
> +
> +void bar2() {
> + foo2();
> +}
> +
> +
> +/* { dg-final { scan-assembler-times "\n\tmov\tw\[0-9\]\+, 3\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tmov\tw\[0-9\]\+, 5\n" 1 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols11.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols11.C
> new file mode 100644
> index 00000000000..dadde22622e
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols11.C
> @@ -0,0 +1,30 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +__attribute__ ((target_version ("default"))) int
> +foo () { return 1; }
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo () { return 3; }
> +
> +int (*test)();
> +
> +void bar ()
> +{
> + test = foo;
> +}
> +
> +__attribute__ ((target_version ("default"))) int
> +foo2 ();
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo2 ();
> +
> +void bar2 ()
> +{
> + test = foo2;
> +}
> +
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, _Z3foov\n" 1 } }
> */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, _Z4foo2v\n" 1 } }
> */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols12.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols12.C
> new file mode 100644
> index 00000000000..d78ee4b91c5
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols12.C
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +int foo () {
> + return 1;
> +}
> +
> +void
> +bar ()
> +{
> + foo ();
> +}
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +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\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\._Mdotprod\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\.default\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols13.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols13.C
> new file mode 100644
> index 00000000000..997b9bad6d6
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols13.C
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +int foo () {
> + return 1;
> +}
> +
> +void bar ()
> +{
> + int (*test)() = foo;
> +
> + test();
> +}
> +
> +__attribute__ ((target_version ("dotprod"))) int 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\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\._Mdotprod\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\.default\n" 1 } } */
> +
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, _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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols2.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C
> index 6da88ddfb48..55f2d48f5e4 100644
> --- a/gcc/testsuite/g++.target/aarch64/mv-symbols2.C
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C
> @@ -41,13 +41,13 @@ int foo (int)
> /* { 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_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" 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 } } */
> +/* { 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/mv-symbols3.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C
> index 5dd7b49be2a..6ba02a2aae9 100644
> --- a/gcc/testsuite/g++.target/aarch64/mv-symbols3.C
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C
> @@ -29,10 +29,10 @@ int bar()
> /* { 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_Z3foov\.resolver:\n" 0 } } */
> /* { 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\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols4.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C
> index 4b25d17cc15..cc013c47848 100644
> --- a/gcc/testsuite/g++.target/aarch64/mv-symbols4.C
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C
> @@ -44,6 +44,6 @@ int bar()
> /* { 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 } } */
> +/* { 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/mv-symbols5.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C
> index fac00b20313..1396ca379e4 100644
> --- a/gcc/testsuite/g++.target/aarch64/mv-symbols5.C
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C
> @@ -44,10 +44,10 @@ int bar()
> /* { 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_Z3foov\.resolver:\n" 0 } } */
> /* { 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\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" 1 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols6.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols6.C
> new file mode 100644
> index 00000000000..e53d88d8bf3
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols6.C
> @@ -0,0 +1,25 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +__attribute__ ((target_version ("default"))) int
> +foo ()
> +{
> + return 1;
> +}
> +
> +int bar()
> +{
> + return foo();
> +}
> +
> +/* It is not overly clear what the correct behaviour is in this case.
> + This test serves more as a test of consistency for this case rather
> + than a test of correctness. */
> +
> +/* { dg-final { scan-assembler-times "\n_Z3foov:\n" 0 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
> +/* { dg-final { scan-assembler-times "bl\t_Z3foov.default\n" 1 } } */
> +/* { dg-final { scan-assembler-times ".global\t_Z3foov\n" 1 } } */
> +/* { dg-final { scan-assembler-times ".set\t_Z3foov,_Z3foov.default\n" 1 } }
> */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols7.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols7.C
> new file mode 100644
> index 00000000000..3998adb54a7
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols7.C
> @@ -0,0 +1,48 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo ();
> +
> +__attribute__ ((target_version ("sve+sve2"))) int
> +foo ();
> +
> +__attribute__ ((target_version ("default"))) int
> +foo ();
> +
> +__attribute__ ((target_version ("sve+sve2"))) int
> +foo ()
> +{
> + return 5;
> +}
> +__attribute__ ((target_version ("dotprod"))) int
> +foo ()
> +{
> + return 3;
> +}
> +__attribute__ ((target_version ("default"))) int
> +foo ()
> +{
> + return 1;
> +}
> +
> +int
> +bar ()
> +{
> + return foo ();
> +}
> +
> +/* { 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\tadrp\tx\[0-9\]+,
> _Z3foov\._MsveMsve2\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\._Mdotprod\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\.default\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols8.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols8.C
> new file mode 100644
> index 00000000000..5983bbd6925
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols8.C
> @@ -0,0 +1,46 @@
> +/* { dg-do compile } */
> +/* { dg-require-ifunc "" } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo ();
> +__attribute__ ((target_version ("sve+sve2"))) int
> +foo ();
> +
> +int
> +foo ()
> +{
> + return 1;
> +}
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo ()
> +{
> + return 3;
> +}
> +__attribute__ ((target_version ("sve+sve2"))) int
> +foo ()
> +{
> + return 5;
> +}
> +
> +int
> +bar ()
> +{
> + return foo ();
> +}
> +
> +/* { 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\tadrp\tx\[0-9\]+,
> _Z3foov\._MsveMsve2\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\._Mdotprod\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\.default\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols9.C
> b/gcc/testsuite/g++.target/aarch64/mv-symbols9.C
> new file mode 100644
> index 00000000000..bfad9bb5850
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/mv-symbols9.C
> @@ -0,0 +1,43 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0" } */
> +/* { dg-additional-options "-Wno-experimental-fmv-target" } */
> +
> +int
> +foo ();
> +
> +int
> +foo ()
> +{
> + return 1;
> +}
> +
> +__attribute__ ((target_version ("dotprod"))) int
> +foo ()
> +{
> + return 3;
> +}
> +__attribute__ ((target_version ("sve+sve2"))) int
> +foo ()
> +{
> + return 5;
> +}
> +
> +int
> +bar ()
> +{
> + return foo ();
> +}
> +
> +/* { 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\tadrp\tx\[0-9\]+,
> _Z3foov\._MsveMsve2\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\._Mdotprod\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+,
> _Z3foov\.default\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 } } */
> diff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C
> b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C
> index 350a5586643..2a315d2db5c 100644
> --- a/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C
> +++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C
> @@ -22,15 +22,15 @@ int bar(int 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_Z3foov\.resolver:\n" 0 } } */
> /* { 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\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" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
> /* { 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 } } */
> +/* { 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/riscv/mv-symbols2.C
> b/gcc/testsuite/g++.target/riscv/mv-symbols2.C
> index 43fa1502b7d..8a5c5a0bc9f 100644
> --- a/gcc/testsuite/g++.target/riscv/mv-symbols2.C
> +++ b/gcc/testsuite/g++.target/riscv/mv-symbols2.C
> @@ -47,15 +47,15 @@ int foo (int)
> /* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\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\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\.arch__v:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\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 } } */
> +/* { 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/riscv/mv-symbols3.C
> b/gcc/testsuite/g++.target/riscv/mv-symbols3.C
> index 4dc81cf7395..fa2d3371e87 100644
> --- a/gcc/testsuite/g++.target/riscv/mv-symbols3.C
> +++ b/gcc/testsuite/g++.target/riscv/mv-symbols3.C
> @@ -36,10 +36,10 @@ int bar()
> /* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\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\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\.arch__v:\n" 0 } } */
> diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols4.C
> b/gcc/testsuite/g++.target/riscv/mv-symbols4.C
> index b0ed16a5eda..fa84e25900c 100644
> --- a/gcc/testsuite/g++.target/riscv/mv-symbols4.C
> +++ b/gcc/testsuite/g++.target/riscv/mv-symbols4.C
> @@ -50,7 +50,7 @@ int bar()
> /* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\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 } } */
> +/* { 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/riscv/mv-symbols5.C
> b/gcc/testsuite/g++.target/riscv/mv-symbols5.C
> index f4c6b294e0f..5551f5da554 100644
> --- a/gcc/testsuite/g++.target/riscv/mv-symbols5.C
> +++ b/gcc/testsuite/g++.target/riscv/mv-symbols5.C
> @@ -48,10 +48,10 @@ int bar()
> /* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\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\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\.arch__v:\n" 1 } } */
> diff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols3.C
> b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C
> index b36c3fa7a95..256fec7d368 100644
> --- a/gcc/testsuite/g++.target/riscv/mvc-symbols3.C
> +++ b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C
> @@ -28,15 +28,15 @@ int bar(int x)
> /* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\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\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\.arch__v:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */
> -/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */
> +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */
> /* { dg-final { scan-assembler-times "\n\tcall\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 } } */
> +/* { 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 } } */