public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Multiversioning fixes (PR c++/55742)
@ 2013-01-18 20:22 Jakub Jelinek
  2013-01-19 16:19 ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Jakub Jelinek @ 2013-01-18 20:22 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson, Sriraman Tallam; +Cc: gcc-patches

Hi!

As discussed in the PR, this patch attempts to change multiversioning
so that backwards compatibility with the previous target attribute behavior
is preserved.  In particular, e.g. for
void foo () __attribute__((target ("avx")));
void foo ()
{
}

the foo definition was just merged with the previous declaration and
used the avx target attribute.  The patch introduces
target ("default")
which should be used if a default multiversion variant is desirable.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

I've mentioned a bunch of other issues with multiversioning in the PR
(including missing documentation for the feature), hope those can be
resolved incrementally.

2013-01-18  Jakub Jelinek  <jakub@redhat.com>

	PR c++/55742
	* config/i386/i386.c (ix86_valid_target_attribute_inner_p): Diagnose
	invalid args instead of ICEing on it.
	(ix86_valid_target_attribute_p): Allow target("default") attribute.
	(sorted_attr_string): Formatting fix.
	(ix86_mangle_function_version_assembler_n): Mangle target("default")
	as if no target attribute is present.
	(ix86_function_versions): Don't return true if one of the decls
	doesn't have target attribute.  If they don't and one of the decls
	is DECL_FUNCTION_VERSIONED, report an error.
	(is_function_default_version): Return true if there is
	target("default") attribute rather than no target attribute at all.

	* g++.dg/mv1.C: Adjust test.
	* g++.dg/mv2.C: Likewise.
	* g++.dg/mv5.C: Likewise.
	* g++.dg/mv6.C: Likewise.

--- gcc/config/i386/i386.c.jj	2013-01-18 17:59:41.692943971 +0100
+++ gcc/config/i386/i386.c	2013-01-18 18:43:21.105326012 +0100
@@ -4223,7 +4223,10 @@ ix86_valid_target_attribute_inner_p (tre
     }
 
   else if (TREE_CODE (args) != STRING_CST)
-    gcc_unreachable ();
+    {
+      error ("invalid %<target%> attribute value");
+      return false;
+    }
 
   /* Handle multiple arguments separated by commas.  */
   next_optstr = ASTRDUP (TREE_STRING_POINTER (args));
@@ -4433,6 +4436,15 @@ ix86_valid_target_attribute_p (tree fnde
 {
   struct cl_target_option cur_target;
   bool ret = true;
+
+  /* attribute((target("default"))) does nothing, beyond
+     affecting multi-versioning.  */
+  if (TREE_VALUE (args)
+      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+      && TREE_CHAIN (args) == NULL_TREE
+      && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
+    return true;
+
   tree old_optimize = build_optimization_node ();
   tree new_target, new_optimize;
   tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
@@ -28964,7 +28976,7 @@ sorted_attr_string (const char *str)
     if (str[i] == ',')
       argnum++;
 
-  attr_str = (char *)xmalloc (strlen (str) + 1);
+  attr_str = (char *) xmalloc (strlen (str) + 1);
   strcpy (attr_str, str);
 
   /* Replace "=,-" with "_".  */
@@ -29034,6 +29046,9 @@ ix86_mangle_function_version_assembler_n
   version_string
     = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr)));
 
+  if (strcmp (version_string, "default") == 0)
+    return id;
+
   attr_str = sorted_attr_string (version_string);
   assembler_name = (char *) xmalloc (strlen (orig_name)
 				     + strlen (attr_str) + 2);
@@ -29058,7 +29073,7 @@ ix86_function_versions (tree fn1, tree f
   const char *attr_str1, *attr_str2;
   char *target1, *target2;
   bool result;
-  
+
   if (TREE_CODE (fn1) != FUNCTION_DECL
       || TREE_CODE (fn2) != FUNCTION_DECL)
     return false;
@@ -29070,12 +29085,35 @@ ix86_function_versions (tree fn1, tree f
   if (attr1 == NULL_TREE && attr2 == NULL_TREE)
     return false;
 
-  /* If one function does not have a target attribute, these are versions.  */
+  /* Diagnose missing target attribute if one of the decls is already
+     multi-versioned.  */
   if (attr1 == NULL_TREE || attr2 == NULL_TREE)
-    return true;
+    {
+      if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
+	{
+	  if (attr2 != NULL_TREE)
+	    {
+	      tree tem = fn1;
+	      fn1 = fn2;
+	      fn2 = tem;
+	      attr1 = attr2;
+	    }
+	  error_at (DECL_SOURCE_LOCATION (fn2),
+		    "missing %<target%> attribute for multi-versioned %D",
+		    fn2);
+	  error_at (DECL_SOURCE_LOCATION (fn1),
+		    "previous declaration of %D", fn1);
+	  /* Prevent diagnosing of the same error multiple times.  */
+	  DECL_ATTRIBUTES (fn2)
+	    = tree_cons (get_identifier ("target"),
+			 copy_node (TREE_VALUE (attr1)),
+			 DECL_ATTRIBUTES (fn2));
+	}
+      return false;
+    }
 
-  attr_str1 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1)));
-  attr_str2 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2)));
+  attr_str1 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1)));
+  attr_str2 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2)));
 
   target1 = sorted_attr_string (attr_str1);
   target2 = sorted_attr_string (attr_str2);
@@ -29196,9 +29234,14 @@ make_dispatcher_decl (const tree decl)
 static bool
 is_function_default_version (const tree decl)
 {
-  return (TREE_CODE (decl) == FUNCTION_DECL
-	  && DECL_FUNCTION_VERSIONED (decl)
-	  && lookup_attribute ("target", DECL_ATTRIBUTES (decl)) == NULL_TREE);
+  if (TREE_CODE (decl) != FUNCTION_DECL
+      || !DECL_FUNCTION_VERSIONED (decl))
+    return false;
+  tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
+  gcc_assert (attr);
+  attr = TREE_VALUE (TREE_VALUE (attr));
+  return (TREE_CODE (attr) == STRING_CST
+	  && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
 }
 
 /* Make a dispatcher declaration for the multi-versioned function DECL.
--- gcc/testsuite/g++.dg/mv1.C.jj	2013-01-18 17:59:41.567944606 +0100
+++ gcc/testsuite/g++.dg/mv1.C	2013-01-18 18:31:36.223533556 +0100
@@ -6,7 +6,7 @@
 #include <assert.h>
 
 /* Default version.  */
-int foo ();
+int foo () __attribute__ ((target("default")));
 /* The other versions of foo.  Mix up the ordering and 
    check if the dispatching does it in the order of priority. */
 /* Check combination of target attributes.  */
@@ -65,7 +65,8 @@ int main ()
   return 0;
 }
 
-int foo ()
+int __attribute__ ((target("default")))
+foo ()
 {
   return 0;
 }
--- gcc/testsuite/g++.dg/mv2.C.jj	2013-01-18 17:59:41.456945279 +0100
+++ gcc/testsuite/g++.dg/mv2.C	2013-01-18 18:31:36.224533535 +0100
@@ -7,7 +7,7 @@
 #include <assert.h>
 
 /* Default version.  */
-int foo ();
+int foo () __attribute__ ((target ("default")));
 /* The dispatch checks should be in the exact reverse order of the
    declarations below.  */
 int foo () __attribute__ ((target ("mmx")));
@@ -51,7 +51,7 @@ int main ()
   return 0;
 }
 
