aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSriraman Tallam <tmsriram@google.com>2013-02-12 06:50:32 +0000
committerSriraman Tallam <tmsriram@gcc.gnu.org>2013-02-12 06:50:32 +0000
commitf80e0faf19690e5c92ca8b3eb5e920855e39c758 (patch)
treebffd76743900390a5af447e0f2216487f175ebad /gcc
parent6e1d47c46a7037d98885677fb4b43227f66c7c96 (diff)
downloadgcc-f80e0faf19690e5c92ca8b3eb5e920855e39c758.zip
gcc-f80e0faf19690e5c92ca8b3eb5e920855e39c758.tar.gz
gcc-f80e0faf19690e5c92ca8b3eb5e920855e39c758.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/i386/i386.c25
-rw-r--r--gcc/doc/extend.texi64
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/ext/mv12-aux.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/mv12.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/mv12.h6
-rw-r--r--gcc/testsuite/g++.dg/ext/mv13.C18
8 files changed, 149 insertions, 15 deletions
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 <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>
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 <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
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;
+}