public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] New attribute to create target clones
@ 2015-08-27 11:35 Evgeny Stupachenko
  2015-09-08 11:47 ` Evgeny Stupachenko
  2015-09-21 13:43 ` Bernd Schmidt
  0 siblings, 2 replies; 36+ messages in thread
From: Evgeny Stupachenko @ 2015-08-27 11:35 UTC (permalink / raw)
  To: GCC Patches, Jan Hubicka, Jeff Law

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

Hi All,

Based on RFC:
https://gcc.gnu.org/ml/gcc-patches/2015-08/msg01322.html

The patch implement an extension to Function Multiversioning that
allows to clone a function for multiple targets.
__attribute__((target_clones("avx","arch=slm","default")))
int foo ()
...

Will create 3 clones of foo(). One optimized with -mavx, one optimized
with -march=slm, and one with default optimizations.
And will create ifunc resolver that calls appropriate clone (same as
in Function Multiversioning).

Bootstrap and make check for x86 passed.

Is it ok for trunk?

2015-08-27  Evgeny Stupachenko  <evstupac@gmail.com>

gcc/
        * Makefile.in (OBJS): Add multiple_target.o.
        * multiple_target.c (make_attribute): New.
        (create_dispatcher_calls): Ditto.
        (expand_target_clones): Ditto.
        (ipa_target_clone): Ditto.
        * passes.def (pass_target_clone): New ipa pass.
        * tree-pass.h (make_pass_target_clone): Ditto.

gcc/c-family
        * c-common.c (handle_target_clones_attribute): New.
        * (c_common_attribute_table): Add handle_target_clones_attribute.
        * (handle_always_inline_attribute): Add check on target_clones
        attribute.
        * (handle_target_attribute): Ditto.

gcc/testsuite
        * gcc.dg/mvc1.c: New test for multiple targets cloning.
        * gcc.dg/mvc2.c: Ditto.
        * gcc.dg/mvc3.c: Ditto.
        * gcc.dg/mvc4.c: Ditto.
        * gcc.dg/mvc5.c: Ditto.
        * gcc.dg/mvc6.c: Ditto.
        * gcc.dg/mvc7.c: Ditto.
        * g++.dg/ext/mvc1.C: Ditto.
        * g++.dg/ext/mvc2.C: Ditto.
        * g++.dg/ext/mvc3.C: Ditto.

gcc/doc
        * doc/extend.texi (target_clones): New attribute description.

[-- Attachment #2: target_clones.patch --]
[-- Type: application/octet-stream, Size: 20246 bytes --]

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e298ecc..fc12ab9 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1350,6 +1350,7 @@ OBJS = \
 	mcf.o \
 	mode-switching.o \
 	modulo-sched.o \
+	multiple_target.o \
 	omp-low.o \
 	optabs.o \
 	options-save.o \
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 7691035..31ba31f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -381,6 +381,7 @@ static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
 static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_target_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
 static tree ignore_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
@@ -788,6 +789,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_error_attribute, false },
   { "target",                 1, -1, true, false, false,
 			      handle_target_attribute, false },
+  { "target_clones",	      1, -1, true, false, false,
+			      handle_target_clones_attribute, false },
   { "optimize",               1, -1, true, false, false,
 			      handle_optimize_attribute, false },
   /* For internal use only.  The leading '*' both prevents its usage in
@@ -7363,6 +7366,13 @@ handle_always_inline_attribute (tree *node, tree name,
 		   "with %qs attribute", name, "noinline");
 	  *no_add_attrs = true;
 	}
+      else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute ignored as it conflict with target_clones",
+		   name);
+	  *no_add_attrs = true;
+	}
       else
 	/* Set the attribute and mark it for disregarding inline
 	   limits.  */
@@ -9774,6 +9784,12 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
+  else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (*node)))
+    {
+      warning (OPT_Wattributes,
+	       "%qE attribute ignored as it conflict with target_clones", name);
+      *no_add_attrs = true;
+    }
   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
 						      flags))
     *no_add_attrs = true;
@@ -9781,6 +9797,39 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
   return NULL_TREE;
 }
 