-int
+int __attribute__ ((target("default")))
 foo ()
 {
   return 0;
--- gcc/testsuite/g++.dg/mv5.C.jj	2013-01-18 17:59:41.587944512 +0100
+++ gcc/testsuite/g++.dg/mv5.C	2013-01-18 18:31:36.224533535 +0100
@@ -7,7 +7,7 @@
 
 
 /* Default version.  */
-inline int
+inline int __attribute__ ((target ("default")))
 foo ()
 {
   return 0;
--- gcc/testsuite/g++.dg/mv6.C.jj	2013-01-18 17:59:41.507944953 +0100
+++ gcc/testsuite/g++.dg/mv6.C	2013-01-18 18:31:36.224533535 +0100
@@ -8,6 +8,7 @@ class Foo
 {
  public:
   /* Default version of foo.  */
+  __attribute__ ((target("default")))
   int foo ()
   {
     return 0;


	Jakub

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742)
  2013-01-18 20:22 [PATCH] Multiversioning fixes (PR c++/55742) Jakub Jelinek
@ 2013-01-19 16:19 ` Jason Merrill
  2013-01-21 14:33   ` [PATCH] Multiversioning fixes (PR c++/55742, take 2) Jakub Jelinek
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2013-01-19 16:19 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Richard Henderson, Sriraman Tallam, gcc-patches

On 01/18/2013 03:22 PM, Jakub Jelinek wrote:
>     else if (TREE_CODE (args) != STRING_CST)
> -    gcc_unreachable ();
> +    {
> +      error ("invalid %<target%> attribute value");
> +      return false;
> +    }

Maybe say that it needs to be a string?

We also need more tests, both for the example in the PR (and your 
introductory text) and for error cases.

Thanks,
Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-01-19 16:19 ` Jason Merrill
@ 2013-01-21 14:33   ` Jakub Jelinek
  2013-01-30 13:55     ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Jakub Jelinek @ 2013-01-21 14:33 UTC (permalink / raw)
  To: Jason Merrill, Richard Henderson; +Cc: Sriraman Tallam, gcc-patches

On Sat, Jan 19, 2013 at 11:19:04AM -0500, Jason Merrill wrote:
> On 01/18/2013 03:22 PM, Jakub Jelinek wrote:
> >    else if (TREE_CODE (args) != STRING_CST)
> >-    gcc_unreachable ();
> >+    {
> >+      error ("invalid %<target%> attribute value");
> >+      return false;
> >+    }
> 
> Maybe say that it needs to be a string?

Fixed, using the wording of another attribute handler in c-common.c.

> We also need more tests, both for the example in the PR (and your
> introductory text) and for error cases.

Added a few ones, merged the patch with the incremental one, fixed handling
of target ("popcnt", "avx") as opposed to target ("popcnt,avx") that was
the only thing handled before by mv, fixed a bunch of memory leaks and
formatting issues, moved tests to g++.dg/ext/ and added a couple of new
ones.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

I hope documentation (which is for multiversioning missing completely right
now) and further testcases can be added incrementally.

2013-01-21  Jakub Jelinek  <jakub@redhat.com>

	PR c++/55742
	* config/i386/i386.c (ix86_valid_target_attribute_inner_p): Diagnose
	invalid args instead of ICEing on it.
	(ix86_valid_target_attribute_tree): Return error_mark_node if
	ix86_valid_target_attribute_inner_p failed.
	(ix86_valid_target_attribute_p): Return false only if
	ix86_valid_target_attribute_tree returned error_mark_node.  Allow
	target("default") attribute.
	(sorted_attr_string): Change argument from const char * to tree,
	merge in all target attribute arguments rather than just one.
	Formatting fix.  Use XNEWVEC instead of xmalloc and XDELETEVEC
	instead of free.  Avoid using strcat.
	(ix86_mangle_function_version_assembler_name): Mangle
	target("default") as if no target attribute is present.  Adjust
	sorted_attr_string caller.  Avoid leaking memory.  Use XNEWVEC
	instead of xmalloc and XDELETEVEC instead of free.
	(ix86_function_versions): Don't return true if one of the decls
	doesn't have target attribute.  If they don't and one of the decls
	is DECL_FUNCTION_VERSIONED, report an error.  Adjust
	sorted_attr_string caller.  Use XDELETEVEC instead of free.
	(ix86_supports_function_versions): Remove.
	(make_name): Fix up formatting.
	(make_dispatcher_decl): Remove resolver_name and its initialization.
	Avoid leaking memory.
	(is_function_default_version): Return true if there is
	target("default") attribute rather than no target attribute at all.
	(make_resolver_func): Avoid leaking memory.
	(ix86_generate_version_dispatcher_body): Likewise.
	(TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Remove.
	* target.def (supports_function_versions): Remove.
	* doc/tm.texi.in (SUPPORTS_FUNCTION_VERSIONS): Remove.
	* doc/tm.texi: Regenerated.

	* c-common.c (handle_target_attribute): Revert 2012-12-26 change.

	* g++.dg/mv1.C: Moved to...
	* g++.dg/ext/mv1.C: ... here.  Adjust test.
	* g++.dg/mv2.C: Moved to...
	* g++.dg/ext/mv2.C: ... here.  Adjust test.
	* g++.dg/mv3.C: Moved to...
	* g++.dg/ext/mv3.C: ... here.
	* g++.dg/mv4.C: Moved to...
	* g++.dg/ext/mv4.C: ... here.
	* g++.dg/mv5.C: Moved to...
	* g++.dg/ext/mv5.C: ... here.  Adjust test.
	* g++.dg/mv6.C: Moved to...
	* g++.dg/ext/mv6.C: ... here.  Adjust test.
	* g++.dg/ext/mv7.C: New test.
	* g++.dg/ext/mv8.C: New test.
	* g++.dg/ext/mv9.C: New test.
	* g++.dg/ext/mv10.C: New test.
	* g++.dg/ext/mv11.C: New test.

--- gcc/config/i386/i386.c.jj	2013-01-21 10:57:08.325945469 +0100
+++ gcc/config/i386/i386.c	2013-01-21 12:02:59.384701394 +0100
@@ -4223,7 +4223,10 @@ ix86_valid_target_attribute_inner_p (tre
     }
 
   else if (TREE_CODE (args) != STRING_CST)
-    gcc_unreachable ();
+    {
+      error ("attribute %<target%> argument not a string");
+      return false;
+    }
 
   /* Handle multiple arguments separated by commas.  */
   next_optstr = ASTRDUP (TREE_STRING_POINTER (args));
@@ -4368,7 +4371,7 @@ ix86_valid_target_attribute_tree (tree a
   /* Process each of the options on the chain.  */
   if (! ix86_valid_target_attribute_inner_p (args, option_strings,
 					     &enum_opts_set))
-    return NULL_TREE;
+    return error_mark_node;
 
   /* If the changed options are different from the default, rerun
      ix86_option_override_internal, and then save the options away.
@@ -4433,6 +4436,15 @@ ix86_valid_target_attribute_p (tree fnde
 {
   struct cl_target_option cur_target;
   bool ret = true;
+
+  /* attribute((target("default"))) does nothing, beyond
+     affecting multi-versioning.  */
+  if (TREE_VALUE (args)
+      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+      && TREE_CHAIN (args) == NULL_TREE
+      && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
+    return true;
+
   tree old_optimize = build_optimization_node ();
   tree new_target, new_optimize;
   tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
@@ -4449,10 +4461,10 @@ ix86_valid_target_attribute_p (tree fnde
   new_target = ix86_valid_target_attribute_tree (args);
   new_optimize = build_optimization_node ();
 
-  if (!new_target)
+  if (new_target == error_mark_node)
     ret = false;
 
-  else if (fndecl)
+  else if (fndecl && new_target)
     {
       DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
 
@@ -28946,26 +28958,44 @@ attr_strcmp (const void *v1, const void
   return strcmp (c1, c2);
 }
 
-/* STR is the argument to target attribute.  This function tokenizes
+/* ARGLIST is the argument to target attribute.  This function tokenizes
    the comma separated arguments, sorts them and returns a string which
    is a unique identifier for the comma separated arguments.   It also
    replaces non-identifier characters "=,-" with "_".  */
 
 static char *
-sorted_attr_string (const char *str)
+sorted_attr_string (tree arglist)
 {
+  tree arg;
+  size_t str_len_sum = 0;
   char **args = NULL;
   char *attr_str, *ret_str;
   char *attr = NULL;
   unsigned int argnum = 1;
   unsigned int i;
 
-  for (i = 0; i < strlen (str); i++)
-    if (str[i] == ',')
-      argnum++;
-
-  attr_str = (char *)xmalloc (strlen (str) + 1);
-  strcpy (attr_str, str);
+  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
+    {
+      const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
+      size_t len = strlen (str);
+      str_len_sum += len + 1;
+      if (arg != arglist)
+	argnum++;
+      for (i = 0; i < strlen (str); i++)
+	if (str[i] == ',')
+	  argnum++;
+    }
+
+  attr_str = XNEWVEC (char, str_len_sum);
+  str_len_sum = 0;
+  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
+    {
+      const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
+      size_t len = strlen (str);
+      memcpy (attr_str + str_len_sum, str, len);
+      attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
+      str_len_sum += len + 1;
+    }
 
   /* Replace "=,-" with "_".  */
   for (i = 0; i < strlen (attr_str); i++)
@@ -28986,18 +29016,20 @@ sorted_attr_string (const char *str)
       attr = strtok (NULL, ",");
     }
 
-  qsort (args, argnum, sizeof (char*), attr_strcmp);
+  qsort (args, argnum, sizeof (char *), attr_strcmp);
 
-  ret_str = (char *)xmalloc (strlen (str) + 1);
-  strcpy (ret_str, args[0]);
-  for (i = 1; i < argnum; i++)
+  ret_str = XNEWVEC (char, str_len_sum);
+  str_len_sum = 0;
+  for (i = 0; i < argnum; i++)
     {
-      strcat (ret_str, "_");
-      strcat (ret_str, args[i]);
+      size_t len = strlen (args[i]);
+      memcpy (ret_str + str_len_sum, args[i], len);
+      ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0';
+      str_len_sum += len + 1;
     }
 
-  free (args);
-  free (attr_str);
+  XDELETEVEC (args);
+  XDELETEVEC (attr_str);
   return ret_str;
 }
 
@@ -29009,8 +29041,8 @@ static tree
 ix86_mangle_function_version_assembler_name (tree decl, tree id)
 {
   tree version_attr;
-  const char *orig_name, *version_string, *attr_str;
-  char *assembler_name;
+  const char *orig_name, *version_string;
+  char *attr_str, *assembler_name;
 
   if (DECL_DECLARED_INLINE_P (decl)
       && lookup_attribute ("gnu_inline",
@@ -29034,9 +29066,11 @@ ix86_mangle_function_version_assembler_n
   version_string
     = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr)));
 
-  attr_str = sorted_attr_string (version_string);
-  assembler_name = (char *) xmalloc (strlen (orig_name)
-				     + strlen (attr_str) + 2);
+  if (strcmp (version_string, "default") == 0)
+    return id;
+
+  attr_str = sorted_attr_string (TREE_VALUE (version_attr));
+  assembler_name = XNEWVEC (char, strlen (orig_name) + strlen (attr_str) + 2);
 
   sprintf (assembler_name, "%s.%s", orig_name, attr_str);
 
@@ -29044,7 +29078,10 @@ ix86_mangle_function_version_assembler_n
   if (DECL_ASSEMBLER_NAME_SET_P (decl))
     SET_DECL_RTL (decl, NULL);
 
-  return get_identifier (assembler_name);
+  tree ret = get_identifier (assembler_name);
+  XDELETEVEC (attr_str);
+  XDELETEVEC (assembler_name);
+  return ret;
 }
 
 /* This function returns true if FN1 and FN2 are versions of the same function,
@@ -29055,10 +29092,9 @@ static bool
 ix86_function_versions (tree fn1, tree fn2)
 {
   tree attr1, attr2;
-  const char *attr_str1, *attr_str2;
   char *target1, *target2;
   bool result;
-  
+
   if (TREE_CODE (fn1) != FUNCTION_DECL
       || TREE_CODE (fn2) != FUNCTION_DECL)
     return false;
@@ -29070,15 +29106,35 @@ ix86_function_versions (tree fn1, tree f
   if (attr1 == NULL_TREE && attr2 == NULL_TREE)
     return false;
 
-  /* If one function does not have a target attribute, these are versions.  */
+  /* Diagnose missing target attribute if one of the decls is already
+     multi-versioned.  */
   if (attr1 == NULL_TREE || attr2 == NULL_TREE)
-    return true;
-
-  attr_str1 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1)));
-  attr_str2 =  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2)));
+    {
+      if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
+	{
+	  if (attr2 != NULL_TREE)
+	    {
+	      tree tem = fn1;
+	      fn1 = fn2;
+	      fn2 = tem;
+	      attr1 = attr2;
+	    }
+	  error_at (DECL_SOURCE_LOCATION (fn2),
+		    "missing %<target%> attribute for multi-versioned %D",
+		    fn2);
+	  error_at (DECL_SOURCE_LOCATION (fn1),
+		    "previous declaration of %D", fn1);
+	  /* Prevent diagnosing of the same error multiple times.  */
+	  DECL_ATTRIBUTES (fn2)
+	    = tree_cons (get_identifier ("target"),
+			 copy_node (TREE_VALUE (attr1)),
+			 DECL_ATTRIBUTES (fn2));
+	}
+      return false;
+    }
 
