{"id":2226702,"url":"http://patchwork.ozlabs.org/api/patches/2226702/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.8@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.8@forge-stage.sourceware.org>","list_archive_url":null,"date":"2026-04-22T18:21:56","name":"[v1,08/13] fmv: Support mixing of target_clones and target_version.","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"d4f94afe419c158062c057ce90c3e5e98f772807","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.8@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/2226702/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2226702/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=38.145.34.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 [38.145.34.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 4g17HS5mvmz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 04:37:07 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 8AC9E48FE097\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 18:37:05 +0000 (GMT)","from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id 96666441F94E\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 93DF04345B\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 8AC9E48FE097","OpenDKIM Filter v2.11.0 sourceware.org 96666441F94E"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org 96666441F94E","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org 96666441F94E","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776882212; cv=none;\n b=vZCHc3em/PrBFT0c5Zyi269MI4dHdx9q1d5E3UUSVEYKpPZsHLsKLdLOb14/tYBlnuHdZgZPLaX/faVrmImv7LCSSOy8kyNnbIwOOJVIFBmex0oRudnl1miEUA2BlbnRlw0IVRO0SbuDyNlDdVFPbHphyI2B3NZjEsB4Mj2T4k4=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776882212; c=relaxed/simple;\n bh=LqXQNpuoo3kCiG+v8UsoTLZF4PBjZBj4GFCJ0GR9DRw=;\n h=From:Date:Subject:To:Message-ID;\n b=tnhWDIsJu6nLODbETXRE/mbFG93XVnDw+SQU23RVRQWCi9JZYmR/9TvOyCj25E8B3ha/jPDmvdz7edovL0Zic5uklR1iIOWpSuiDT5N8KaDNYbgdyh6OCX0s6NIGPKyxgmXQGY8knImySIESVCHNJFFj2IFNVAP6G/qXOmybGJ4=","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:56 +0000","Subject":"[PATCH v1 08/13] fmv: Support mixing of target_clones and\n target_version.","To":"gcc-patches mailing list <gcc-patches@gcc.gnu.org>","Message-ID":"\n <bmm.hhuodmon6a.gcc.gcc-TEST.alfie.richards.49.1.8@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/0718c0f0a9815fad0a2b85b9fc308b2f90eac8af","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\nAdd support for a FMV set defined by a combination of target_clones and\ntarget_version definitions.\n\nAdditionally, change is_function_default_version to consider a function\ndeclaration annotated with target_clones containing default to be a\ndefault version.\n\nLastly, add support for the case that a target_clone has all versions filtered\nout and therefore the declaration should be removed. This is relevant as now\nthe default could be defined in a target_version, so a target_clones no longer\nnecessarily contains the default.\n\nThis takes advantage of refactoring done in previous patches changing how\ntarget_clones are expanded and how conflicting decls are handled.\n\ngcc/ChangeLog:\n\n\t* attribs.cc (is_function_default_version): Update to handle\n\ttarget_clones.\n\t* cgraph.h (FOR_EACH_FUNCTION_REMOVABLE): New macro.\n\t* multiple_target.cc (expand_target_clones): Update logic to delete\n\tempty target_clones and modify diagnostic.\n\t(ipa_target_clone): Update to use FOR_EACH_FUNCTION_REMOVABLE.\n\ngcc/c-family/ChangeLog:\n\n\t* c-attribs.cc: Add support for target_version and target_clone mixing.\n\ngcc/testsuite/ChangeLog:\n\n\t* g++.target/aarch64/mv-and-mvc1.C: New test.\n\t* g++.target/aarch64/mv-and-mvc2.C: New test.\n\t* g++.target/aarch64/mv-and-mvc3.C: New test.\n\t* g++.target/aarch64/mv-and-mvc4.C: New test.\n---\n gcc/attribs.cc                                | 10 ++++-\n gcc/c-family/c-attribs.cc                     |  9 +---\n gcc/cgraph.h                                  |  7 ++++\n gcc/multiple_target.cc                        | 24 +++++++++--\n .../g++.target/aarch64/mv-and-mvc1.C          | 38 +++++++++++++++++\n .../g++.target/aarch64/mv-and-mvc2.C          | 29 +++++++++++++\n .../g++.target/aarch64/mv-and-mvc3.C          | 41 +++++++++++++++++++\n .../g++.target/aarch64/mv-and-mvc4.C          | 38 +++++++++++++++++\n 8 files changed, 183 insertions(+), 13 deletions(-)\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc1.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc2.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc3.C\n create mode 100644 gcc/testsuite/g++.target/aarch64/mv-and-mvc4.C","diff":"diff --git a/gcc/attribs.cc b/gcc/attribs.cc\nindex 06785eaa136b..2ca82674f7c2 100644\n--- a/gcc/attribs.cc\n+++ b/gcc/attribs.cc\n@@ -1242,7 +1242,8 @@ make_dispatcher_decl (const tree decl)\n    With the target attribute semantics, returns true if the function is marked\n    as default with the target version.\n    With the target_version attribute semantics, returns true if the function\n-   is either not annotated, or annotated as default.  */\n+   is either not annotated, annotated as default, or is a target_clone\n+   containing the default declaration.  */\n \n bool\n is_function_default_version (const tree decl)\n@@ -1259,6 +1260,13 @@ is_function_default_version (const tree decl)\n     }\n   else\n     {\n+      if (lookup_attribute (\"target_clones\", DECL_ATTRIBUTES (decl)))\n+\t{\n+\t  int num_defaults = 0;\n+\t  get_clone_versions (decl, &num_defaults);\n+\t  return num_defaults > 0;\n+\t}\n+\n       attr = lookup_attribute (\"target_version\", DECL_ATTRIBUTES (decl));\n       if (!attr)\n \treturn true;\ndiff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc\nindex 86d2b60c83a0..a4d607a9a96a 100644\n--- a/gcc/c-family/c-attribs.cc\n+++ b/gcc/c-family/c-attribs.cc\n@@ -249,13 +249,6 @@ static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =\n   ATTR_EXCL (\"always_inline\", true, true, true),\n   ATTR_EXCL (\"target\", TARGET_HAS_FMV_TARGET_ATTRIBUTE,\n \t     TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),\n-  ATTR_EXCL (\"target_version\", true, true, true),\n-  ATTR_EXCL (NULL, false, false, false),\n-};\n-\n-static const struct attribute_spec::exclusions attr_target_version_exclusions[] =\n-{\n-  ATTR_EXCL (\"target_clones\", true, true, true),\n   ATTR_EXCL (NULL, false, false, false),\n };\n \n@@ -543,7 +536,7 @@ const struct attribute_spec c_common_gnu_attributes[] =\n \t\t\t      attr_target_exclusions },\n   { \"target_version\",         1, 1, true, false, false, false,\n \t\t\t      handle_target_version_attribute,\n-\t\t\t      attr_target_version_exclusions },\n+\t\t\t      NULL },\n   { \"target_clones\",          1, -1, true, false, false, false,\n \t\t\t      handle_target_clones_attribute,\n \t\t\t      attr_target_clones_exclusions },\ndiff --git a/gcc/cgraph.h b/gcc/cgraph.h\nindex a719321a538f..07d9cde01bda 100644\n--- a/gcc/cgraph.h\n+++ b/gcc/cgraph.h\n@@ -3120,6 +3120,13 @@ symbol_table::next_function_with_gimple_body (cgraph_node *node)\n    for ((node) = symtab->first_function (); (node); \\\n \t(node) = symtab->next_function ((node)))\n \n+/* Walk all functions but precompute so a node can be deleted if needed.  */\n+#define FOR_EACH_FUNCTION_REMOVABLE(node) \\\n+   cgraph_node *next; \\\n+   for ((node) = symtab->first_function (), \\\n+\tnext = (node) ? symtab->next_function ((node)) : NULL; (node); \\\n+\t(node) = next, next = (node) ? symtab->next_function ((node)) : NULL)\n+\n /* Return true when callgraph node is a function with Gimple body defined\n    in current unit.  Functions can also be define externally or they\n    can be thunks with no Gimple representation.\ndiff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc\nindex 02e868212e46..e85d7e71442d 100644\n--- a/gcc/multiple_target.cc\n+++ b/gcc/multiple_target.cc\n@@ -269,14 +269,28 @@ expand_target_clones (struct cgraph_node *node, bool definition)\n   auto_vec<string_slice> attr_list = get_clone_versions (node->decl,\n \t\t\t\t\t\t\t &num_defaults);\n \n+  /* If the target clones list is empty after filtering, remove this node.  */\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE && attr_list.is_empty ())\n+    {\n+      node->remove ();\n+      return false;\n+    }\n+\n   /* No need to clone for 1 target attribute.  */\n-  if (attr_list.length () == 1)\n+  if (attr_list.length () == 1 && TARGET_HAS_FMV_TARGET_ATTRIBUTE)\n     {\n       warning_at (DECL_SOURCE_LOCATION (node->decl),\n \t\t  0, \"single %<target_clones%> attribute is ignored\");\n       return false;\n     }\n \n+  /* For target_version semantics, a target clone with just a default version\n+     is the same as an unannotated decl, so can ignore.  */\n+  if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE\n+      && attr_list.length () == 1\n+      && num_defaults == 1)\n+    return false;\n+\n   if (node->definition\n       && (node->alias || !tree_versionable_function_p (node->decl)))\n     {\n@@ -304,8 +318,10 @@ expand_target_clones (struct cgraph_node *node, bool definition)\n \t\t\"multiple %<default%> targets were set\");\n       return false;\n     }\n-  /* Disallow target clones with no defaults.  */\n-  if (num_defaults == 0)\n+\n+  /* For target FMV semantics, where target and target_clone mixing\n+     is not supported, disallow target clones with no defaults.  */\n+  if (TARGET_HAS_FMV_TARGET_ATTRIBUTE && num_defaults == 0)\n     {\n       error_at (DECL_SOURCE_LOCATION (node->decl),\n \t\t\"%<default%> target was not set\");\n@@ -521,7 +537,7 @@ ipa_target_clone (bool early)\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+  FOR_EACH_FUNCTION_REMOVABLE (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.  */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc1.C b/gcc/testsuite/g++.target/aarch64/mv-and-mvc1.C\nnew file mode 100644\nindex 000000000000..24b81f5f5f3d\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc1.C\n@@ -0,0 +1,38 @@\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(\"default\")))\n+int foo ()\n+{\n+  return 0;\n+}\n+\n+__attribute__((target_clones(\"dotprod\", \"sve+sve2\")))\n+int foo ()\n+{\n+  return 1;\n+}\n+\n+__attribute__((target_clones(\"sve2+sme\", \"sve2+sme2\")))\n+int foo ()\n+{\n+  return 2;\n+}\n+\n+int bar()\n+{\n+  return foo ();\n+}\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+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme2:\\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-and-mvc2.C b/gcc/testsuite/g++.target/aarch64/mv-and-mvc2.C\nnew file mode 100644\nindex 000000000000..5939353d2d22\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc2.C\n@@ -0,0 +1,29 @@\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(\"default\")))\n+int foo ();\n+\n+__attribute__((target_clones(\"dotprod\", \"sve+sve2\")))\n+int foo ()\n+{\n+  return 1;\n+}\n+\n+__attribute__((target_clones(\"sve2+sme\", \"sve2+sme2\")))\n+int foo ()\n+{\n+  return 2;\n+}\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 0 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov:\\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\\._Msve2Msme:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme2:\\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 } } */\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc3.C b/gcc/testsuite/g++.target/aarch64/mv-and-mvc3.C\nnew file mode 100644\nindex 000000000000..fb1c596e9196\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc3.C\n@@ -0,0 +1,41 @@\n+/* { dg-do compile } */\n+/* { dg-require-ifunc \"\" } */\n+/* { dg-options \"-O0\" } */\n+/* { dg-additional-options \"-Wno-experimental-fmv-target\" } */\n+\n+__attribute__((target_clones(\"dotprod\", \"sve+sve2\")))\n+int foo ();\n+\n+__attribute__((target_version(\"default\")))\n+int foo ()\n+{\n+  return 0;\n+}\n+\n+__attribute__((target_clones(\"sve2+sme\", \"sve2+sme2\")))\n+int foo ()\n+{\n+  return 2;\n+}\n+\n+int bar()\n+{\n+  return foo ();\n+}\n+\n+\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\.default:\\n\" 1 } } */\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\\._Msve2Msme:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme2:\\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 } } */\n+// { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\.default\\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\\._MsveMsve2\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Msve2Msme\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n\\tadrp\\tx\\[0-9\\]+, _Z3foov\\._Msve2Msme2\\n\" 1 } } */\n+\ndiff --git a/gcc/testsuite/g++.target/aarch64/mv-and-mvc4.C b/gcc/testsuite/g++.target/aarch64/mv-and-mvc4.C\nnew file mode 100644\nindex 000000000000..e198fecc4cc3\n--- /dev/null\n+++ b/gcc/testsuite/g++.target/aarch64/mv-and-mvc4.C\n@@ -0,0 +1,38 @@\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\")))\n+int foo ()\n+{\n+  return 0;\n+}\n+\n+__attribute__((target_clones(\"default\", \"sve+sve2\")))\n+int foo ()\n+{\n+  return 1;\n+}\n+\n+__attribute__((target_clones(\"sve2+sme\", \"sve2+sme2\")))\n+int foo ()\n+{\n+  return 2;\n+}\n+\n+int bar()\n+{\n+  return foo ();\n+}\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+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme:\\n\" 1 } } */\n+/* { dg-final { scan-assembler-times \"\\n_Z3foov\\._Msve2Msme2:\\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 } } */\n","prefixes":["v1","08/13"]}