From f80e0faf19690e5c92ca8b3eb5e920855e39c758 Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Tue, 12 Feb 2013 06:50:32 +0000 Subject: [PATCH] extend.texi: Document Function Multiversioning and "default" parameter string to target... * doc/extend.texi: Document Function Multiversioning and "default" parameter string to target attribute. * 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. * 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. From-SVN: r195967 --- gcc/ChangeLog | 11 +++++++ gcc/config/i386/i386.c | 25 ++++++--------- gcc/doc/extend.texi | 64 +++++++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 7 ++++ gcc/testsuite/g++.dg/ext/mv12-aux.C | 11 +++++++ gcc/testsuite/g++.dg/ext/mv12.C | 22 +++++++++++++ gcc/testsuite/g++.dg/ext/mv12.h | 6 ++++ gcc/testsuite/g++.dg/ext/mv13.C | 18 +++++++++++ 8 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/mv12-aux.C create mode 100644 gcc/testsuite/g++.dg/ext/mv12.C create mode 100644 gcc/testsuite/g++.dg/ext/mv12.h create mode 100644 gcc/testsuite/g++.dg/ext/mv13.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b99a9e5..360514e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2013-02-11 Sriraman Tallam + + * 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 Jack Howarth Patrick Marlier diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8826acd..caf4894 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -28696,6 +28696,9 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) 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 @@ -28828,14 +28831,8 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) 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; } @@ -29065,14 +29062,12 @@ ix86_mangle_function_version_assembler_name (tree decl, tree id) 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 @@ -29512,8 +29507,8 @@ ix86_generate_version_dispatcher_body (void *node_p) 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); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 34cbd3d..eb84408 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3655,6 +3655,11 @@ Enable/disable the generation of the advanced bit instructions. @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 virtual table dispatch. 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2add53a..4aa1b4c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-02-11 Sriraman Tallam + + * 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 * lib/target-supports.exp diff --git a/gcc/testsuite/g++.dg/ext/mv12-aux.C b/gcc/testsuite/g++.dg/ext/mv12-aux.C new file mode 100644 index 0000000..abdc142 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv12-aux.C @@ -0,0 +1,11 @@ +// 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; +} diff --git a/gcc/testsuite/g++.dg/ext/mv12.C b/gcc/testsuite/g++.dg/ext/mv12.C new file mode 100644 index 0000000..3ffb245 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv12.C @@ -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 "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; +} diff --git a/gcc/testsuite/g++.dg/ext/mv12.h b/gcc/testsuite/g++.dg/ext/mv12.h new file mode 100644 index 0000000..1d09f45 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv12.h @@ -0,0 +1,6 @@ +// 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"))); diff --git a/gcc/testsuite/g++.dg/ext/mv13.C b/gcc/testsuite/g++.dg/ext/mv13.C new file mode 100644 index 0000000..9554993 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv13.C @@ -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; +} -- 2.7.4