Hi,
I have attached a patch documenting Function Multiversioning and
added a few more tests. I have also updated the wiki
http://gcc.gnu.org/wiki/FunctionMultiVersioning. Please let me know if
there are any more tests you specifically want.
Please review.
Thanks
Sri
On Wed, Jan 30, 2013 at 5:55 AM, Jason Merrill <[email protected]> wrote:
> OK. Sriraman, are you working on documentation and more tests?
>
> Jason
* doc/extend.texi: Document Function Multiversioning and "default"
parameter string to target attribute.
* g++.dg/ext/mv12.C: New test.
* g++.dg/ext/mv13.C: New test.
* g++.dg/ext/mv13.h: New file.
* g++.dg/ext/mv13-aux.C: New file.
* config/i386/i386.c (ix86_mangle_function_version_assembler_name):
Change
comment.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi (revision 195818)
+++ gcc/doc/extend.texi (working copy)
@@ -3655,6 +3655,11 @@ Enable/disable the generation of the advanced bit
@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
@@ -15215,6 +15220,7 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
* 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.
@@ -15744,6 +15750,64 @@ interface table mechanism, instead of regular virt
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
Index: gcc/testsuite/g++.dg/ext/mv13-aux.C
===================================================================
--- gcc/testsuite/g++.dg/ext/mv13-aux.C (revision 0)
+++ gcc/testsuite/g++.dg/ext/mv13-aux.C (revision 0)
@@ -0,0 +1,11 @@
+// Test case to check if multiversioning works as expected when the versions
+// are defined in different files. Auxiliary file for mv13.C.
+// { dg-do compile }
+
+#include "mv13.h"
+
+__attribute__ ((target ("sse4.2")))
+int foo ()
+{
+ return 1;
+}
Index: gcc/testsuite/g++.dg/ext/mv12.C
===================================================================
--- gcc/testsuite/g++.dg/ext/mv12.C (revision 0)
+++ gcc/testsuite/g++.dg/ext/mv12.C (revision 0)
@@ -0,0 +1,21 @@
+// Test to check if an error is generated when virtual functions
+// are multiversioned.
+
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+class Foo
+{
+ public:
+ /* Default version of foo. */
+ __attribute__ ((target("default")))
+ virtual int foo () // { dg-error "Virtual function multiversioning not
supported" }
+ {
+ return 0;
+ }
+ /* corei7 version of foo. */
+ __attribute__ ((target("arch=corei7")))
+ virtual int foo () // { dg-error "Virtual function multiversioning not
supported" }
+ {
+ return 0;
+ }
+};
Index: gcc/testsuite/g++.dg/ext/mv13.C
===================================================================
--- gcc/testsuite/g++.dg/ext/mv13.C (revision 0)
+++ gcc/testsuite/g++.dg/ext/mv13.C (revision 0)
@@ -0,0 +1,22 @@
+// 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 "mv13-aux.C" }
+
+#include "mv13.h"
+
+int main ()
+{
+ if (__builtin_cpu_supports ("sse4.2"))
+ return foo () - 1;
+ return foo ();
+}
+
+__attribute__ ((target ("default")))
+int foo ()
+{
+ return 0;
+}
Index: gcc/testsuite/g++.dg/ext/mv13.h
===================================================================
--- gcc/testsuite/g++.dg/ext/mv13.h (revision 0)
+++ gcc/testsuite/g++.dg/ext/mv13.h (revision 0)
@@ -0,0 +1,6 @@
+// Header file used by mv13.C and mv13-aux.C.
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+
+int foo () __attribute__ ((target ("default")));
+int foo () __attribute__ ((target ("sse4.2")));
Index: gcc/testsuite/g++.dg/ext/mv14.C
===================================================================
--- gcc/testsuite/g++.dg/ext/mv14.C (revision 0)
+++ gcc/testsuite/g++.dg/ext/mv14.C (revision 0)
@@ -0,0 +1,18 @@
+// 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;
+}
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c (revision 195818)
+++ gcc/config/i386/i386.c (working copy)
@@ -29065,7 +29065,7 @@ ix86_mangle_function_version_assembler_name (tree
if (DECL_VIRTUAL_P (decl)
|| DECL_VINDEX (decl))
error_at (DECL_SOURCE_LOCATION (decl),
- "Virtual function versioning not supported\n");
+ "Virtual function multiversioning not supported\n");
version_attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));