-  target1 = sorted_attr_string (attr_str1);
-  target2 = sorted_attr_string (attr_str2);
+  target1 = sorted_attr_string (TREE_VALUE (attr1));
+  target2 = sorted_attr_string (TREE_VALUE (attr2));
 
   /* The sorted target strings must be different for fn1 and fn2
      to be versions.  */
@@ -29087,20 +29143,12 @@ ix86_function_versions (tree fn1, tree f
   else
     result = true;
 
-  free (target1);
-  free (target2); 
+  XDELETEVEC (target1);
+  XDELETEVEC (target2); 
   
   return result;
 }
 
-/* This target supports function multiversioning.  */
-
-static bool
-ix86_supports_function_versions (void)
-{
-  return true;
-}
-
 static tree 
 ix86_mangle_decl_assembler_name (tree decl, tree id)
 {
@@ -29141,10 +29189,10 @@ make_name (tree decl, const char *suffix
 
   /* Use '.' to concatenate names as it is demangler friendly.  */
   if (make_unique)
-      snprintf (global_var_name, name_len, "%s.%s.%s", name,
-		unique_name, suffix);
+    snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name,
+	      suffix);
   else
-      snprintf (global_var_name, name_len, "%s.%s", name, suffix);
+    snprintf (global_var_name, name_len, "%s.%s", name, suffix);
 
   return global_var_name;
 }
