/* When NODE is a target clone, consider all callees and redirect
to a clone with equal target attributes. That prevents multiple
- multi-versioning dispatches and a call-chain can be optimized. */
+ multi-versioning dispatches and a call-chain can be optimized.
+
+ This optimisation might pick the wrong version in some cases, since knowing
+ that we meet the target requirements for a matching callee version does not
+ tell us that we won't also meet the target requirements for a higher
+ priority callee version at runtime. Since this is longstanding behaviour
+ for x86 and powerpc, we preserve it for those targets, but skip the optimisation
+ for targets that use the "target_version" attribute for multi-versioning. */
static void
redirect_to_specific_clone (cgraph_node *node)
if (fv == NULL)
return;
+ gcc_assert (TARGET_HAS_FMV_TARGET_ATTRIBUTE);
tree attr_target = lookup_attribute ("target", DECL_ATTRIBUTES (node->decl));
if (attr_target == NULL_TREE)
return;
for (unsigned i = 0; i < to_dispatch.length (); i++)
create_dispatcher_calls (to_dispatch[i]);
- FOR_EACH_FUNCTION (node)
- redirect_to_specific_clone (node);
+ if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)
+ FOR_EACH_FUNCTION (node)
+ redirect_to_specific_clone (node);
return 0;
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+#pragma GCC target ("+sve")
+
+__attribute__((target_version("default")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_version("sve2")))
+int foo ()
+{
+ return 2;
+}
+
+__attribute__((target_version("default")))
+int bar ()
+{
+ return foo();
+}
+
+__attribute__((target_version("sha3")))
+int bar ()
+{
+ return foo() + 5;
+}
+
+/* { dg-final { scan-assembler-times "\n\tbl\t_Z3foov\n" 2 } } */