+/* Handle a "target_clones" attribute.  */
+
+static tree
+handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+			  int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  /* Ensure we have a function type.  */
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    {
+      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute ignored as it assumes noinline", name);
+	  *no_add_attrs = true;
+	}
+      else if (lookup_attribute ("target", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute ignored as it conflict with target", name);
+	  *no_add_attrs = true;
+	}
+      else
+      /* Do not inline functions with multiple clone targets.  */
+	DECL_UNINLINABLE (*node) = 1;
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  return NULL_TREE;
+}
+
 /* Arguments being collected for optimization.  */
 typedef const char *const_char_p;		/* For DEF_VEC_P.  */
 static GTY(()) vec<const_char_p, va_gc> *optimize_args;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index dba8b43..c0b5875 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3066,6 +3066,19 @@ This function attribute make a stack protection of the function if
 flags @option{fstack-protector} or @option{fstack-protector-strong}
 or @option{fstack-protector-explicit} are set.
 
+@item target_clones (@var{options})
+@cindex @code{target_clones} function attribute
+The @code{target_clones} attribute is used to specify that a function is to
+be cloned into multiple versions compiled with different target options
+than specified on the command line.  The supported options and restrictions
+are the same as for @code{target}.
+
+For instance on an x86, you could compile a function with
+@code{target_clones("sse4.1,avx")}.  It will create 2 function clones,
+one compiled with @option{-msse4.1} and another with @option{-mavx}.
+At the function call it will create resolver @code{ifunc}, that will
+dynamically call a clone suitable for current architecture.
+
 @item target (@var{options})
 @cindex @code{target} function attribute
 Multiple target back ends implement the @code{target} attribute
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
new file mode 100644
index 0000000..1946dba
--- /dev/null
+++ b/gcc/multiple_target.c
@@ -0,0 +1,331 @@
+/* Pass for parsing functions with multiple target attributes.
+
+   Contributed by Evgeny Stupachenko <evstupac@gmail.com>
+
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "gimple.h"
+#include "diagnostic-core.h"
+#include "gimple-ssa.h"
+#include "cgraph.h"
+#include "tree-pass.h"
+#include "target.h"
+#include "pretty-print.h"
+
+/* Makes a function attribute of the form NAME(ARG_NAME) and chains
+   it to CHAIN.  */
+
+static tree
+make_attribute (const char *name, const char *arg_name, tree chain)
+{
+  tree attr_name;
+  tree attr_arg_name;
+  tree attr_args;
+  tree attr;
+
+  attr_name = get_identifier (name);
+  attr_arg_name = build_string (strlen (arg_name), arg_name);
+  attr_args = tree_cons (NULL_TREE, attr_arg_name, NULL_TREE);
+  attr = tree_cons (attr_name, attr_args, chain);
+  return attr;
+}
+
+/* If the call in NODE has multiple target attribute with multiple fields,
+   replace it with dispatcher call and create dispatcher (once).  */
+
+static void
+create_dispatcher_calls (struct cgraph_node *node)
+{
+  cgraph_edge *e;
+  cgraph_edge *e_next;
+  for (e = node->callers; e ;e = (e == NULL) ? e_next : e->next_caller)
+    {
+      tree resolver_decl;
+      tree idecl;
+      tree decl;
+      gimple call = e->call_stmt;
+      struct cgraph_node *inode;
+
+      /* Checking if call of function is call of versioned function.
+	 Versioned function are not inlined, so there is no need to
+	 check for inline.  */
+      if (!call
+	  || !(decl = gimple_call_fndecl (call))
+	  || !DECL_FUNCTION_VERSIONED (decl))
+	continue;
+
+      e_next = e->next_caller;
+      idecl = targetm.get_function_versions_dispatcher (decl);
+      if (!idecl)
+	{
+	  error_at (gimple_location (call),
+		    "default target_clones attribute was not set");
+	}
+      inode = cgraph_node::get (idecl);
+      gcc_assert (inode);
+      resolver_decl = targetm.generate_version_dispatcher_body (inode);
+
+      /* Update aliases.  */
+      inode->alias = true;
+      inode->alias_target = resolver_decl;
+      if (!inode->analyzed)
+	inode->resolve_alias (cgraph_node::get (resolver_decl));
+      e->redirect_callee (inode);
+      gimple_call_set_fndecl (call, idecl);
+      /*  Force to move to next edge caller.  */
+      e = NULL;
+    }
+}
+
+/* If the function in NODE has multiple target attribute with multiple fields,
+   create the appropriate clone for each field.  */
+
+static bool
+expand_target_clones (struct cgraph_node *node)
+{
+  tree id;
+  /* Parsing target attributes separated by comma.  */
+  tree attr_target = lookup_attribute ("target_clones",
+				       DECL_ATTRIBUTES (node->decl));
+  /* No targets specified.  */
+  if (!attr_target)
+    return false;
+
+  tree arg;
+  tree arglist = TREE_VALUE (attr_target);
+  size_t str_len_sum = 0;
+  char **args = NULL;
+  char *attr_str;
+  char *attr = NULL;
+  int argnum = 1;
+  int i;
+
+  for (arg = arglist; arg; arg = TREE_CHAIN (arg))
+    {
+      unsigned int i;
+      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++;
+    }
+
+  /* No need to clone for 1 target attribute.  */
+  if (argnum == 1)
+    {
+      warning_at (DECL_SOURCE_LOCATION (node->decl),
+		  0,
+		  "single target_clones attribute is ignored");
+      return false;
+    }
+
+  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;
+    }
+
+  args = XNEWVEC (char *, argnum);
+  bool has_default = false;
+  attr = strtok (attr_str, ",");
+  i = 0;
+  while (attr != NULL)
+    {
+      if (strcmp (attr, "default") == 0)
+	{
+	  has_default = true;
+	  attr = strtok (NULL, ",");
+	  continue;
+	}
+      args[i] = attr;
+      attr = strtok (NULL, ",");
+      i++;
+    }
+
+  int args_num = i;
+
+  const char *old_asm_name;
+  old_asm_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
+
+  cgraph_function_version_info *decl1_v = NULL;
+  cgraph_function_version_info *decl2_v = NULL;
+  cgraph_function_version_info *before = NULL;
+  cgraph_function_version_info *after = NULL;
+  tree attributes = NULL;
+  if (!has_default)
+    error_at (DECL_SOURCE_LOCATION (node->decl),
+	      "default target was not set");
+  attributes = make_attribute ("target", "default", NULL);
+  DECL_ATTRIBUTES (node->decl) = attributes;
+  targetm.target_option.valid_attribute_p (node->decl, NULL,
+					   TREE_VALUE (attributes), 0);
+  decl1_v = node->function_version ();
+  if (decl1_v == NULL)
+    decl1_v = node->insert_new_function_version ();
+  before = decl1_v;
+  DECL_FUNCTION_VERSIONED (node->decl) = 1;
+
+  /* Setting new attribute to initial function.  */
+
+  for (i = 0; i < args_num; i++)
+    {
+      pretty_printer pp;
+      attr = args[i];
+      cgraph_node *new_node;
+      unsigned int j;
+
+      if (node->definition)
+	{
+	  if (!node->has_gimple_body_p ())
+	    return false;
+	  node->get_body ();
+
+	  /* Replacing initial function with clone only for 1st target.  */
+	  new_node = node->create_version_clone_with_body (vNULL, NULL,
+							   NULL, false,
+							   NULL, NULL,
+							   "target_clone");
+	  new_node->externally_visible = node->externally_visible;
+	  new_node->address_taken = node->address_taken;
+	  new_node->thunk = node->thunk;
+	  new_node->alias = node->alias;
+	  new_node->weakref = node->weakref;
+	  new_node->cpp_implicit_alias = node->cpp_implicit_alias;
+	  new_node->local.local = node->local.local;
+	  TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (node->decl);
+	}
+      else
+	{
+	  tree new_decl = copy_node (node->decl);
+	  new_node = cgraph_node::get_create (new_decl);
+	}
+
+	const char *new_asm_name;
+	char *new_suffix;
+	new_suffix = XNEWVEC (char, strlen (attr) + 1);
+	memcpy (new_suffix, attr, strlen (attr) + 1);
+
+	/* Replace all '=' and '-' in target option with '_'.  */
+	for (j = 0; j < strlen (new_suffix); j++)
+	  if (new_suffix[j] == '=' || new_suffix[j] == '-')
+	    new_suffix[j] = '_';
+
+	pp_string (&pp, old_asm_name);
+	pp_string (&pp, ".");
+	pp_string (&pp, new_suffix);
+	new_asm_name = pp_formatted_text (&pp);
+	id = get_identifier (new_asm_name);
+	symtab->change_decl_assembler_name (new_node->decl, id);
+	XDELETEVEC (new_suffix);
+
+	/* Setting new attribute to cloned function.  */
+	tree attributes = make_attribute ("target", attr, NULL_TREE);
+	DECL_ATTRIBUTES (new_node->decl) = attributes;
+	targetm.target_option.valid_attribute_p (new_node->decl, NULL,
+						 TREE_VALUE (attributes), 0);
+	decl2_v = new_node->function_version ();
+	if (decl2_v != NULL)
+	  continue;
+	decl2_v = new_node->insert_new_function_version ();
+
+	/* Chain decl2_v and decl1_v.  All semantically identical versions
+	   will be chained together.  */
+
+	after = decl2_v;
+	while (before->next != NULL)
+	  before = before->next;
+	while (after->prev != NULL)
+	  after = after->prev;
+
+	before->next = after;
+	after->prev = before;
+	DECL_FUNCTION_VERSIONED (new_node->decl) = 1;
+    }
+  XDELETEVEC (args);
+  XDELETEVEC (attr_str);
+  return true;
+}
+
+static unsigned int
+ipa_target_clone (void)
+{
+  struct cgraph_node *node;
+  bool res = false;
+  FOR_EACH_FUNCTION (node)
+    res |= expand_target_clones (node);
+  if (res)
+    FOR_EACH_FUNCTION (node)
+      create_dispatcher_calls (node);
+  return 0;
+}
+
+namespace {
+
+const pass_data pass_data_target_clone =
+{
+  SIMPLE_IPA_PASS,		/* type */
+  "targetclone",		/* name */
+  OPTGROUP_NONE,		/* optinfo_flags */
+  TV_NONE,			/* tv_id */
+  ( PROP_ssa | PROP_cfg ),	/* properties_required */
+  0,				/* properties_provided */
+  0,				/* properties_destroyed */
+  0,				/* todo_flags_start */
+  0,				/* todo_flags_finish */
+};
+
+class pass_target_clone : public simple_ipa_opt_pass
+{
+public:
+  pass_target_clone (gcc::context *ctxt)
+    : simple_ipa_opt_pass (pass_data_target_clone, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *) { return ipa_target_clone (); }
+};
+
+bool
+pass_target_clone::gate (function *)
+{
+  return true;
+}
+
+} // anon namespace
+
+simple_ipa_opt_pass *
+make_pass_target_clone (gcc::context *ctxt)
+{
+  return new pass_target_clone (ctxt);
+}
diff --git a/gcc/passes.def b/gcc/passes.def
index 64fc4d9..ff6c550 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -141,6 +141,7 @@ along with GCC; see the file COPYING3.  If not see
   INSERT_PASSES_AFTER (all_late_ipa_passes)
   NEXT_PASS (pass_ipa_pta);
   NEXT_PASS (pass_omp_simd_clone);