@@ -29159,7 +29207,7 @@ static tree
 make_dispatcher_decl (const tree decl)
 {
   tree func_decl;
-  char *func_name, *resolver_name;
+  char *func_name;
   tree fn_type, func_type;
   bool is_uniq = false;
 
@@ -29167,14 +29215,13 @@ make_dispatcher_decl (const tree decl)
     is_uniq = true;
 
   func_name = make_name (decl, "ifunc", is_uniq);
-  resolver_name = make_name (decl, "resolver", is_uniq);
-  gcc_assert (resolver_name);
 
   fn_type = TREE_TYPE (decl);
   func_type = build_function_type (TREE_TYPE (fn_type),
 				   TYPE_ARG_TYPES (fn_type));
   
   func_decl = build_fn_decl (func_name, func_type);
+  XDELETEVEC (func_name);
   TREE_USED (func_decl) = 1;
   DECL_CONTEXT (func_decl) = NULL_TREE;
   DECL_INITIAL (func_decl) = error_mark_node;
@@ -29196,9 +29243,14 @@ make_dispatcher_decl (const tree decl)
 static bool
 is_function_default_version (const tree decl)
 {
-  return (TREE_CODE (decl) == FUNCTION_DECL
-	  && DECL_FUNCTION_VERSIONED (decl)
-	  && lookup_attribute ("target", DECL_ATTRIBUTES (decl)) == NULL_TREE);
+  if (TREE_CODE (decl) != FUNCTION_DECL
+      || !DECL_FUNCTION_VERSIONED (decl))
+    return false;
+  tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
+  gcc_assert (attr);
+  attr = TREE_VALUE (TREE_VALUE (attr));
+  return (TREE_CODE (attr) == STRING_CST
+	  && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
 }
 
 /* Make a dispatcher declaration for the multi-versioned function DECL.
@@ -29392,6 +29444,7 @@ make_resolver_func (const tree default_d
   /* Create the alias for dispatch to resolver here.  */
   /*cgraph_create_function_alias (dispatch_decl, decl);*/
   cgraph_same_body_alias (NULL, dispatch_decl, decl);
+  XDELETEVEC (resolver_name);
   return decl;
 }
 
@@ -29453,7 +29506,7 @@ ix86_generate_version_dispatcher_body (v
     }
 
   dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
-
+  fn_ver_vec.release ();
   rebuild_cgraph_edges (); 
   pop_cfun ();
   return resolver_decl;
@@ -42441,10 +42494,6 @@ ix86_memmodel_check (unsigned HOST_WIDE_
 #undef TARGET_OPTION_FUNCTION_VERSIONS
 #define TARGET_OPTION_FUNCTION_VERSIONS ix86_function_versions
 
-#undef TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS
-#define TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS \
-  ix86_supports_function_versions
-
 #undef TARGET_CAN_INLINE_P
 #define TARGET_CAN_INLINE_P ix86_can_inline_p
 
--- gcc/target.def.jj	2013-01-11 09:02:32.000000000 +0100
+++ gcc/target.def	2013-01-21 11:25:29.145124702 +0100
@@ -2831,14 +2831,6 @@ DEFHOOK
  bool, (tree decl1, tree decl2),
  hook_bool_tree_tree_false)
 
-/* This function returns true if the target supports function
-   multiversioning.  */
-DEFHOOK
-(supports_function_versions,
- "",
- bool, (void),
- hook_bool_void_false)
-
 /* Function to determine if one function can inline another function.  */
 #undef HOOK_PREFIX
 #define HOOK_PREFIX "TARGET_"
--- gcc/doc/tm.texi.in.jj	2013-01-11 09:02:26.000000000 +0100
+++ gcc/doc/tm.texi.in	2013-01-21 11:25:57.789962584 +0100
@@ -9768,11 +9768,6 @@ different target specific attributes, th
 different target machines.
 @end deftypefn
 
-@hook TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS
-This target hook returns @code{true} if the target supports function
-multiversioning.
-@end deftypefn
-
 @hook TARGET_CAN_INLINE_P
 This target hook returns @code{false} if the @var{caller} function
 cannot inline @var{callee}, based on target specific information.  By
--- gcc/doc/tm.texi.jj	2013-01-11 09:02:26.000000000 +0100
+++ gcc/doc/tm.texi	2013-01-21 11:26:08.647897014 +0100
@@ -9907,11 +9907,6 @@ different target specific attributes, th
 different target machines.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS (void)
-This target hook returns @code{true} if the target supports function
-multiversioning.
-@end deftypefn
-
 @deftypefn {Target Hook} bool TARGET_CAN_INLINE_P (tree @var{caller}, tree @var{callee})
 This target hook returns @code{false} if the @var{caller} function
 cannot inline @var{callee}, based on target specific information.  By
--- gcc/c-family/c-common.c.jj	2013-01-21 10:56:55.165014693 +0100
+++ gcc/c-family/c-common.c	2013-01-21 10:59:04.305285038 +0100
@@ -8759,12 +8759,8 @@ handle_target_attribute (tree *node, tre
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
-  /* Do not strip invalid target attributes for targets which support function
-     multiversioning as the target string is used to determine versioned
-     functions.  */
   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
-						      flags)
-	   && ! targetm.target_option.supports_function_versions ())
+						      flags))
     *no_add_attrs = true;
 
   return NULL_TREE;
