Patchwork Multiversioning fixes (PR c++/55742, take 2)

login
register
mail settings
Submitter Sriraman Tallam
Date Feb. 7, 2013, 1:39 a.m.
Message ID <CAAs8HmyVs3i2v=MH+djkqROHEGbZXYE7Dyga9oCVO-v1ekiUYw@mail.gmail.com>
Download mbox | patch
Permalink /patch/218810/
State New
Headers show

Comments

Sriraman Tallam - Feb. 7, 2013, 1:39 a.m.
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 <jason@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.
Jason Merrill - Feb. 7, 2013, 2:29 p.m.
On 02/06/2013 08:39 PM, Sriraman Tallam wrote:
> +// Test to check if an error is generated when virtual functions
> +// are multiversioned.

This seems like a TODO, rather than something to test for.  I don't see 
any reason why we couldn't support multiversioned virtual functions.

>      error_at (DECL_SOURCE_LOCATION (decl),
> -	      "Virtual function versioning not supported\n");
> +	      "Virtual function multiversioning not supported\n");

And so this should be a sorry rather than an error.

Jason

Patch

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));