+  NEXT_PASS (pass_target_clone);
   TERMINATE_PASS_LIST ()
 
   /* These passes are run after IPA passes on every function that is being
diff --git a/gcc/testsuite/gcc.dg/mvc1.c b/gcc/testsuite/gcc.dg/mvc1.c
new file mode 100644
index 0000000..ab1e0f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc1.c
@@ -0,0 +1,27 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+__attribute__((target_clones("avx","arch=slm","arch=core-avx2","default")))
+int
+foo ()
+{
+  return -2;
+}
+
+int
+bar ()
+{
+  return 2;
+}
+
+int
+main ()
+{
+  int r = 0;
+  r += bar ();
+  r += foo ();
+  r += bar ();
+  r += foo ();
+  r += bar ();
+  return r - 2;
+}
diff --git a/gcc/testsuite/gcc.dg/mvc2.c b/gcc/testsuite/gcc.dg/mvc2.c
new file mode 100644
index 0000000..165e632
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc2.c
@@ -0,0 +1,5 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+__attribute__((target_clones("avx","arch=slm","arch=core-avx2")))
+int foo ();
diff --git a/gcc/testsuite/gcc.dg/mvc3.c b/gcc/testsuite/gcc.dg/mvc3.c
new file mode 100644
index 0000000..074808a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "" } */
+
+__attribute__((target_clones("avx","arch=slm","arch=core-avx2")))
+int foo (); /* { dg-error "default target was not set" } */
+
+int
+bar ()
+{
+  return foo();
+}
diff --git a/gcc/testsuite/gcc.dg/mvc4.c b/gcc/testsuite/gcc.dg/mvc4.c
new file mode 100644
index 0000000..6147365
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc4.c
@@ -0,0 +1,27 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2" } */
+
+__attribute__((target_clones("default","avx","default")))
+int
+foo ()
+{
+  return -2;
+}
+
+int
+bar ()
+{
+  return 2;
+}
+
+int
+main ()
+{
+  int r = 0;
+  r += bar ();
+  r += foo ();
+  r += bar ();
+  r += foo ();
+  r += bar ();
+  return r - 2;
+}
diff --git a/gcc/testsuite/gcc.dg/mvc5.c b/gcc/testsuite/gcc.dg/mvc5.c
new file mode 100644
index 0000000..dfdb762
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fno-inline" } */
+/* { dg-final { scan-assembler-times "foo.ifunc" 6 } } */
+
+__attribute__((target_clones("default","avx","avx2")))
+int
+foo ()
+{
+  return 10;
+}
+
+__attribute__((target_clones("default","avx","avx2")))
+int
+bar ()
+{
+  return -foo ();
+}
diff --git a/gcc/testsuite/gcc.dg/mvc6.c b/gcc/testsuite/gcc.dg/mvc6.c
new file mode 100644
index 0000000..1621985
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc6.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler "vpshufb" } } */
+/* { dg-final { scan-assembler "punpcklbw" } } */
+
+__attribute__((target_clones("arch=core-avx2","arch=slm","default")))
+void
+foo(char *in, char *out, int size)
+{
+  int i;
+  for(i = 0; i < size; i++)
+    {
+	out[2 * i] = in[i];
+	out[2 * i + 1] = in[i];
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/mvc7.c b/gcc/testsuite/gcc.dg/mvc7.c
new file mode 100644
index 0000000..782f8dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc7.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler-times "foo.ifunc" 4 } } */
+
+__attribute__((target_clones("avx","default","arch=slm","arch=core-avx2")))
+int foo ();
+
+int main()
+{
+  return foo();
+}
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 7b66a1c..ec723b8 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -483,6 +483,7 @@ extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);
 extern simple_ipa_opt_pass *make_pass_omp_simd_clone (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_target_clone (gcc::context *ctxt);
 extern ipa_opt_pass_d *make_pass_ipa_profile (gcc::context *ctxt);
 extern ipa_opt_pass_d *make_pass_ipa_cdtor_merge (gcc::context *ctxt);
 extern ipa_opt_pass_d *make_pass_ipa_single_use (gcc::context *ctxt);
diff --git a/target_clones.ChangeLog b/target_clones.ChangeLog
new file mode 100644
index 0000000..b06e702
--- /dev/null
+++ b/target_clones.ChangeLog
@@ -0,0 +1,32 @@
+2015-08-26  Evgeny Stupachenko  <evstupac@gmail.com>
+
+gcc/
+	* Makefile.in (OBJS): Add multiple_target.o.
+	* multiple_target.c (make_attribute): New.
+	(create_dispatcher_calls): Ditto.
+	(expand_target_clones): Ditto.
+	(ipa_target_clone): Ditto.
+	* passes.def (pass_target_clone): New ipa pass.
+	* tree-pass.h (make_pass_target_clone): Ditto.
+
+gcc/c-family
+	* c-common.c (handle_target_clones_attribute): New.
+	* (c_common_attribute_table): Add handle_target_clones_attribute.
+	* (handle_always_inline_attribute): Add check on target_clones
+	attribute.
+	* (handle_target_attribute): Ditto.
+
+gcc/testsuite
+	* gcc.dg/mvc1.c: New test for multiple targets cloning.
+	* gcc.dg/mvc2.c: Ditto.
+	* gcc.dg/mvc3.c: Ditto.
+	* gcc.dg/mvc4.c: Ditto.
+	* gcc.dg/mvc5.c: Ditto.
+	* gcc.dg/mvc6.c: Ditto.
+	* gcc.dg/mvc7.c: Ditto.
+	* g++.dg/ext/mvc1.C: Ditto.
+	* g++.dg/ext/mvc2.C: Ditto.
+	* g++.dg/ext/mvc3.C: Ditto.
+
+gcc/doc
+	* doc/extend.texi (target_clones): New attribute description.

^ permalink raw reply	[flat|nested] 36+ messages in thread
* Re: [PATCH] New attribute to create target clones
@ 2015-10-31 10:52 Dominique d'Humières
  2015-11-02 14:50 ` Evgeny Stupachenko
  0 siblings, 1 reply; 36+ messages in thread
From: Dominique d'Humières @ 2015-10-31 10:52 UTC (permalink / raw)
  To: evstupac; +Cc: law, hubicka, bschmidt, gcc-patches

Evgeny,
On darwin I see the following failures
FAIL: g++.dg/ext/mvc1.C  -std=c++11 (test for excess errors)
UNRESOLVED: g++.dg/ext/mvc1.C  -std=c++11 compilation failed to produce executable
FAIL: g++.dg/ext/mvc1.C  -std=c++14 (test for excess errors)
UNRESOLVED: g++.dg/ext/mvc1.C  -std=c++14 compilation failed to produce executable
FAIL: g++.dg/ext/mvc1.C  -std=c++98 (test for excess errors)
UNRESOLVED: g++.dg/ext/mvc1.C  -std=c++98 compilation failed to produce executable
FAIL: g++.dg/ext/mvc4.C  -std=gnu++11 (internal compiler error)
FAIL: g++.dg/ext/mvc4.C  -std=gnu++11 (test for excess errors)
FAIL: g++.dg/ext/mvc4.C  -std=gnu++14 (internal compiler error)
FAIL: g++.dg/ext/mvc4.C  -std=gnu++14 (test for excess errors)
FAIL: g++.dg/ext/mvc4.C  -std=gnu++98 (internal compiler error)
FAIL: g++.dg/ext/mvc4.C  -std=gnu++98 (test for excess errors)

FAIL: gcc.dg/mvc1.c (internal compiler error)
FAIL: gcc.dg/mvc1.c (test for excess errors)
UNRESOLVED: gcc.dg/mvc1.c compilation failed to produce executable
FAIL: gcc.dg/mvc4.c (internal compiler error)
FAIL: gcc.dg/mvc4.c (test for excess errors)
UNRESOLVED: gcc.dg/mvc4.c compilation failed to produce executable
FAIL: gcc.dg/mvc5.c (internal compiler error)
FAIL: gcc.dg/mvc5.c (test for excess errors)
FAIL: gcc.dg/mvc5.c scan-assembler-times foo.ifunc 6
FAIL: gcc.dg/mvc7.c (internal compiler error)
FAIL: gcc.dg/mvc7.c (test for excess errors)
FAIL: gcc.dg/mvc7.c scan-assembler-times foo.ifunc 4

The errors are of the kind

/opt/gcc/_clean/gcc/testsuite/gcc.dg/mvc7.C:5:5: error: multiversioning needs ifunc which is not supported on this target

These tests probably require something such as

/* { dg-require-ifunc "" } */

I have no opinion if this should also used in the tests for warnings or errors.

The ICEs are of the kind

/opt/gcc/_clean/gcc/testsuite/gcc.dg/mvc7.C:10:1: internal compiler error: Segmentation fault: 11
 }
 ^

TIA

Dominique

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

end of thread, other threads:[~2015-11-03 11:45 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-27 11:35 [PATCH] New attribute to create target clones Evgeny Stupachenko
2015-09-08 11:47 ` Evgeny Stupachenko
2015-09-16 11:42   ` Evgeny Stupachenko
2015-09-21 13:43 ` Bernd Schmidt
2015-09-22 20:24   ` Jeff Law
2015-09-22 21:09     ` Bernd Schmidt
2015-09-22 23:52       ` Evgeny Stupachenko
2015-09-25  0:02         ` Evgeny Stupachenko
2015-10-02 13:18           ` Evgeny Stupachenko
2015-10-08 19:00           ` Jeff Law
2015-10-08 19:23             ` Jan Hubicka
2015-10-08 19:53               ` Jeff Law
2015-10-08 21:36                 ` Jan Hubicka
2015-10-09 17:45                   ` Jeff Law
2015-10-09 18:27                     ` Jan Hubicka
2015-10-09 19:57                       ` Evgeny Stupachenko
2015-10-09 20:04                         ` Jan Hubicka
2015-10-09 21:44                           ` Evgeny Stupachenko
2015-10-12 23:35                             ` Evgeny Stupachenko
2015-10-14 21:32                               ` Evgeny Stupachenko
2015-10-22 18:07                                 ` Evgeny Stupachenko
2015-10-26 15:59                               ` Jeff Law
2015-10-29 13:42                                 ` Evgeny Stupachenko
2015-10-29 17:07                                   ` Jan Hubicka
2015-10-29 18:15                                     ` Evgeny Stupachenko
2015-10-30  3:55                                       ` Jan Hubicka
2015-10-30  5:30                                       ` Jeff Law
2015-10-30 12:30                                         ` Evgeny Stupachenko
2015-10-08 20:01             ` Evgeny Stupachenko
2015-10-09  4:05               ` Jeff Law
2015-10-08 16:39       ` Jeff Law
2015-10-31 10:52 Dominique d'Humières
2015-11-02 14:50 ` Evgeny Stupachenko
2015-11-02 15:22   ` Dominique d'Humières
2015-11-02 17:02   ` Jeff Law
2015-11-03 11:45     ` Evgeny Stupachenko

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