--- gcc/testsuite/g++.dg/mv1.C.jj	2013-01-21 10:56:54.564017815 +0100
+++ gcc/testsuite/g++.dg/mv1.C	2013-01-21 11:35:42.260684508 +0100
@@ -1,130 +0,0 @@
-/* Test case to check if Multiversioning works.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
-/* { dg-require-ifunc "" }  */
-/* { dg-options "-O2 -fPIC" } */
-
-#include <assert.h>
-
-/* Default version.  */
-int foo ();
-/* The other versions of foo.  Mix up the ordering and 
-   check if the dispatching does it in the order of priority. */
-/* Check combination of target attributes.  */
-int foo () __attribute__ ((target("arch=corei7,popcnt")));
-/* The target operands in this declaration and the definition are re-ordered.
-   This should still work.  */
-int foo () __attribute__ ((target("ssse3,avx2")));
-
-/* Check for all target attributes for which dispatchers are available.  */
-/* Check arch= */
-int foo () __attribute__((target("arch=core2")));
-int foo () __attribute__((target("arch=corei7")));
-int foo () __attribute__((target("arch=atom")));
-/* Check ISAs  */
-int foo () __attribute__((target("avx")));
-int foo () __attribute__ ((target("arch=core2,sse4.2")));
-/* Check more arch=.  */
-int foo () __attribute__((target("arch=amdfam10")));
-int foo () __attribute__((target("arch=bdver1")));
-int foo () __attribute__((target("arch=bdver2")));
-
-int (*p)() = &foo;
-int main ()
-{
-  int val = foo ();
-  assert (val ==  (*p)());
-
-  /* Check in the exact same order in which the dispatching
-     is expected to happen.  */
-  if (__builtin_cpu_is ("bdver1"))
-    assert (val == 1);
-  else if (__builtin_cpu_is ("bdver2"))
-    assert (val == 2);
-  else if (__builtin_cpu_supports ("avx2")
-	   && __builtin_cpu_supports ("ssse3"))
-    assert (val == 3);
-  else if (__builtin_cpu_supports ("avx"))
-    assert (val == 4);
-  else if (__builtin_cpu_is ("corei7")
-	   && __builtin_cpu_supports ("popcnt"))
-    assert (val == 5);
-  else if (__builtin_cpu_is ("corei7"))
-    assert (val == 6);
-  else if (__builtin_cpu_is ("amdfam10h"))
-    assert (val == 7);
-  else if (__builtin_cpu_is ("core2")
-	   && __builtin_cpu_supports ("sse4.2"))
-    assert (val == 8);
-  else if (__builtin_cpu_is ("core2"))
-    assert (val == 9);
-  else if (__builtin_cpu_is ("atom"))
-    assert (val == 10);
-  else
-    assert (val == 0);
-  
-  return 0;
-}
-
-int foo ()
-{
-  return 0;
-}
-
-int __attribute__ ((target("arch=corei7,popcnt")))
-foo ()
-{
-  return 5;
-}
-int __attribute__ ((target("avx2,ssse3")))
-foo ()
-{
-  return 3;
-}
-
-int __attribute__ ((target("arch=core2")))
-foo ()
-{
-  return 9;
-}
-
-int __attribute__ ((target("arch=corei7")))
-foo ()
-{
-  return 6;
-}
-
-int __attribute__ ((target("arch=atom")))
-foo ()
-{
-  return 10;
-}
-
-int __attribute__ ((target("avx")))
-foo ()
-{
-  return 4;
-}
-
-int __attribute__ ((target("arch=core2,sse4.2")))
-foo ()
-{
-  return 8;
-}
-
-int __attribute__ ((target("arch=amdfam10")))
-foo ()
-{
-  return 7;
-}
-
-int __attribute__ ((target("arch=bdver1")))
-foo ()
-{
-  return 1;
-}
-
-int __attribute__ ((target("arch=bdver2")))
-foo ()
-{
-  return 2;
-}
--- gcc/testsuite/g++.dg/ext/mv1.C.jj	2013-01-21 11:36:16.084491175 +0100
+++ gcc/testsuite/g++.dg/ext/mv1.C	2013-01-21 11:42:52.975315718 +0100
@@ -0,0 +1,132 @@
+/* Test case to check if Multiversioning works.  */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O2 -fPIC" } */
+
+#include <assert.h>
+
+/* Default version.  */
+int foo (); // Extra declaration that is merged with the second one.
+int foo () __attribute__ ((target("default")));
+/* The other versions of foo.  Mix up the ordering and 
+   check if the dispatching does it in the order of priority. */
+/* Check combination of target attributes.  */
+int foo () __attribute__ ((target("arch=corei7,popcnt")));
+/* The target operands in this declaration and the definition are re-ordered.
+   This should still work.  */
+int foo () __attribute__ ((target("ssse3,avx2")));
+
+/* Check for all target attributes for which dispatchers are available.  */
+/* Check arch= */
+int foo () __attribute__((target("arch=core2")));
+int foo () __attribute__((target("arch=corei7")));
+int foo () __attribute__((target("arch=atom")));
+/* Check ISAs  */
+int foo () __attribute__((target("avx")));
+int foo () __attribute__ ((target("arch=core2,sse4.2")));
+/* Check more arch=.  */
+int foo () __attribute__((target("arch=amdfam10")));
+int foo () __attribute__((target("arch=bdver1")));
+int foo () __attribute__((target("arch=bdver2")));
+
+int (*p)() = &foo;
+int main ()
+{
+  int val = foo ();
+  assert (val ==  (*p)());
+
+  /* Check in the exact same order in which the dispatching
+     is expected to happen.  */
+  if (__builtin_cpu_is ("bdver1"))
+    assert (val == 1);
+  else if (__builtin_cpu_is ("bdver2"))
+    assert (val == 2);
+  else if (__builtin_cpu_supports ("avx2")
+	   && __builtin_cpu_supports ("ssse3"))
+    assert (val == 3);
+  else if (__builtin_cpu_supports ("avx"))
+    assert (val == 4);
+  else if (__builtin_cpu_is ("corei7")
+	   && __builtin_cpu_supports ("popcnt"))
+    assert (val == 5);
+  else if (__builtin_cpu_is ("corei7"))
+    assert (val == 6);
+  else if (__builtin_cpu_is ("amdfam10h"))
+    assert (val == 7);
+  else if (__builtin_cpu_is ("core2")
+	   && __builtin_cpu_supports ("sse4.2"))
+    assert (val == 8);
+  else if (__builtin_cpu_is ("core2"))
+    assert (val == 9);
+  else if (__builtin_cpu_is ("atom"))
+    assert (val == 10);
+  else
+    assert (val == 0);
+  
+  return 0;
+}
+
+int __attribute__ ((target("default")))
+foo ()
+{
+  return 0;
+}
+
+int __attribute__ ((target("arch=corei7,popcnt")))
+foo ()
+{
+  return 5;
+}
+int __attribute__ ((target("avx2,ssse3")))
+foo ()
+{
+  return 3;
+}
+
+int __attribute__ ((target("arch=core2")))
+foo ()
+{
+  return 9;
+}
+
+int __attribute__ ((target("arch=corei7")))
+foo ()
+{
+  return 6;
+}
+
+int __attribute__ ((target("arch=atom")))
+foo ()
+{
+  return 10;
+}
+
+int __attribute__ ((target("avx")))
+foo ()
+{
+  return 4;
+}
+
+int __attribute__ ((target("arch=core2,sse4.2")))
+foo ()
+{
+  return 8;
+}
+
+int __attribute__ ((target("arch=amdfam10")))
+foo ()
+{
+  return 7;
+}
+
+int __attribute__ ((target("arch=bdver1")))
+foo ()
+{
+  return 1;
+}
+
+int __attribute__ ((target("arch=bdver2")))
+foo ()
+{
+  return 2;
+}
--- gcc/testsuite/g++.dg/mv2.C.jj	2013-01-21 10:56:54.465018354 +0100
+++ gcc/testsuite/g++.dg/mv2.C	2013-01-21 11:35:45.088666745 +0100
@@ -1,118 +0,0 @@
-/* Test case to check if Multiversioning chooses the correct
-   dispatching order when versions are for various ISAs.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
-/* { dg-require-ifunc "" }  */
-/* { dg-options "-O2" } */
-
-#include <assert.h>
-
-/* Default version.  */
-int foo ();
-/* The dispatch checks should be in the exact reverse order of the
-   declarations below.  */
-int foo () __attribute__ ((target ("mmx")));
-int foo () __attribute__ ((target ("sse")));
-int foo () __attribute__ ((target ("sse2")));
-int foo () __attribute__ ((target ("sse3")));
-int foo () __attribute__ ((target ("ssse3")));
-int foo () __attribute__ ((target ("sse4.1")));
-int foo () __attribute__ ((target ("sse4.2")));
-int foo () __attribute__ ((target ("popcnt")));
-int foo () __attribute__ ((target ("avx")));
-int foo () __attribute__ ((target ("avx2")));
-
-int main ()
-{
-  int val = foo ();
-
-  if (__builtin_cpu_supports ("avx2"))
-    assert (val == 1);
-  else if (__builtin_cpu_supports ("avx"))
-    assert (val == 2);
-  else if (__builtin_cpu_supports ("popcnt"))
-    assert (val == 3);
-  else if (__builtin_cpu_supports ("sse4.2"))
-    assert (val == 4);
-  else if (__builtin_cpu_supports ("sse4.1"))
-    assert (val == 5);
-  else if (__builtin_cpu_supports ("ssse3"))
-    assert (val == 6);
-  else if (__builtin_cpu_supports ("sse3"))
-    assert (val == 7);
-  else if (__builtin_cpu_supports ("sse2"))
-    assert (val == 8);
-  else if (__builtin_cpu_supports ("sse"))
-    assert (val == 9);
-  else if (__builtin_cpu_supports ("mmx"))
-    assert (val == 10);
-  else
-    assert (val == 0);
-
-  return 0;
-}
-
-int
-foo ()
-{
-  return 0;
-}
-
-int __attribute__ ((target("mmx")))
-foo ()
-{
-  return 10;
-}
-
-int __attribute__ ((target("sse")))
-foo ()
-{
-  return 9;
-}
-
-int __attribute__ ((target("sse2")))
-foo ()
-{
-  return 8;
-}
-
-int __attribute__ ((target("sse3")))
-foo ()
-{
-  return 7;
-}
-
-int __attribute__ ((target("ssse3")))
-foo ()
-{
-  return 6;
-}
-
-int __attribute__ ((target("sse4.1")))
-foo ()
-{
-  return 5;
-}
-
-int __attribute__ ((target("sse4.2")))
-foo ()
-{
-  return 4;
-}
-
-int __attribute__ ((target("popcnt")))
-foo ()
-{
-  return 3;
-}
-
-int __attribute__ ((target("avx")))
-foo ()
-{
-  return 2;
-}
-
-int __attribute__ ((target("avx2")))
-foo ()
-{
-  return 1;
-}
--- gcc/testsuite/g++.dg/ext/mv2.C.jj	2013-01-21 11:36:16.085491165 +0100
+++ gcc/testsuite/g++.dg/ext/mv2.C	2013-01-21 10:58:57.000000000 +0100
@@ -0,0 +1,118 @@
+/* Test case to check if Multiversioning chooses the correct
+   dispatching order when versions are for various ISAs.  */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O2" } */
+
+#include <assert.h>
+
+/* Default version.  */
+int foo () __attribute__ ((target ("default")));
+/* The dispatch checks should be in the exact reverse order of the
+   declarations below.  */
+int foo () __attribute__ ((target ("mmx")));
+int foo () __attribute__ ((target ("sse")));
+int foo () __attribute__ ((target ("sse2")));
+int foo () __attribute__ ((target ("sse3")));
+int foo () __attribute__ ((target ("ssse3")));
+int foo () __attribute__ ((target ("sse4.1")));
+int foo () __attribute__ ((target ("sse4.2")));
+int foo () __attribute__ ((target ("popcnt")));
+int foo () __attribute__ ((target ("avx")));
+int foo () __attribute__ ((target ("avx2")));
+
+int main ()
+{
+  int val = foo ();
+
+  if (__builtin_cpu_supports ("avx2"))
+    assert (val == 1);
+  else if (__builtin_cpu_supports ("avx"))
+    assert (val == 2);
+  else if (__builtin_cpu_supports ("popcnt"))
+    assert (val == 3);
+  else if (__builtin_cpu_supports ("sse4.2"))
+    assert (val == 4);
+  else if (__builtin_cpu_supports ("sse4.1"))
+    assert (val == 5);
+  else if (__builtin_cpu_supports ("ssse3"))
+    assert (val == 6);
+  else if (__builtin_cpu_supports ("sse3"))
+    assert (val == 7);
+  else if (__builtin_cpu_supports ("sse2"))
+    assert (val == 8);
+  else if (__builtin_cpu_supports ("sse"))
+    assert (val == 9);
+  else if (__builtin_cpu_supports ("mmx"))
+    assert (val == 10);
+  else
+    assert (val == 0);
+
+  return 0;
+}
+
+int __attribute__ ((target("default")))
+foo ()
+{
+  return 0;
+}
+
+int __attribute__ ((target("mmx")))
+foo ()
+{
+  return 10;
+}
+
+int __attribute__ ((target("sse")))
+foo ()
+{
+  return 9;
+}
+
+int __attribute__ ((target("sse2")))
+foo ()
+{
+  return 8;
+}
+
+int __attribute__ ((target("sse3")))
+foo ()
+{
+  return 7;
+}
+
+int __attribute__ ((target("ssse3")))
+foo ()
+{
+  return 6;
+}
+
+int __attribute__ ((target("sse4.1")))
+foo ()
+{
+  return 5;
+}
+
+int __attribute__ ((target("sse4.2")))
+foo ()
+{
+  return 4;
+}
+
+int __attribute__ ((target("popcnt")))
+foo ()
+{
+  return 3;
+}
+
+int __attribute__ ((target("avx")))
+foo ()
+{
+  return 2;
+}
+
+int __attribute__ ((target("avx2")))
+foo ()
+{
+  return 1;
+}
--- gcc/testsuite/g++.dg/mv3.C.jj	2013-01-18 21:23:45.000000000 +0100
+++ gcc/testsuite/g++.dg/mv3.C	2013-01-21 11:35:52.400626435 +0100
@@ -1,36 +0,0 @@
-/* Test case to check if a call to a multiversioned function
-   is replaced with a direct call to the particular version when
-   the most specialized version's target attributes match the
-   caller.  
-  
-   In this program, foo is multiversioned but there is no default
-   function.  This is an error if the call has to go through a
-   dispatcher.  However, the call to foo in bar can be replaced
-   with a direct call to the popcnt version of foo.  Hence, this
-   test should pass.  */
-
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O2" } */
-
-
-int __attribute__ ((target ("sse")))
-foo ()
-{
-  return 1;
-}
-int __attribute__ ((target ("popcnt")))
-foo ()
-{
-  return 0;
-}
-
-int __attribute__ ((target ("popcnt")))
-bar ()
-{
-  return foo ();
-}
-
-int main ()
-{
-  return bar ();
-}
--- gcc/testsuite/g++.dg/ext/mv3.C.jj	2013-01-21 11:36:16.086491156 +0100
+++ gcc/testsuite/g++.dg/ext/mv3.C	2013-01-18 21:23:45.000000000 +0100
@@ -0,0 +1,36 @@
+/* Test case to check if a call to a multiversioned function
+   is replaced with a direct call to the particular version when
+   the most specialized version's target attributes match the
+   caller.  
+  
+   In this program, foo is multiversioned but there is no default
+   function.  This is an error if the call has to go through a
+   dispatcher.  However, the call to foo in bar can be replaced
+   with a direct call to the popcnt version of foo.  Hence, this
+   test should pass.  */
+
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+
+int __attribute__ ((target ("sse")))
+foo ()
+{
+  return 1;
+}
+int __attribute__ ((target ("popcnt")))
+foo ()
+{
+  return 0;
+}
+
+int __attribute__ ((target ("popcnt")))
+bar ()
+{
+  return foo ();
+}
+
+int main ()
+{
+  return bar ();
+}
--- gcc/testsuite/g++.dg/mv4.C.jj	2013-01-18 21:23:45.000000000 +0100
+++ gcc/testsuite/g++.dg/mv4.C	2013-01-21 11:35:54.308616223 +0100
@@ -1,24 +0,0 @@
-/* Test case to check if the compiler generates an error message
-   when the default version of a multiversioned function is absent
-   and its pointer is taken.  */
-
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-require-ifunc "" }  */
-/* { dg-options "-O2" } */
-
-int __attribute__ ((target ("sse")))
-foo ()
-{
-  return 1;
-}
-int __attribute__ ((target ("popcnt")))
-foo ()
-{
-  return 0;
-}
-
-int main ()
-{
-  int (*p)() = &foo; /* { dg-error "use of multiversioned function without a default" {} } */
-  return (*p)();
-}
--- gcc/testsuite/g++.dg/ext/mv4.C.jj	2013-01-21 11:36:16.088491133 +0100
+++ gcc/testsuite/g++.dg/ext/mv4.C	2013-01-18 21:23:45.000000000 +0100
@@ -0,0 +1,24 @@
+/* Test case to check if the compiler generates an error message
+   when the default version of a multiversioned function is absent
+   and its pointer is taken.  */
+
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O2" } */
+
+int __attribute__ ((target ("sse")))
+foo ()
+{
+  return 1;
+}
+int __attribute__ ((target ("popcnt")))
+foo ()
+{
+  return 0;
+}
+
+int main ()
+{
+  int (*p)() = &foo; /* { dg-error "use of multiversioned function without a default" {} } */
+  return (*p)();
+}
--- gcc/testsuite/g++.dg/mv5.C.jj	2013-01-21 10:56:54.582017723 +0100
+++ gcc/testsuite/g++.dg/mv5.C	2013-01-21 11:35:56.027606185 +0100
@@ -1,25 +0,0 @@
-/* Test case to check if multiversioned functions are still generated if they are
-   marked comdat with inline keyword.  */
-
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
-/* { dg-require-ifunc "" }  */
-/* { dg-options "-O2" } */
-
-
-/* Default version.  */
-inline int
-foo ()
-{
-  return 0;
-}
-
-inline int __attribute__ ((target ("popcnt")))
-foo ()
-{
-  return 0;
-}
-
-int main ()
-{
-  return foo ();
-}
--- gcc/testsuite/g++.dg/ext/mv5.C.jj	2013-01-21 11:36:16.089491123 +0100
+++ gcc/testsuite/g++.dg/ext/mv5.C	2013-01-21 10:58:57.000000000 +0100
@@ -0,0 +1,25 @@
+/* Test case to check if multiversioned functions are still generated if they are
+   marked comdat with inline keyword.  */
+
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O2" } */
+
+
+/* Default version.  */
+inline int __attribute__ ((target ("default")))
+foo ()
+{
+  return 0;
+}
+
+inline int __attribute__ ((target ("popcnt")))
+foo ()
+{
+  return 0;
+}
+
+int main ()
+{
+  return foo ();
+}
--- gcc/testsuite/g++.dg/mv6.C.jj	2013-01-21 10:56:54.504018081 +0100
+++ gcc/testsuite/g++.dg/mv6.C	2013-01-21 11:35:57.514597697 +0100
@@ -1,27 +0,0 @@
-/* Test to check if member version multiversioning works correctly.  */
-
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
-/* { dg-require-ifunc "" }  */
-/* { dg-options "-march=x86-64" } */
-
-class Foo
-{
- public:
-  /* Default version of foo.  */
-  int foo ()
-  {
-    return 0;
-  }
-  /* corei7 version of foo.  */
-  __attribute__ ((target("arch=corei7")))
-  int foo ()
-  {
-    return 0;
-  }
-};
-
-int main ()
-{
-  Foo f;
-  return f.foo ();
-}
--- gcc/testsuite/g++.dg/ext/mv6.C.jj	2013-01-21 11:36:16.090491117 +0100
+++ gcc/testsuite/g++.dg/ext/mv6.C	2013-01-21 10:58:57.000000000 +0100
@@ -0,0 +1,28 @@
+/* Test to check if member version multiversioning works correctly.  */
+
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-march=x86-64" } */
+
+class Foo
+{
+ public:
+  /* Default version of foo.  */
+  __attribute__ ((target("default")))
+  int foo ()
+  {
+    return 0;
+  }
+  /* corei7 version of foo.  */
+  __attribute__ ((target("arch=corei7")))
+  int foo ()
+  {
+    return 0;
+  }
+};
+
+int main ()
+{
+  Foo f;
+  return f.foo ();
+}
--- gcc/testsuite/g++.dg/ext/mv7.C.jj	2013-01-21 11:39:21.789460493 +0100
+++ gcc/testsuite/g++.dg/ext/mv7.C	2013-01-21 11:45:05.098589632 +0100
@@ -0,0 +1,12 @@
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+
+__attribute__((target ("default")))
+void foo (void)	// { dg-error "previously defined here" }
+{
+}
+
+__attribute__((target (128)))
+void foo (void) // { dg-error "(not a string|redefinition)" }
+{
+}
--- gcc/testsuite/g++.dg/ext/mv8.C.jj	2013-01-21 11:41:17.147836101 +0100
+++ gcc/testsuite/g++.dg/ext/mv8.C	2013-01-21 11:45:13.493544256 +0100
@@ -0,0 +1,7 @@
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+
+__attribute__((target (11,12)))
+void foo (void) // { dg-error "not a string" }
+{
+}
--- gcc/testsuite/g++.dg/ext/mv9.C.jj	2013-01-21 11:44:31.634774921 +0100
+++ gcc/testsuite/g++.dg/ext/mv9.C	2013-01-21 11:45:18.275516266 +0100
@@ -0,0 +1,9 @@
+// { dg-do compile { target i?86-*-* x86_64-*-* } }    
+// { dg-options "" }   
+
+void foo ();
+void foo () __attribute__((target ("sse4")));
+void foo () __attribute__((target ("default"))); // { dg-error "previous declaration" }
+void foo ()	// { dg-error "attribute for multi-versioned" }
+{
+}
--- gcc/testsuite/g++.dg/ext/mv10.C.jj	2013-01-21 12:12:29.354541630 +0100
+++ gcc/testsuite/g++.dg/ext/mv10.C	2013-01-21 12:12:56.207392886 +0100
@@ -0,0 +1,12 @@
+// { dg-do assemble { target i?86-*-* x86_64-*-* } }
+// { dg-options "" }
+
+__attribute__((target ("popcnt"), used))
+void foo (void)
+{
+}
+
+__attribute__((target ("popcnt","avx"), used))
+void foo (void)
+{
+}
--- gcc/testsuite/g++.dg/ext/mv11.C.jj	2013-01-21 12:16:26.381285535 +0100
+++ gcc/testsuite/g++.dg/ext/mv11.C	2013-01-21 12:17:33.380918996 +0100
@@ -0,0 +1,23 @@
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-options "-msse2" }
+
+int foo () __attribute__ ((target("default")));
+int foo () __attribute__ ((target("sse2")));
+
+int
+main ()
+{
+  return foo ();
+}
+
+int  __attribute__ ((target("default")))
+foo ()
+{
+  return 0;
+}
+
+int __attribute__ ((target("sse2")))
+foo ()
+{
+  return 0;
+}


	Jakub

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-01-21 14:33   ` [PATCH] Multiversioning fixes (PR c++/55742, take 2) Jakub Jelinek
@ 2013-01-30 13:55     ` Jason Merrill
  2013-02-07  1:39       ` Sriraman Tallam
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2013-01-30 13:55 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Richard Henderson, Sriraman Tallam, gcc-patches

OK.  Sriraman, are you working on documentation and more tests?

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-01-30 13:55     ` Jason Merrill
@ 2013-02-07  1:39       ` Sriraman Tallam
  2013-02-07 14:30         ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Sriraman Tallam @ 2013-02-07  1:39 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Jakub Jelinek, Richard Henderson, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

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

[-- Attachment #2: mv.txt --]
[-- Type: text/plain, Size: 6900 bytes --]

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-07  1:39       ` Sriraman Tallam
@ 2013-02-07 14:30         ` Jason Merrill
  2013-02-08  0:10           ` Sriraman Tallam
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2013-02-07 14:30 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Jakub Jelinek, Richard Henderson, GCC Patches

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-07 14:30         ` Jason Merrill
@ 2013-02-08  0:10           ` Sriraman Tallam
  2013-02-11 18:35             ` Sriraman Tallam
  2013-02-13  9:22             ` Andreas Schwab
  0 siblings, 2 replies; 13+ messages in thread
