+2013-02-11 Sriraman Tallam <tmsriramgoogle.com>
+
+ * doc/extend.texi: Document Function Multiversioning and "default"
+ parameter string to target attribute.
+ * config/i386/i386.c (get_builtin_code_for_version): Return 0 if
+ target attribute parameter is "default".
+ (ix86_compare_version_priority): Remove checks for target attribute.
+ (ix86_mangle_function_version_assembler_name): Change error to sorry.
+ Remove check for target attribute equal to NULL. Add assert.
+ (ix86_generate_version_dispatcher_body): Change error to sorry.
+
2013-02-11 Iain Sandoe <iain@codesourcery.com>
Jack Howarth <howarth@bromo.med.uc.edu>
Patrick Marlier <patrick.marlier@gmail.com>
gcc_assert (TREE_CODE (attrs) == STRING_CST);
attrs_str = TREE_STRING_POINTER (attrs);
+ /* Return priority zero for default function. */
+ if (strcmp (attrs_str, "default") == 0)
+ return 0;
/* Handle arch= if specified. For priority, set it to be 1 more than
the best instruction set the processor can handle. For instance, if
static int
ix86_compare_version_priority (tree decl1, tree decl2)
{
- unsigned int priority1 = 0;
- unsigned int priority2 = 0;
-
- if (lookup_attribute ("target", DECL_ATTRIBUTES (decl1)) != NULL)
- priority1 = get_builtin_code_for_version (decl1, NULL);
-
- if (lookup_attribute ("target", DECL_ATTRIBUTES (decl2)) != NULL)
- priority2 = get_builtin_code_for_version (decl2, NULL);
+ unsigned int priority1 = get_builtin_code_for_version (decl1, NULL);
+ unsigned int priority2 = get_builtin_code_for_version (decl2, NULL);
return (int)priority1 - (int)priority2;
}
if (DECL_VIRTUAL_P (decl)
|| DECL_VINDEX (decl))
- error_at (DECL_SOURCE_LOCATION (decl),
- "Virtual function versioning not supported\n");
+ sorry ("Virtual function multiversioning not supported");
version_attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
- /* target attribute string is NULL for default functions. */
- if (version_attr == NULL_TREE)
- return id;
+ /* target attribute string cannot be NULL. */
+ gcc_assert (version_attr != NULL_TREE);
orig_name = IDENTIFIER_POINTER (id);
version_string
virtual methods in base classes but are not explicitly marked as
virtual. */
if (DECL_VINDEX (versn->symbol.decl))
- error_at (DECL_SOURCE_LOCATION (versn->symbol.decl),
- "Virtual function multiversioning not supported");
+ sorry ("Virtual function multiversioning not supported");
+
fn_ver_vec.safe_push (versn->symbol.decl);
}
@cindex @code{target("aes")} attribute
Enable/disable the generation of the AES instructions.
+@item default
+@cindex @code{target("default")} attribute
+@xref{Function Multiversioning}, where it is used to specify the
+default function version.
+
@item mmx
@itemx no-mmx
@cindex @code{target("mmx")} attribute
* Bound member functions:: You can extract a function pointer to the
method denoted by a @samp{->*} or @samp{.*} expression.
* C++ Attributes:: Variable, function, and type attributes for C++ only.
+* Function Multiversioning:: Declaring multiple function versions.
* Namespace Association:: Strong using-directives for namespace association.
* Type Traits:: Compiler support for type traits
* Java Exceptions:: Tweaking exception handling to work with Java.
See also @ref{Namespace Association}.
+@node Function Multiversioning
+@section Function Multiversioning
+@cindex function versions
+
+With the GNU C++ front end, for target i386, you may specify multiple
+versions of a function, where each function is specialized for a
+specific target feature. At runtime, the appropriate version of the
+function is automatically executed depending on the characteristics of
+the execution platform. Here is an example.
+
+@smallexample
+__attribute__ ((target ("default")))
+int foo ()
+@{
+ // The default version of foo.
+ return 0;
+@}
+
+__attribute__ ((target ("sse4.2")))
+int foo ()
+@{
+ // foo version for SSE4.2
+ return 1;
+@}
+
+__attribute__ ((target ("arch=atom")))
+int foo ()
+@{
+ // foo version for the Intel ATOM processor
+ return 2;
+@}
+
+__attribute__ ((target ("arch=amdfam10")))
+int foo ()
+@{
+ // foo version for the AMD Family 0x10 processors.
+ return 3;
+@}
+
+int main ()
+@{
+ int (*p)() = &foo;
+ assert ((*p) () == foo ());
+ return 0;
+@}
+@end smallexample
+
+In the above example, four versions of function foo are created. The
+first version of foo with the target attribute "default" is the default
+version. This version gets executed when no other target specific
+version qualifies for execution on a particular platform. A new version
+of foo is created by using the same function signature but with a
+different target string. Function foo is called or a pointer to it is
+taken just like a regular function. GCC takes care of doing the
+dispatching to call the right version at runtime. Refer to the
+@uref{http://gcc.gnu.org/wiki/FunctionMultiVersioning, GCC wiki on
+Function Multiversioning} for more details.
+
@node Namespace Association
@section Namespace Association
+2013-02-11 Sriraman Tallam <tmsriramgoogle.com>
+
+ * g++.dg/ext/mv12.C: New test.
+ * g++.dg/ext/mv12.h: New file.
+ * g++.dg/ext/mv12-aux.C: New file.
+ * g++.dg/ext/mv13.C: New test.
+
2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
* lib/target-supports.exp
--- /dev/null
+// Test case to check if multiversioning works as expected when the versions
+// are defined in different files. Auxiliary file for mv12.C.
+// { dg-do compile }
+
+#include "mv12.h"
+
+__attribute__ ((target ("sse4.2")))
+int foo ()
+{
+ return 1;
+}
--- /dev/null
+// Test case to check if multiversioning works as expected when the versions
+// are defined in different files.
+
+// { dg-do run { target i?86-*-* x86_64-*-* } }
+// { dg-require-ifunc "" }
+// { dg-options "-O2" }
+// { dg-additional-sources "mv12-aux.C" }
+
+#include "mv12.h"
+
+int main ()
+{
+ if (__builtin_cpu_supports ("sse4.2"))
+ return foo () - 1;
+ return foo ();
+}
+
+__attribute__ ((target ("default")))
+int foo ()
+{
+ return 0;
+}
--- /dev/null
+// Header file used by mv12.C and mv12-aux.C.
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+
+int foo () __attribute__ ((target ("default")));
+int foo () __attribute__ ((target ("sse4.2")));
--- /dev/null
+// Test case to check if multiversioning functions that are extern "C"
+// generates errors.
+
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+
+extern "C"
+__attribute__ ((target ("default")))
+int foo () // { dg-error "previously defined here" }
+{
+ return 0;
+}
+
+extern "C"
+__attribute__ ((target ("sse4.2")))
+int foo () // { dg-error "redefinition" }
+{
+ return 1;
+}