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 <ja...@redhat.com> 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));