From: Sriraman Tallam @ 2013-02-08  0:10 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Jakub Jelinek, Richard Henderson, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 730 bytes --]

On Thu, Feb 7, 2013 at 6:29 AM, Jason Merrill <jason@redhat.com> wrote:
> 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.

Attached a new patch with these changes. Also made more minor changes
to config/i386/i386.c.

Thanks
Sri

>
> Jason
>

[-- Attachment #2: mv.txt --]
[-- Type: text/plain, Size: 8214 bytes --]

	* 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.

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/mv12-aux.C
===================================================================
--- gcc/testsuite/g++.dg/ext/mv12-aux.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/mv12-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 mv12.C.
+// { dg-do compile }
+
+#include "mv12.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,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;
+}
Index: gcc/testsuite/g++.dg/ext/mv12.h
===================================================================
--- gcc/testsuite/g++.dg/ext/mv12.h	(revision 0)
+++ gcc/testsuite/g++.dg/ext/mv12.h	(revision 0)
@@ -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")));
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,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)
@@ -28695,6 +28695,9 @@ get_builtin_code_for_version (tree decl, tree *pre
   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
@@ -28827,15 +28830,9 @@ get_builtin_code_for_version (tree decl, tree *pre
 static int
 ix86_compare_version_priority (tree decl1, tree decl2)
 {
-  unsigned int priority1 = 0;
-  unsigned int priority2 = 0;
+  unsigned int priority1 = get_builtin_code_for_version (decl1, NULL);
+  unsigned int priority2 = get_builtin_code_for_version (decl2, NULL);
 
-  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);
-
   return (int)priority1 - (int)priority2;
 }
 
@@ -29064,14 +29061,12 @@ 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");
+    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
@@ -29511,8 +29506,8 @@ ix86_generate_version_dispatcher_body (void *node_
 	 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);
     }
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-08  0:10           ` Sriraman Tallam
@ 2013-02-11 18:35             ` Sriraman Tallam
  2013-02-12  3:01               ` Jason Merrill
  2013-02-13  9:22             ` Andreas Schwab
  1 sibling, 1 reply; 13+ messages in thread
