{"id":2226679,"url":"http://patchwork.ozlabs.org/api/patches/2226679/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.5@forge-stage.sourceware.org/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","name":"GNU Compiler Collection","link_name":"gcc","list_id":"gcc-patches.gcc.gnu.org","list_email":"gcc-patches@gcc.gnu.org","web_url":null,"scm_url":null,"webscm_url":null,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.5@forge-stage.sourceware.org>","list_archive_url":null,"date":"2026-04-22T18:21:53","name":"[v1,05/13] fmv: Change target_version semantics to follow ACLE specification.","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"b9d99a5563a8c5ea476e6e14f988040f82395267","submitter":{"id":93228,"url":"http://patchwork.ozlabs.org/api/people/93228/?format=json","name":"\\\"alfie.richards via Sourceware Forge\\\"","email":"forge-bot+alfie.richards@forge-stage.sourceware.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.5@forge-stage.sourceware.org/mbox/","series":[{"id":501072,"url":"http://patchwork.ozlabs.org/api/series/501072/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=501072","date":"2026-04-22T18:21:54","name":"FMV refactor and ACLE compliance for C++","version":1,"mbox":"http://patchwork.ozlabs.org/series/501072/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2226679/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2226679/checks/","tags":{},"related":[],"headers":{"Return-Path":"<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>","X-Original-To":["incoming@patchwork.ozlabs.org","gcc-patches@gcc.gnu.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","gcc-patches@gcc.gnu.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)","sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org","sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org","server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39"],"Received":["from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g173b4vdmz1yGs\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 04:26:51 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 070A848FF1A8\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 18:26:46 +0000 (GMT)","from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 6F3404422C6C\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:23:32 +0000 (GMT)","from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id 68DA543458\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 18:23:30 +0000 (UTC)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org 070A848FF1A8","OpenDKIM Filter v2.11.0 sourceware.org 6F3404422C6C"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 6F3404422C6C","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 6F3404422C6C","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776882212; cv=none;\n b=KtcaI2ESSkjg2QnZuYqgNUgeauEsNQc9R+Rf3cwuPihWsi5mnO7haFRETS0fShrPsD5yOMyFAzK0o9NRMR7wPQ7qqlCk57nez07naL3zAMx6+mwmlnh21vAQB7LM+yf5VNlRh+C5AoI0if9u0ZAtNUpjiEr6GQ3yzkPQh0mevw4=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776882212; c=relaxed/simple;\n bh=qiuvEG2GFwpdc0Ic6z5Dd3eqPoW9+x1HX/OhcmoEUdE=;\n h=From:Date:Subject:To:Message-ID;\n b=CzLgAAsqtpuxXZl4ec4rkmsiLCkYhp9EC9cNZ+//afAK5KE3P/s/6Mzvtp4t5dsZd9o1jQ74DJ9avOdkSVY5M8+Nay2yu8aFdsQ3z+MK3HBtFy3pSd0kSIthVR3J4vyJNzC68NKXbgfyTXXRER54Pz+AK50VpWp2McTEJO+ajzI=","ARC-Authentication-Results":"i=1; server2.sourceware.org","From":"\"\\\"alfie.richards via Sourceware Forge\\\"\"\n <forge-bot+alfie.richards@forge-stage.sourceware.org>","Date":"Wed, 22 Apr 2026 18:21:53 +0000","Subject":"[PATCH v1 05/13] fmv: Change target_version semantics to follow ACLE\n specification.","To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>","Message-ID":"\n <bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.5@forge-stage.sourceware.org>","X-Mailer":"batrachomyomachia","X-Requested-Reviewer":["rsandifo","rearnsha"],"X-Pull-Request-Organization":"gcc","X-Pull-Request-Repository":"gcc-TEST","X-Pull-Request":"https://forge.sourceware.org/gcc/gcc-TEST/pulls/49","References":"\n <bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.0@forge-stage.sourceware.org>","In-Reply-To":"\n <bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.0@forge-stage.sourceware.org>","X-Patch-URL":"\n https://forge.sourceware.org/alfie.richards/gcc-TEST/commit/ded7703bbcf795bd53dcebb0c78b1d286d48c03a","X-BeenThere":"gcc-patches@gcc.gnu.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"Gcc-patches mailing list <gcc-patches.gcc.gnu.org>","List-Unsubscribe":"<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>","List-Archive":"<https://gcc.gnu.org/pipermail/gcc-patches/>","List-Post":"<mailto:gcc-patches@gcc.gnu.org>","List-Help":"<mailto:gcc-patches-request@gcc.gnu.org?subject=help>","List-Subscribe":"<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>","Reply-To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>,\n alfierichards@sourceware.org","Errors-To":"gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"},"content":"From: Alfie Richards <alfie.richards@arm.com>\n\nThis patch changes the semantics of target_version and target_clones attributes\nto match the behavior described in the Arm C Language extension.\n\nThe changes to behavior are:\n\n- The scope and signature of an FMV function set is now that of the default\n  version.\n- The FMV resolver is now created at the locations of the default version\n  implementation. Previously this was at the first call to an FMV function.\n- When a TU has a single annotated function version, it gets mangled.\n  - This includes a lone annotated default version.\n\nThis only affects targets with TARRGET_HAS_FMV_TARGET_ATTRIBUTE set to false.\nCurrently that is aarch64 and riscv.\n\nThis is achieved by:\n\n- Skipping the existing FMV dispatching code at C++ gimplification and instead\n  making use of the target_clones dispatching code in multiple_targets.cc.\n  (This fixes PR target/118313 for aarch64 and riscv).\n- Splitting target_clones pass in two, an early and late pass, where the early\n  pass handles cases where multiple declarations are used to define a version,\n  and the late pass handling target semantics targets, and cases where a FMV\n  set is defined by a single target_clones decl.\n- Changing the logic in add_candidates and resolve_address of overloaded\n  function to prevent resolution of any version except a default version.\n  (thus making the default version determine scope and signature of the\n  versioned function set).\n- Adding logic for dispatching a lone annotated default version in\n  multiple_targets.cc\n  - As as annotated default version gets mangled an alias is created from the\n    dispatched symbol to the default version as no ifunc resolution is required\n    in this case. (ie. an alias from `_Z3foov` to `_Z3foov.default`)\n- Adding logic to `symbol_table::remove_unreachable_nodes` and analyze_functions\n  that a reference to the default function version also implies a possible\n  reference to the other versions (so they shouldnt be deleted and do need to\n  be analyzed).\n\ngcc/ChangeLog:\n\n\tPR target/118313\n\t* cgraph.cc (delete_function_version): Made public static member of\n\tcgraph_node.\n\t* cgraph.h (delete_function_version): Ditto.\n\t* cgraphunit.cc (analyze_functions): Add logic for target version\n\tdependencies.\n\t* ipa.cc (symbol_table::remove_unreachable_nodes): Ditto.\n\t* multiple_target.cc (create_dispatcher_calls): Change to support\n\ttarget version semantics.\n\t(ipa_target_clone): Change to dispatch all function sets in\n\ttarget_version semantics, and to have early and late pass.\n\t(expand_target_clones): Add logic for cases of target_clones with no\n\tdefaults.\n\t(is_simple_target_clones_case): New function.\n\t(class pass_target_clone): New parameter for early or late pass.\n\t* config/aarch64/aarch64.cc: (aarch64_get_function_versions_dispatcher):\n\tRefactor with the assumption that the DECL node will be default.\n\t* config/riscv/riscv.cc: (riscv_get_function_versions_dispatcher):\n\tRefactor with the assumption that the DECL node will be default.\n\t* passes.def: Split target_clones pass into early and late version.\n\ngcc/cp/ChangeLog:\n\n\tPR target/118313\n\t* call.cc (add_candidates): Change to not resolve non-default versions\n\tin target_version semantics.\n\t* class.cc (resolve_address_of_overloaded_function): Ditto.\n\t* cp-gimplify.cc (cp_genericize_r): Change logic to not apply for\n\ttarget_version semantics.\n\t* decl.cc (start_decl): Change to mark and therefore mangle all\n\ttarget_version decls in target_version semantics.\n\t(start_preparsed_function): Ditto.\n\t* typeck.cc (cp_build_function_call_vec): Add error for calling\n\tunresolvable non-default node in target_version semantics.\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.target/aarch64/mv-1.C: Change for target_version semantics.\n\t* g++.target/aarch64/mv-symbols2.C: Ditto.\n\t* g++.target/aarch64/mv-symbols3.C: Ditto.\n\t* g++.target/aarch64/mv-symbols4.C: Ditto.\n\t* g++.target/aarch64/mv-symbols5.C: Ditto.\n\t* g++.target/aarch64/mvc-symbols3.C: Ditto.\n\t* g++.target/riscv/mv-symbols2.C: Ditto.\n\t* g++.target/riscv/mv-symbols3.C: Ditto.\n\t* g++.target/riscv/mv-symbols4.C: Ditto.\n\t* g++.target/riscv/mv-symbols5.C: Ditto.\n\t* g++.target/riscv/mvc-symbols3.C: Ditto.\n\t* g++.target/aarch64/mv-symbols10.C: New test.\n\t* g++.target/aarch64/mv-symbols11.C: New test.\n\t* g++.target/aarch64/mv-symbols12.C: New test.\n\t* g++.target/aarch64/mv-symbols13.C: New test.\n\t* g++.target/aarch64/mv-symbols6.C: New test.\n\t* g++.target/aarch64/mv-symbols7.C: New test.\n\t* g++.target/aarch64/mv-symbols8.C: New test.\n\t* g++.target/aarch64/mv-symbols9.C: New test.\n---\n gcc/cgraph.cc                                 |   4 +-\n gcc/cgraph.h                                  |   2 +\n gcc/cgraphunit.cc                             |   9 +\n gcc/config/aarch64/aarch64.cc                 |  43 ++--\n gcc/config/riscv/riscv.cc                     |  43 ++--\n gcc/cp/call.cc                                |  10 +\n gcc/cp/class.cc                               |  13 +-\n gcc/cp/cp-gimplify.cc                         |  11 +-\n gcc/cp/decl.cc                                |  14 ++\n gcc/cp/typeck.cc                              |  10 +\n gcc/ipa.cc                                    |  11 +\n gcc/multiple_target.cc                        | 188 +++++++++++++++---\n gcc/passes.def                                |   3 +-\n gcc/testsuite/g++.target/aarch64/mv-1.C       |   4 +\n .../g++.target/aarch64/mv-symbols10.C         |  27 +++\n .../g++.target/aarch64/mv-symbols11.C         |  30 +++\n .../g++.target/aarch64/mv-symbols12.C         |  28 +++\n .../g++.target/aarch64/mv-symbols13.C         |  28 +++\n .../g++.target/aarch64/mv-symbols2.C          |  12 +-\n .../g++.target/aarch64/mv-symbols3.C          |   6 +-\n .../g++.target/aarch64/mv-symbols4.C          |   6 +-\n .../g++.target/aarch64/mv-symbols5.C          |   6 +-\n .../g++.target/aarch64/mv-symbols6.C          |  21 ++\n .../g++.target/aarch64/mv-symbols7.C          |  48 +++++\n .../g++.target/aarch64/mv-symbols8.C          |  46 +++++\n .../g++.target/aarch64/mv-symbols9.C          |  43 ++++\n .../g++.target/aarch64/mvc-symbols3.C         |  12 +-\n gcc/testsuite/g++.target/riscv/mv-symbols2.C  |  12 +-\n gcc/testsuite/g++.target/riscv/mv-symbols3.C  |   6 +-\n gcc/testsuite/g++.target/riscv/mv-symbols4.C  |   6 +-\n gcc/testsuite/g++.target/riscv/mv-symbols5.C  |   6 +-\n gcc/testsuite/g++.target/riscv/mvc-symbols3.C |  12 +-\n 32 files changed, 588 insertions(+), 132 deletions(-)\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols10.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols11.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols12.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols13.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols6.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols7.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols8.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-symbols9.C","diff":"diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc\nindex c0be16edfcb7..1d86bcec67f0 100644\n--- a/gcc/cgraph.cc\n+++ b/gcc/cgraph.cc\n@@ -333,8 +333,8 @@ cgraph_node::insert_new_function_version (void)\n }\n \n /* Remove the cgraph_function_version_info node given by DECL_V.  */\n-static void\n-delete_function_version (cgraph_function_version_info *decl_v)\n+void\n+cgraph_node::delete_function_version (cgraph_function_version_info *decl_v)\n {\n   if (decl_v == NULL)\n     return;\ndiff --git a/gcc/cgraph.h b/gcc/cgraph.h\nindex 21f891127695..a719321a538f 100644\n--- a/gcc/cgraph.h\n+++ b/gcc/cgraph.h\n@@ -1352,6 +1352,8 @@ struct GTY((tag (\"SYMTAB_FUNCTION\"))) cgraph_node : public symtab_node\n      DECL is a duplicate declaration.  */\n   static void delete_function_version_by_decl (tree decl);\n \n+  static void delete_function_version (cgraph_function_version_info *);\n+\n   /* Add the function FNDECL to the call graph.\n      Unlike finalize_function, this function is intended to be used\n      by middle end and allows insertion of new function at arbitrary point\ndiff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc\nindex 9f4af63b7dc0..a81f685654f8 100644\n--- a/gcc/cgraphunit.cc\n+++ b/gcc/cgraphunit.cc\n@@ -1264,6 +1264,15 @@ analyze_functions (bool first_time)\n \t      if (!cnode->analyzed)\n \t\tcnode->analyze ();\n \n+\t      /* A reference to a default node in a function set implies a\n+\t\t reference to all versions in the set.  */\n+\t      cgraph_function_version_info *node_v = cnode->function_version ();\n+\t      if (node_v && is_function_default_version (node->decl))\n+\t\tfor (cgraph_function_version_info *fvi = node_v->next;\n+\t\t     fvi;\n+\t\t     fvi = fvi->next)\n+\t\t  enqueue_node (fvi->this_node);\n+\n \t      for (edge = cnode->callees; edge; edge = edge->next_callee)\n \t\tif (edge->callee->definition\n \t\t    && (!DECL_EXTERNAL (edge->callee->decl)\ndiff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc\nindex 5415af2a73b6..441a5cf9b428 100644\n--- a/gcc/config/aarch64/aarch64.cc\n+++ b/gcc/config/aarch64/aarch64.cc\n@@ -21052,42 +21052,29 @@ aarch64_generate_version_dispatcher_body (void *node_p)\n   return resolver_decl;\n }\n \n-/* Make a dispatcher declaration for the multi-versioned function DECL.\n-   Calls to DECL function will be replaced with calls to the dispatcher\n-   by the front-end.  Returns the decl of the dispatcher function.  */\n+/* Make a dispatcher declaration for the multi-versioned default function DECL.\n+   Calls to DECL function will be replaced with calls to the dispatcher by\n+   the target_clones pass.  Returns the decl of the dispatcher function.  */\n \n tree\n aarch64_get_function_versions_dispatcher (void *decl)\n {\n-  tree fn = (tree) decl;\n-  struct cgraph_node *node = NULL;\n-  struct cgraph_node *default_node = NULL;\n-  struct cgraph_function_version_info *node_v = NULL;\n-\n+  tree default_decl = (tree) decl;\n   tree dispatch_decl = NULL;\n \n-  struct cgraph_function_version_info *default_version_info = NULL;\n-\n-  gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));\n-\n-  node = cgraph_node::get (fn);\n-  gcc_assert (node != NULL);\n+  gcc_assert (decl != NULL\n+\t      && DECL_FUNCTION_VERSIONED (default_decl)\n+\t      && is_function_default_version (default_decl));\n \n-  node_v = node->function_version ();\n-  gcc_assert (node_v != NULL);\n+  struct cgraph_node *default_node = cgraph_node::get (default_decl);\n+  gcc_assert (default_node != NULL);\n \n-  if (node_v->dispatcher_resolver != NULL)\n-    return node_v->dispatcher_resolver;\n+  struct cgraph_function_version_info *default_node_v\n+    = default_node->function_version ();\n+  gcc_assert (default_node_v != NULL && !default_node_v->prev);\n \n-  /* The default node is always the beginning of the chain.  */\n-  default_version_info = node_v;\n-  while (default_version_info->prev)\n-    default_version_info = default_version_info->prev;\n-  default_node = default_version_info->this_node;\n-\n-  /* If there is no default node, just return NULL.  */\n-  if (!is_function_default_version (default_node->decl))\n-    return NULL;\n+  if (default_node_v->dispatcher_resolver != NULL)\n+    return default_node_v->dispatcher_resolver;\n \n   if (targetm.has_ifunc_p ())\n     {\n@@ -21097,7 +21084,7 @@ aarch64_get_function_versions_dispatcher (void *decl)\n       dispatch_decl = make_dispatcher_decl (default_node->decl);\n \n       /* Set the dispatcher for all the versions.  */\n-      it_v = default_version_info;\n+      it_v = default_node_v;\n       while (it_v != NULL)\n \t{\n \t  it_v->dispatcher_resolver = dispatch_decl;\ndiff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc\nindex 419eec7ed168..3c9538048040 100644\n--- a/gcc/config/riscv/riscv.cc\n+++ b/gcc/config/riscv/riscv.cc\n@@ -14573,42 +14573,29 @@ riscv_generate_version_dispatcher_body (void *node_p)\n   return resolver_decl;\n }\n \n-/* Make a dispatcher declaration for the multi-versioned function DECL.\n-   Calls to DECL function will be replaced with calls to the dispatcher\n-   by the front-end.  Returns the decl of the dispatcher function.  */\n+/* Make a dispatcher declaration for the multi-versioned default function DECL.\n+   Calls to DECL function will be replaced with calls to the dispatcher by\n+   the target_clones pass.  Returns the decl of the dispatcher function.  */\n \n tree\n riscv_get_function_versions_dispatcher (void *decl)\n {\n-  tree fn = (tree) decl;\n-  struct cgraph_node *node = NULL;\n-  struct cgraph_node *default_node = NULL;\n-  struct cgraph_function_version_info *node_v = NULL;\n-\n+  tree default_decl = (tree) decl;\n   tree dispatch_decl = NULL;\n \n-  struct cgraph_function_version_info *default_version_info = NULL;\n-\n-  gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn));\n-\n-  node = cgraph_node::get (fn);\n-  gcc_assert (node != NULL);\n-\n-  node_v = node->function_version ();\n-  gcc_assert (node_v != NULL);\n+  gcc_assert (decl != NULL\n+\t      && DECL_FUNCTION_VERSIONED (default_decl)\n+\t      && is_function_default_version (default_decl));\n \n-  if (node_v->dispatcher_resolver != NULL)\n-    return node_v->dispatcher_resolver;\n+  struct cgraph_node *default_node = cgraph_node::get (default_decl);\n+  gcc_assert (default_node != NULL);\n \n-  /* The default node is always the beginning of the chain.  */\n-  default_version_info = node_v;\n-  while (default_version_info->prev)\n-    default_version_info = default_version_info->prev;\n-  default_node = default_version_info->this_node;\n+  struct cgraph_function_version_info *default_node_v\n+    = default_node->function_version ();\n+  gcc_assert (default_node_v != NULL && !default_node_v->prev);\n \n-  /* If there is no default node, just return NULL.  */\n-  if (!is_function_default_version (default_node->decl))\n-    return NULL;\n+  if (default_node_v->dispatcher_resolver != NULL)\n+    return default_node_v->dispatcher_resolver;\n \n   if (targetm.has_ifunc_p ())\n     {\n@@ -14618,7 +14605,7 @@ riscv_get_function_versions_dispatcher (void *decl)\n       dispatch_decl = make_dispatcher_decl (default_node->decl);\n \n       /* Set the dispatcher for all the versions.  */\n-      it_v = default_version_info;\n+      it_v = default_node_v;\n       while (it_v != NULL)\n \t{\n \t  it_v->dispatcher_resolver = dispatch_decl;\ndiff --git a/gcc/cp/call.cc b/gcc/cp/call.cc\nindex 63cad2aca4ca..a6a3fd0d6bb8 100644\n--- a/gcc/cp/call.cc\n+++ b/gcc/cp/call.cc\n@@ -6927,6 +6927,16 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args,\n \t    continue;\n \t}\n \n+      /* Do not resolve any non-default function.  Only the default version\n+\t is resolvable (for the target_version attribute semantics.)  */\n+      if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+\t  && TREE_CODE (fn) == FUNCTION_DECL\n+\t  && !is_function_default_version (fn))\n+\t{\n+\t  add_ignored_candidate (candidates, fn);\n+\t  continue;\n+\t}\n+\n       if (TREE_CODE (fn) == TEMPLATE_DECL)\n \tadd_template_candidate (candidates,\n \t\t\t\tfn,\ndiff --git a/gcc/cp/class.cc b/gcc/cp/class.cc\nindex 14acb9c23c01..5e9ad1724d56 100644\n--- a/gcc/cp/class.cc\n+++ b/gcc/cp/class.cc\n@@ -8974,6 +8974,13 @@ resolve_address_of_overloaded_function (tree target_type,\n \tif (!constraints_satisfied_p (fn))\n \t  continue;\n \n+\t/* For target_version semantics, never resolve a non-default\n+\t   version.  */\n+\tif (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+\t    && TREE_CODE (fn) == FUNCTION_DECL\n+\t    && !is_function_default_version (fn))\n+\t  continue;\n+\n \tif (undeduced_auto_decl (fn))\n \t  {\n \t    /* Force instantiation to do return type deduction.  */\n@@ -9199,8 +9206,10 @@ resolve_address_of_overloaded_function (tree target_type,\n   /* If a pointer to a function that is multi-versioned is requested, the\n      pointer to the dispatcher function is returned instead.  This works\n      well because indirectly calling the function will dispatch the right\n-     function version at run-time.  */\n-  if (DECL_FUNCTION_VERSIONED (fn))\n+     function version at run-time.\n+     This is done at multiple_target.cc for target_version semantics.  */\n+\n+  if (DECL_FUNCTION_VERSIONED (fn) && TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n     {\n       fn = get_function_version_dispatcher (fn);\n       if (fn == NULL)\ndiff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc\nindex 4ff8f36a9fb6..7ff287a2b1cb 100644\n--- a/gcc/cp/cp-gimplify.cc\n+++ b/gcc/cp/cp-gimplify.cc\n@@ -2165,13 +2165,16 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)\n \t returns the function with the highest target priority, that is,\n \t the version that will checked for dispatching first.  If this\n \t version is inlinable, a direct call to this version can be made\n-\t otherwise the call should go through the dispatcher.  */\n+\t otherwise the call should go through the dispatcher.\n+\t This is done at multiple_target.cc for target_version semantics.  */\n       {\n \ttree fn = cp_get_callee_fndecl_nofold (stmt);\n-\tif (fn && DECL_FUNCTION_VERSIONED (fn)\n+\tif (TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+\t    && fn\n+\t    && DECL_FUNCTION_VERSIONED (fn)\n \t    && (current_function_decl == NULL\n-\t\t|| !targetm.target_option.can_inline_p (current_function_decl,\n-\t\t\t\t\t\t\tfn)))\n+\t\t|| !targetm.target_option.can_inline_p\n+\t\t      (current_function_decl, fn)))\n \t  if (tree dis = get_function_version_dispatcher (fn))\n \t    {\n \t      mark_versions_used (dis);\ndiff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc\nindex 0671c9b594b2..27b2487927e3 100644\n--- a/gcc/cp/decl.cc\n+++ b/gcc/cp/decl.cc\n@@ -6196,6 +6196,13 @@ start_decl (const cp_declarator *declarator,\n \n   was_public = TREE_PUBLIC (decl);\n \n+  /* For target_version semantics, mark any annotated function as versioned\n+     so that it gets mangled even when on its own in a TU.  */\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+      && TREE_CODE (decl) == FUNCTION_DECL\n+      && get_target_version (decl).is_valid ())\n+    maybe_mark_function_versioned (decl);\n+\n   if ((DECL_EXTERNAL (decl) || TREE_CODE (decl) == FUNCTION_DECL)\n       && current_function_decl)\n     {\n@@ -19096,6 +19103,13 @@ start_preparsed_function (tree decl1, tree attrs, int flags)\n   if (!DECL_OMP_DECLARE_REDUCTION_P (decl1))\n     start_lambda_scope (decl1);\n \n+  /* For target_version semantics, mark any annotated function as versioned\n+     so that it gets mangled even when on its own in a TU.  */\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+      && TREE_CODE (decl1) == FUNCTION_DECL\n+      && get_target_version (decl1).is_valid ())\n+    maybe_mark_function_versioned (decl1);\n+\n   return true;\n }\n \ndiff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc\nindex f592894e01ab..e5e05cfc4b74 100644\n--- a/gcc/cp/typeck.cc\n+++ b/gcc/cp/typeck.cc\n@@ -4490,6 +4490,16 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,\n \treturn error_mark_node;\n       fndecl = function;\n \n+      /* For target_version semantics, the function set cannot be called\n+\t if there is no default version in scope.  */\n+      if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+\t   && !is_function_default_version (fndecl))\n+\t {\n+\t   if (complain & tf_error)\n+\t    error (\"no default version in scope\");\n+\t   return error_mark_node;\n+\t }\n+\n       /* Convert anything with function type to a pointer-to-function.  */\n       if (DECL_MAIN_P (function))\n \t{\ndiff --git a/gcc/ipa.cc b/gcc/ipa.cc\nindex 8a7b067a526a..dea22ea0b491 100644\n--- a/gcc/ipa.cc\n+++ b/gcc/ipa.cc\n@@ -433,6 +433,17 @@ symbol_table::remove_unreachable_nodes (FILE *file)\n \t\t\t\t\t\t       e, &first, &reachable);\n \t\t    }\n \t\t}\n+\n+\t      /* A reference to the default node implies use of all the other\n+\t\t versions (they get used in the function resolver made later\n+\t\t in multiple_target.cc)  */\n+\t      cgraph_function_version_info *node_v = cnode->function_version ();\n+\t      if (node_v && is_function_default_version (node->decl))\n+\t\tfor (cgraph_function_version_info *fvi = node_v->next;\n+\t\t     fvi;\n+\t\t     fvi = fvi->next)\n+\t\t  enqueue_node (fvi->this_node, &first, &reachable);\n+\n \t      for (e = cnode->callees; e; e = e->next_callee)\n \t\t{\n \t          symtab_node *body = e->callee->function_symbol ();\ndiff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc\nindex dc3b72c8e850..02e868212e46 100644\n--- a/gcc/multiple_target.cc\n+++ b/gcc/multiple_target.cc\n@@ -58,8 +58,15 @@ replace_function_decl (tree *op, int *walk_subtrees, void *data)\n   return NULL;\n }\n \n-/* If the call in NODE has multiple target attribute with multiple fields,\n-   replace it with dispatcher call and create dispatcher (once).  */\n+/* In target FMV attributes, if the call in NODE has multiple target attribute\n+   with multiple fields, replace it with calls to the dispatched symbol and\n+   create the dispatcher body (once).\n+\n+   In target_version semantics, if it is a lone annotated default, then\n+   the dispatched symbol is changed to be an alias and no resolver is\n+   required.  Otherwise, redirect all calls and references to the dispatched\n+   symbol, but only create the resolver body if the default version is\n+   implemented.  */\n \n static void\n create_dispatcher_calls (struct cgraph_node *node)\n@@ -90,13 +97,48 @@ create_dispatcher_calls (struct cgraph_node *node)\n \n   cgraph_node *inode = cgraph_node::get (idecl);\n   gcc_assert (inode);\n-  tree resolver_decl = targetm.generate_version_dispatcher_body (inode);\n-\n-  /* Update aliases.  */\n-  inode->alias = true;\n-  inode->alias_target = resolver_decl;\n-  if (!inode->analyzed)\n-    inode->resolve_alias (cgraph_node::get (resolver_decl));\n+  cgraph_function_version_info *inode_info = inode->function_version ();\n+  gcc_assert (inode_info);\n+\n+  tree resolver_decl = NULL;\n+\n+  /* For target_version semantics, if there is a lone default declaration\n+     it needs to be mangled, with an alias from the dispatched symbol to the\n+     default version.  */\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+      && TREE_STATIC (node->decl)\n+      && inode_info->next\n+      && !inode_info->next->next)\n+    {\n+      inode->alias = true;\n+      inode->alias_target = inode_info->next->this_node->decl;\n+      inode->externally_visible = true;\n+      if (!inode->analyzed)\n+\tinode->resolve_alias\n+\t  (cgraph_node::get (inode_info->next->this_node->decl));\n+\n+      DECL_ATTRIBUTES (idecl)\n+\t= make_attribute (\"alias\",\n+\t\t\t  IDENTIFIER_POINTER\n+\t\t\t    (DECL_ASSEMBLER_NAME\n+\t\t\t       (inode_info->next->this_node->decl)),\n+\t\t\t  DECL_ATTRIBUTES (node->decl));\n+      TREE_USED (idecl) = true;\n+      DECL_EXTERNAL (idecl) = false;\n+      TREE_STATIC (idecl) = true;\n+      return;\n+    }\n+  /* In target_version semantics, only create the resolver if the\n+     default node is implemented.  */\n+  else if (TARGET_HAS_FMV_TARGET_ATTRIBUTE || TREE_STATIC (node->decl))\n+    {\n+      resolver_decl = targetm.generate_version_dispatcher_body (inode);\n+      /* Update aliases.  */\n+      inode->alias = true;\n+      inode->alias_target = resolver_decl;\n+      if (!inode->analyzed)\n+\tinode->resolve_alias (cgraph_node::get (resolver_decl));\n+    }\n \n   auto_vec<cgraph_edge *> edges_to_redirect;\n   /* We need to capture the references by value rather than just pointers to them\n@@ -299,19 +341,32 @@ expand_target_clones (struct cgraph_node *node, bool definition)\n   tree assembler_name = node_v->assembler_name;\n \n   /* Change the current node into the default node.  */\n-  gcc_assert (num_defaults == 1);\n-\n-  /* Setting new attribute to initial function.  */\n-  tree attributes = make_attribute (new_attr_name, \"default\", attrs);\n-  DECL_ATTRIBUTES (node->decl) = attributes;\n-  DECL_FUNCTION_VERSIONED (node->decl) = true;\n+  if (num_defaults == 1)\n+    {\n+      /* Setting new attribute to initial function.  */\n+      tree attributes = make_attribute (new_attr_name, \"default\", attrs);\n+      DECL_ATTRIBUTES (node->decl) = attributes;\n+      DECL_FUNCTION_VERSIONED (node->decl) = true;\n \n-  node->is_target_clone = true;\n-  node->local = false;\n+      node->is_target_clone = true;\n+      node->local = false;\n \n-  /* Remangle base node after new target version string set.  */\n-  tree id = targetm.mangle_decl_assembler_name (node->decl, assembler_name);\n-  symtab->change_decl_assembler_name (node->decl, id);\n+      /* Remangle base node after new target version string set.  */\n+      tree id = targetm.mangle_decl_assembler_name (node->decl, assembler_name);\n+      symtab->change_decl_assembler_name (node->decl, id);\n+    }\n+  else\n+    {\n+      /* Target clones without a default are only allowed for target_version\n+\t semantics where we can have target_clones/target_version mixing.  */\n+      gcc_assert (!TARGET_HAS_FMV_TARGET_ATTRIBUTE);\n+\n+      /* If there isn't a default version, can safely remove this version.\n+\t The node itself gets removed after the other versions are created.  */\n+      cgraph_function_version_info *temp = node_v;\n+      node_v = node_v->next ? node_v->next : node_v->prev;\n+      cgraph_node::delete_function_version (temp);\n+    }\n \n   for (string_slice attr : attr_list)\n     {\n@@ -344,6 +399,10 @@ expand_target_clones (struct cgraph_node *node, bool definition)\n       symtab->change_decl_assembler_name (new_node->decl, id);\n     }\n \n+  /* If there are no default versions in the target_clones, this node is not\n+     reused, so can delete this node.  */\n+  if (num_defaults == 0)\n+    node->remove ();\n \n   return true;\n }\n@@ -406,15 +465,87 @@ redirect_to_specific_clone (cgraph_node *node)\n     }\n }\n \n+/* Checks if NODE is in the 'simple' target_clones case, which is where NODE\n+   is a declaration annotated with target_clones containing the default, and it\n+   is the sole function declaration in the FMV function set.  */\n+\n+static bool\n+is_simple_target_clones_case (cgraph_node *node)\n+{\n+  /* target attribute semantics doesnt support the complex case,\n+     so this is always true.  */\n+  if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n+    return true;\n+\n+  int num_defaults = 0;\n+  auto versions = get_clone_versions (node->decl, &num_defaults);\n+  if (versions.is_empty () || num_defaults != 1)\n+    return false;\n+\n+  cgraph_function_version_info *fv = node->function_version ();\n+\n+  if (fv && (fv->next || fv->prev))\n+    return false;\n+\n+  return true;\n+}\n+\n static unsigned int\n-ipa_target_clone (void)\n+ipa_target_clone (bool early)\n {\n   struct cgraph_node *node;\n   auto_vec<cgraph_node *> to_dispatch;\n \n+  /* Don't need to do anything early for target attribute semantics.  */\n+  if (early && TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n+    return 0;\n+\n+  /* For target attribute semantics, this pass skips the early phase, and in\n+     the later stage is only responsible for expanding and dispatching\n+     target_clone declarations, as target annotated functions are dispatched\n+     in the front end.\n+\n+     The expanding and dispatching can be done at the late stage as the\n+     target_clone functions aren't allowed to be part of a larger FMV set, so\n+     all versions will all have the same body, so early optimisations are safe\n+     to treat a call to a target_clones set as a call to one function.\n+\n+     For target_version semantics, this pass is responsible for expanding\n+     target_clones and dispatching all FMV function sets, including ones only\n+     made up of target_version declarations.\n+\n+     Cases where there is more than one declaration must be expanded and\n+     dispatched at the early stage, as the declarations may have different\n+     bodies, and so the early optimisation passes would not be valid.\n+\n+     The late stage is only used for the expansion and dispatching of the simple\n+     case where the FMV set is defined by a single target_clone attribute.  */\n+\n   FOR_EACH_FUNCTION (node)\n-    if (expand_target_clones (node, node->definition))\n-      to_dispatch.safe_push (node);\n+    {\n+      /* In the early stage, we need to expand any target clone that is not\n+\t the simple case.  Simple cases are dispatched in the later stage.  */\n+\n+      if (early == !is_simple_target_clones_case (node))\n+\tif (expand_target_clones (node, node->definition)\n+\t    && TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n+\t  /* In non target_version semantics, dispatch all target clones.  */\n+\t  to_dispatch.safe_push (node);\n+    }\n+\n+  /* In target_version semantics dispatch all FMV function sets with a default\n+     implementation in the early stage.\n+     Also dispatch any default versions generated by expanding target_clones\n+     in the late stage.  */\n+\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n+    FOR_EACH_FUNCTION (node)\n+      if (is_function_default_version (node->decl)\n+\t  && DECL_FUNCTION_VERSIONED (node->decl)\n+\t  /* Don't dispatch target clones, as they haven't been expanded so\n+\t     are simple.  */\n+\t  && !lookup_attribute (\"target_clones\", DECL_ATTRIBUTES (node->decl)))\n+\tto_dispatch.safe_push (node);\n \n   for (unsigned i = 0; i < to_dispatch.length (); i++)\n     create_dispatcher_calls (to_dispatch[i]);\n@@ -445,14 +576,21 @@ class pass_target_clone : public simple_ipa_opt_pass\n {\n public:\n   pass_target_clone (gcc::context *ctxt)\n-    : simple_ipa_opt_pass (pass_data_target_clone, ctxt)\n+    : simple_ipa_opt_pass (pass_data_target_clone, ctxt), early_p (false)\n   {}\n+  bool early_p;\n \n+  void set_pass_param (unsigned int n, bool param) final override\n+    {\n+      gcc_assert (n == 0);\n+      early_p = param;\n+    }\n   /* opt_pass methods: */\n   bool gate (function *) final override;\n+  opt_pass * clone () final override { return new pass_target_clone (m_ctxt); }\n   unsigned int execute (function *) final override\n   {\n-    return ipa_target_clone ();\n+    return ipa_target_clone (early_p);\n   }\n };\n \ndiff --git a/gcc/passes.def b/gcc/passes.def\nindex d528a0477d9a..619dc0e460b9 100644\n--- a/gcc/passes.def\n+++ b/gcc/passes.def\n@@ -66,6 +66,7 @@ along with GCC; see the file COPYING3.  If not see\n       NEXT_PASS (pass_nothrow);\n       NEXT_PASS (pass_rebuild_cgraph_edges);\n   POP_INSERT_PASSES ()\n+  NEXT_PASS (pass_target_clone, true);\n \n   NEXT_PASS (pass_local_optimization_passes);\n   PUSH_INSERT_PASSES_WITHIN (pass_local_optimization_passes)\n@@ -141,7 +142,7 @@ along with GCC; see the file COPYING3.  If not see\n       POP_INSERT_PASSES ()\n   POP_INSERT_PASSES ()\n \n-  NEXT_PASS (pass_target_clone);\n+  NEXT_PASS (pass_target_clone, false);\n   NEXT_PASS (pass_ipa_auto_profile);\n   PUSH_INSERT_PASSES_WITHIN (pass_ipa_auto_profile)\n       NEXT_PASS (pass_feedback_split_functions);\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-1.C b/gcc/testsuite/g++.target/aarch64/mv-1.C\nindex b10037f1b9ba..93b8a1365873 100644\n--- a/gcc/testsuite/g++.target/aarch64/mv-1.C\n+++ b/gcc/testsuite/g++.target/aarch64/mv-1.C\n@@ -37,3 +37,7 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mrng:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MrngMflagm:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mflagm:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols10.C b/gcc/testsuite/g++.target/aarch64/mv-symbols10.C\nnew file mode 100644\nindex 000000000000..92d4ab617d85\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols10.C\n@@ -0,0 +1,27 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__ ((target_version (\"default\"))) void\n+foo (int a = 3);\n+\n+__attribute__ ((target_version (\"sve\"))) void\n+foo (int a = 4);\n+\n+void bar() {\n+  foo();\n+}\n+\n+__attribute__ ((target_version (\"sve\"))) void\n+foo2 (int a = 6);\n+\n+__attribute__ ((target_version (\"default\"))) void\n+foo2 (int a = 5);\n+\n+void bar2() {\n+  foo2();\n+}\n+\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tmov\\tw\\[0-9\\]\\+, 3\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tmov\\tw\\[0-9\\]\\+, 5\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols11.C b/gcc/testsuite/g++.target/aarch64/mv-symbols11.C\nnew file mode 100644\nindex 000000000000..dadde22622ea\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols11.C\n@@ -0,0 +1,30 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__ ((target_version (\"default\"))) int\n+foo () { return 1; }\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo () { return 3; }\n+\n+int (*test)();\n+\n+void bar ()\n+{\n+  test = foo;\n+}\n+\n+__attribute__ ((target_version (\"default\"))) int\n+foo2 ();\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo2 ();\n+\n+void bar2 ()\n+{\n+  test = foo2;\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z4foo2v\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols12.C b/gcc/testsuite/g++.target/aarch64/mv-symbols12.C\nnew file mode 100644\nindex 000000000000..d78ee4b91c5c\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols12.C\n@@ -0,0 +1,28 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+int foo () {\n+  return 1;\n+}\n+\n+void\n+bar ()\n+{\n+  foo ();\n+}\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ();\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 0 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Mdotprod\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols13.C b/gcc/testsuite/g++.target/aarch64/mv-symbols13.C\nnew file mode 100644\nindex 000000000000..997b9bad6d6c\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols13.C\n@@ -0,0 +1,28 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+int foo () {\n+  return 1;\n+}\n+\n+void bar ()\n+{\n+  int (*test)() = foo;\n+\n+  test();\n+}\n+\n+__attribute__ ((target_version (\"dotprod\"))) int foo ();\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 0 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Mdotprod\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols2.C b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C\nindex 6da88ddfb48d..55f2d48f5e47 100644\n--- a/gcc/testsuite/g++.target/aarch64/mv-symbols2.C\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols2.C\n@@ -41,13 +41,13 @@ int foo (int)\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._Mdotprod:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._MsveMsve2:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols3.C b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C\nindex 5dd7b49be2a1..6ba02a2aae9f 100644\n--- a/gcc/testsuite/g++.target/aarch64/mv-symbols3.C\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols3.C\n@@ -29,10 +29,10 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._Mdotprod:\\n\" 0 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols4.C b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C\nindex 4b25d17cc15a..cc013c478489 100644\n--- a/gcc/testsuite/g++.target/aarch64/mv-symbols4.C\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols4.C\n@@ -44,6 +44,6 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._Mdotprod:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._MsveMsve2:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols5.C b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C\nindex fac00b203135..1396ca379e48 100644\n--- a/gcc/testsuite/g++.target/aarch64/mv-symbols5.C\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols5.C\n@@ -44,10 +44,10 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._Mdotprod:\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols6.C b/gcc/testsuite/g++.target/aarch64/mv-symbols6.C\nnew file mode 100644\nindex 000000000000..2b67bcb47a4e\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols6.C\n@@ -0,0 +1,21 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__ ((target_version (\"default\"))) int\n+foo ()\n+{\n+  return 1;\n+}\n+\n+int bar()\n+{\n+  return foo();\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"bl\\t_Z3foov.default\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \".global\\t_Z3foov\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \".set\\t_Z3foov,_Z3foov.default\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols7.C b/gcc/testsuite/g++.target/aarch64/mv-symbols7.C\nnew file mode 100644\nindex 000000000000..3998adb54a74\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols7.C\n@@ -0,0 +1,48 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ();\n+\n+__attribute__ ((target_version (\"sve+sve2\"))) int\n+foo ();\n+\n+__attribute__ ((target_version (\"default\"))) int\n+foo ();\n+\n+__attribute__ ((target_version (\"sve+sve2\"))) int\n+foo ()\n+{\n+  return 5;\n+}\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ()\n+{\n+  return 3;\n+}\n+__attribute__ ((target_version (\"default\"))) int\n+foo ()\n+{\n+  return 1;\n+}\n+\n+int\n+bar ()\n+{\n+  return foo ();\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._MsveMsve2\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Mdotprod\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols8.C b/gcc/testsuite/g++.target/aarch64/mv-symbols8.C\nnew file mode 100644\nindex 000000000000..5983bbd69251\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols8.C\n@@ -0,0 +1,46 @@\n+/* { dg-do compile } */\n+/* { dg-require-ifunc \"\" } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ();\n+__attribute__ ((target_version (\"sve+sve2\"))) int\n+foo ();\n+\n+int\n+foo ()\n+{\n+  return 1;\n+}\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ()\n+{\n+  return 3;\n+}\n+__attribute__ ((target_version (\"sve+sve2\"))) int\n+foo ()\n+{\n+  return 5;\n+}\n+\n+int\n+bar ()\n+{\n+  return foo ();\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._MsveMsve2\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Mdotprod\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-symbols9.C b/gcc/testsuite/g++.target/aarch64/mv-symbols9.C\nnew file mode 100644\nindex 000000000000..bfad9bb5850b\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-symbols9.C\n@@ -0,0 +1,43 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+int\n+foo ();\n+\n+int\n+foo ()\n+{\n+  return 1;\n+}\n+\n+__attribute__ ((target_version (\"dotprod\"))) int\n+foo ()\n+{\n+  return 3;\n+}\n+__attribute__ ((target_version (\"sve+sve2\"))) int\n+foo ()\n+{\n+  return 5;\n+}\n+\n+int\n+bar ()\n+{\n+  return foo ();\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._MsveMsve2\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Mdotprod\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n+\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C\nindex 350a5586643f..2a315d2db5cf 100644\n--- a/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C\n+++ b/gcc/testsuite/g++.target/aarch64/mvc-symbols3.C\n@@ -22,15 +22,15 @@ int bar(int x)\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Mdotprod:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\._MsveMsve2:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3foov\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, %gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._Mdotprod:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\._MsveMsve2:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tbl\\t_Z3fooi\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, %gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\ndiff --git a/gcc/testsuite/g++.target/riscv/mv-symbols2.C b/gcc/testsuite/g++.target/riscv/mv-symbols2.C\nindex 43fa1502b7d1..8a5c5a0bc9f4 100644\n--- a/gcc/testsuite/g++.target/riscv/mv-symbols2.C\n+++ b/gcc/testsuite/g++.target/riscv/mv-symbols2.C\n@@ -47,15 +47,15 @@ int foo (int)\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__v:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__zba__zbb:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3foov\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__v:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__zba__zbb:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3fooi\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/riscv/mv-symbols3.C b/gcc/testsuite/g++.target/riscv/mv-symbols3.C\nindex 6596a277f6a9..2a7b2bc8e429 100644\n--- a/gcc/testsuite/g++.target/riscv/mv-symbols3.C\n+++ b/gcc/testsuite/g++.target/riscv/mv-symbols3.C\n@@ -36,10 +36,10 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__v:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__zba__zbb:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3foov(?:@plt)?\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__v:\\n\" 0 } } */\ndiff --git a/gcc/testsuite/g++.target/riscv/mv-symbols4.C b/gcc/testsuite/g++.target/riscv/mv-symbols4.C\nindex 83d51e337066..7665e775239b 100644\n--- a/gcc/testsuite/g++.target/riscv/mv-symbols4.C\n+++ b/gcc/testsuite/g++.target/riscv/mv-symbols4.C\n@@ -50,7 +50,7 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__v:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__zba__zbb:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3fooi(?:@plt)?\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/riscv/mv-symbols5.C b/gcc/testsuite/g++.target/riscv/mv-symbols5.C\nindex c92421ab0fb3..5ca31851618d 100644\n--- a/gcc/testsuite/g++.target/riscv/mv-symbols5.C\n+++ b/gcc/testsuite/g++.target/riscv/mv-symbols5.C\n@@ -48,10 +48,10 @@ int bar()\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__v:\\n\" 1 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__zba__zbb:\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3foov(?:@plt)?\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__v:\\n\" 1 } } */\ndiff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols3.C b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C\nindex 78f027b0457e..e3987eaa75a5 100644\n--- a/gcc/testsuite/g++.target/riscv/mvc-symbols3.C\n+++ b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C\n@@ -28,15 +28,15 @@ int bar(int x)\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__v:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3foov\\.arch__zba__zbb:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3foov(?:@plt)?\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3foov, @gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3foov,_Z3foov\\.resolver\\n\" 0 } } */\n \n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.default:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__v:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.arch__zba__zbb:\\n\" 0 } } */\n-/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3fooi\\.resolver:\\n\" 0 } } */\n /* { dg-final { scan-assembler-times \"\\n\\tcall\\t_Z3fooi(?:@plt)?\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 1 } } */\n-/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.type\\t_Z3fooi, @gnu_indirect_function\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\t\\.set\\t_Z3fooi,_Z3fooi\\.resolver\\n\" 0 } } */\n","prefixes":["v1","05/13"]}