From: Sriraman Tallam @ 2013-02-11 18:35 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Jakub Jelinek, Richard Henderson, GCC Patches

Hi,

  Is this alright to commit?

Thanks
Sri

On Thu, Feb 7, 2013 at 4:10 PM, Sriraman Tallam <tmsriram@google.com> wrote:
> On Thu, Feb 7, 2013 at 6:29 AM, Jason Merrill <jason@redhat.com> wrote:
>> 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.
>
> Attached a new patch with these changes. Also made more minor changes
> to config/i386/i386.c.
>
> Thanks
> Sri
>
>>
>> Jason
>>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-11 18:35             ` Sriraman Tallam
@ 2013-02-12  3:01               ` Jason Merrill
  0 siblings, 0 replies; 13+ messages in thread
From: Jason Merrill @ 2013-02-12  3:01 UTC (permalink / raw)
  To: Sriraman Tallam; +Cc: Jakub Jelinek, Richard Henderson, GCC Patches

OK, thanks.

Jason

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-08  0:10           ` Sriraman Tallam
  2013-02-11 18:35             ` Sriraman Tallam
@ 2013-02-13  9:22             ` Andreas Schwab
       [not found]               ` <CAAs8HmyKtXHzTA+93PF5e+Ggd=zWDbO_s_ujdq92guPd4T+Zww@mail.gmail.com>
  1 sibling, 1 reply; 13+ messages in thread
From: Andreas Schwab @ 2013-02-13  9:22 UTC (permalink / raw)
  To: Sriraman Tallam
  Cc: Jason Merrill, Jakub Jelinek, Richard Henderson, GCC Patches

Sriraman Tallam <tmsriram@google.com> writes:

> Index: gcc/testsuite/g++.dg/ext/mv12-aux.C
> ===================================================================
> --- gcc/testsuite/g++.dg/ext/mv12-aux.C	(revision 0)
> +++ gcc/testsuite/g++.dg/ext/mv12-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 mv12.C.
> +// { dg-do compile }
> +
> +#include "mv12.h"
> +
> +__attribute__ ((target ("sse4.2")))
> +int foo ()

FAIL: g++.dg/ext/mv12-aux.C -std=c++11 (test for excess errors)
Excess errors:
/daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12.h:5:47: warning: target attribute is not supported on this machine [-Wattributes]
/daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12.h:6:46: warning: target attribute is not supported on this machine [-Wattributes]
/daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12-aux.C:8:10: warning: target attribute is not supported on this machine [-Wattributes]

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
       [not found]               ` <CAAs8HmyKtXHzTA+93PF5e+Ggd=zWDbO_s_ujdq92guPd4T+Zww@mail.gmail.com>
@ 2013-02-13 18:57                 ` Sriraman Tallam
  2013-02-13 20:14                   ` Jakub Jelinek
  0 siblings, 1 reply; 13+ messages in thread
From: Sriraman Tallam @ 2013-02-13 18:57 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Jason Merrill, GCC Patches, Richard Henderson, Jakub Jelinek

On Wed, Feb 13, 2013 at 7:46 AM, Sriraman Tallam <tmsriram@google.com> wrote:
>
> On Feb 13, 2013 1:21 AM, "Andreas Schwab" <schwab@suse.de> wrote:
>>
>> Sriraman Tallam <tmsriram@google.com> writes:
>>
>> > Index: gcc/testsuite/g++.dg/ext/mv12-aux.C
>> > ===================================================================
>> > --- gcc/testsuite/g++.dg/ext/mv12-aux.C       (revision 0)
>> > +++ gcc/testsuite/g++.dg/ext/mv12-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 mv12.C.
>> > +// { dg-do compile }
>> > +
>> > +#include "mv12.h"
>> > +
>> > +__attribute__ ((target ("sse4.2")))
>> > +int foo ()
>>
>> FAIL: g++.dg/ext/mv12-aux.C -std=c++11 (test for excess errors)
>> Excess errors:
>> /daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12.h:5:47:
>> warning: target attribute is not supported on this machine [-Wattributes]
>> /daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12.h:6:46:
>> warning: target attribute is not supported on this machine [-Wattributes]
>> /daten/aranym/gcc/gcc-20130213/gcc/testsuite/g++.dg/ext/mv12-aux.C:8:10:
>> warning: target attribute is not supported on this machine [-Wattributes]
>
> I will fix this asap. Sorry about this.

I committed a trivial patch to fix this problem. mv12-aux.C is
auxiliary to mv12.C and should have the same test directives as
mv12.C.

2013-02-13  Sriraman Tallam  <tmsriram@google.com>

        * g++.dg/ext/mv12-aux.C: Add directives to match mv12.C.


Index: g++.dg/ext/mv12-aux.C
===================================================================
--- g++.dg/ext/mv12-aux.C (revision 196025)
+++ g++.dg/ext/mv12-aux.C (working copy)
@@ -1,7 +1,10 @@
 // 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 }

+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+// { dg-require-ifunc "" }
+// { dg-options "-O2" }
+
 #include "mv12.h"

This should fix the problem.

Thanks
Sri


>
> Sri
>
>>
>> Andreas.
>>
>> --
>> Andreas Schwab, SUSE Labs, schwab@suse.de
>> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
>> "And now for something completely different."

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-13 18:57                 ` Sriraman Tallam
@ 2013-02-13 20:14                   ` Jakub Jelinek
  2013-02-13 21:53                     ` Sriraman Tallam
  0 siblings, 1 reply; 13+ messages in thread
From: Jakub Jelinek @ 2013-02-13 20:14 UTC (permalink / raw)
  To: Sriraman Tallam
  Cc: Andreas Schwab, Jason Merrill, GCC Patches, Richard Henderson

On Wed, Feb 13, 2013 at 10:57:42AM -0800, Sriraman Tallam wrote:
> I committed a trivial patch to fix this problem. mv12-aux.C is
> auxiliary to mv12.C and should have the same test directives as
> mv12.C.
> 
> 2013-02-13  Sriraman Tallam  <tmsriram@google.com>
> 
>         * g++.dg/ext/mv12-aux.C: Add directives to match mv12.C.

Better would be to rename
g++.dg/ext/mv12-aux.C to g++.dg/ext/mv12-aux.cc and remove all dg-*
directives from it, plus adjust dg-additional-sources in mv12.C.
The dg.exp driver is only looking for *.C testcases, so it will skip
*.cc, which is what you want.

> --- g++.dg/ext/mv12-aux.C (revision 196025)
> +++ g++.dg/ext/mv12-aux.C (working copy)
> @@ -1,7 +1,10 @@
>  // 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 }
> 
> +// { dg-do compile { target i?86-*-* x86_64-*-* } }
> +// { dg-require-ifunc "" }
> +// { dg-options "-O2" }
> +
>  #include "mv12.h"
> 
> This should fix the problem.

	Jakub

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] Multiversioning fixes (PR c++/55742, take 2)
  2013-02-13 20:14                   ` Jakub Jelinek
@ 2013-02-13 21:53                     ` Sriraman Tallam
  0 siblings, 0 replies; 13+ messages in thread
From: Sriraman Tallam @ 2013-02-13 21:53 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Andreas Schwab, Jason Merrill, GCC Patches, Richard Henderson

On Wed, Feb 13, 2013 at 12:14 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Feb 13, 2013 at 10:57:42AM -0800, Sriraman Tallam wrote:
>> I committed a trivial patch to fix this problem. mv12-aux.C is
>> auxiliary to mv12.C and should have the same test directives as
>> mv12.C.
>>
>> 2013-02-13  Sriraman Tallam  <tmsriram@google.com>
>>
>>         * g++.dg/ext/mv12-aux.C: Add directives to match mv12.C.
>
> Better would be to rename
> g++.dg/ext/mv12-aux.C to g++.dg/ext/mv12-aux.cc and remove all dg-*
> directives from it, plus adjust dg-additional-sources in mv12.C.
> The dg.exp driver is only looking for *.C testcases, so it will skip
> *.cc, which is what you want.

Committed patch which does exactly this.

2013-02-13  Sriraman Tallam  <tmsriram@google.com>

        * g++.dg/ext/mv12-aux.C: Delete, move to mv12-aux.cc.
        * g++.dg/ext/mv12-aux.cc: New file.
        * g++.dg/ext/mv12.h: Remove directives. Fix comment.
        * g++.dg/ext/mv12.C: Fix file name.

Index: mv12-aux.cc
===================================================================
--- mv12-aux.cc (revision 0)
+++ mv12-aux.cc (revision 0)
@@ -0,0 +1,10 @@
+// Test case to check if multiversioning works as expected when the versions
+// are defined in different files. Auxiliary file for mv12.C.
+
+#include "mv12.h"
+
+__attribute__ ((target ("sse4.2")))
+int foo ()
+{
+  return 1;
+}
Index: mv12.C
===================================================================
--- mv12.C (revision 196025)
+++ mv12.C (working copy)
@@ -4,7 +4,7 @@
 // { dg-do run { target i?86-*-* x86_64-*-* } }
 // { dg-require-ifunc "" }
 // { dg-options "-O2" }
-// { dg-additional-sources "mv12-aux.C" }
+// { dg-additional-sources "mv12-aux.cc" }

 #include "mv12.h"

Index: mv12.h
===================================================================
--- mv12.h (revision 196025)
+++ mv12.h (working copy)
@@ -1,6 +1,4 @@
-// Header file used by mv12.C and mv12-aux.C.
-// { dg-do compile { target i?86-*-* x86_64-*-* } }
-// { dg-options "" }
+// Header file used by mv12.C and mv12-aux.cc.

 int foo () __attribute__ ((target ("default")));
 int foo () __attribute__ ((target ("sse4.2")));
Index: mv12-aux.C
===================================================================
--- mv12-aux.C (revision 196025)
+++ mv12-aux.C (working copy)
@@ -1,14 +0,0 @@
-// 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 { target i?86-*-* x86_64-*-* } }
-// { dg-require-ifunc "" }
-// { dg-options "-O2" }
-
-#include "mv12.h"
-
-__attribute__ ((target ("sse4.2")))
-int foo ()
-{
-  return 1;
-}

Thanks
Sri


>
>> --- g++.dg/ext/mv12-aux.C (revision 196025)
>> +++ g++.dg/ext/mv12-aux.C (working copy)
>> @@ -1,7 +1,10 @@
>>  // 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 }
>>
>> +// { dg-do compile { target i?86-*-* x86_64-*-* } }
>> +// { dg-require-ifunc "" }
>> +// { dg-options "-O2" }
>> +
>>  #include "mv12.h"
>>
>> This should fix the problem.
>
>         Jakub

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2013-02-13 21:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-18 20:22 [PATCH] Multiversioning fixes (PR c++/55742) Jakub Jelinek
2013-01-19 16:19 ` Jason Merrill
2013-01-21 14:33   ` [PATCH] Multiversioning fixes (PR c++/55742, take 2) Jakub Jelinek
2013-01-30 13:55     ` Jason Merrill
2013-02-07  1:39       ` Sriraman Tallam
2013-02-07 14:30         ` Jason Merrill
2013-02-08  0:10           ` Sriraman Tallam
2013-02-11 18:35             ` Sriraman Tallam
2013-02-12  3:01               ` Jason Merrill
2013-02-13  9:22             ` Andreas Schwab
     [not found]               ` <CAAs8HmyKtXHzTA+93PF5e+Ggd=zWDbO_s_ujdq92guPd4T+Zww@mail.gmail.com>
2013-02-13 18:57                 ` Sriraman Tallam
2013-02-13 20:14                   ` Jakub Jelinek
2013-02-13 21:53                     ` Sriraman Tallam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).