public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC, patch] New attribute to create target clones
@ 2015-07-30 22:40 Evgeny Stupachenko
  2015-07-30 22:41 ` Evgeny Stupachenko
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Evgeny Stupachenko @ 2015-07-30 22:40 UTC (permalink / raw)
  To: GCC Patches

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

Hi All,

The patch enables new attribute 'ctarget',
The attribute force compiler to create clones of a function with the attribute.

For example:
__attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
int
foo ()

will create 3 clones of foo() optimized for corresponding targets and
replace all foo() calls with ifunc resolver.
The patch include new tests for the feature.

Currently default ctarget means that foo() will be optimized with
current compiler options and target.
The other option is to switch target to target specific minimum (like
target x86-64). Is it better?

What do you think about attribute name? 'ctarget' is short but not
informative. Other variants are 'target_clones', 'targets'...

Below is ChangeLog. Attached patch passed make check on x86.

Thanks,
Evgeny

2015-07-31  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_ctarget_attribute): New.
        * (c_common_attribute_table): Add handle_ctarget_attribute.
        * (handle_always_inline_attribute): Add check on ctarget 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.

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

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 07c6f0a..219345b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1337,6 +1337,7 @@ OBJS = \
 	mcf.o \
 	mode-switching.o \
 	modulo-sched.o \
+	multiple_target.o \
 	omega.o \
 	omp-low.o \
 	optabs.o \
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 7fe7fa6..8ca0710 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -390,6 +390,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_ctarget_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 *);
@@ -789,6 +790,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_error_attribute, false },
   { "target",                 1, -1, true, false, false,
 			      handle_target_attribute, false },
+  { "ctarget",                 1, -1, true, false, false,
+			      handle_ctarget_attribute, false },
   { "optimize",               1, -1, true, false, false,
 			      handle_optimize_attribute, false },
   /* For internal use only.  The leading '*' both prevents its usage in
@@ -6898,6 +6901,12 @@ handle_always_inline_attribute (tree *node, tree name,
 		   "with %qs attribute", name, "noinline");
 	  *no_add_attrs = true;
 	}
+      else if (lookup_attribute ("ctarget", DECL_ATTRIBUTES (*node)))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute ignored as it conflict with ctarget", name);
+	  *no_add_attrs = true;
+	}
       else
 	/* Set the attribute and mark it for disregarding inline
 	   limits.  */
@@ -9299,6 +9308,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 ("ctarget", DECL_ATTRIBUTES (*node)))
+    {
+      warning (OPT_Wattributes,
+	       "%qE attribute ignored as it conflict with ctarget", name);
+      *no_add_attrs = true;
+    }
   else if (! targetm.target_option.valid_attribute_p (*node, name, args,
 						      flags))
     *no_add_attrs = true;
@@ -9306,6 +9321,39 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
   return NULL_TREE;
 }
 
+/* Handle a "ctarget" attribute.  */
+
+static tree
+handle_ctarget_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/multiple_target.c b/gcc/multiple_target.c
new file mode 100644
index 0000000..fe8ee18
--- /dev/null
+++ b/gcc/multiple_target.c
@@ -0,0 +1,359 @@
+/* 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 "tm.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "rtl.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "gimple-expr.h"
+#include "gimple.h"
+#include "tree-iterator.h"
+#include "diagnostic-core.h"
+#include "gimple-ssa.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
+#include "tree-cfg.h"
+#include "tree-phinodes.h"
+#include "calls.h"
+#include "stmt.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 to NODE has multiple ctarget 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;
+  tree decl = node->decl;
+
+  /* Checking if call of function is call of versioned function.  */
+  if (!decl
+      || TREE_CODE (decl) != FUNCTION_DECL
+      || !DECL_FUNCTION_VERSIONED (decl))
+    return;
+
+  for (e = node->callers; e ;e = (e == NULL) ? e_next : e->next_caller)
+    {
+      tree resolver_decl;
+      tree idecl;
+      gimple call = e->call_stmt;
+      struct cgraph_node *inode;
+
+      e_next = e->next_caller;
+      idecl = targetm.get_function_versions_dispatcher (decl);
+      if (!idecl)
+	{
+	  error_at (gimple_location (call),
+		    "default ctarget 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 NODE has multiple ctarget attribute with multiple fields,
+   create the appropriate clone for each field.  */
+
+static bool
+expand_target_clones (struct cgraph_node *node)
+{
+  tree id;
+  /* Parsing ctarget attributes separated by comma.  */
+  tree attr_target = lookup_attribute ("ctarget",
+				       DECL_ATTRIBUTES (node->decl));
+  /* No ctargets 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 ctarget attribute.  */
+  if (argnum == 1)
+    {
+      warning_at (DECL_SOURCE_LOCATION (node->decl),
+		  0,
+		  "single ctarget 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 ctarget 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 ctarget.  */
+	  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 f77d3d3..e836741 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..b5ff6aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc1.c
@@ -0,0 +1,26 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("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..5f2675f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc2.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("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..24f0919
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("avx","arch=slm","arch=core-avx2")))
+int foo (); /* { dg-error "default ctarget 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..56df3af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc4.c
@@ -0,0 +1,26 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("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..edc6860
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/mvc5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-final { scan-assembler-times "foo.ifunc" 6 } } */
+
+__attribute__((ctarget("default","avx","avx2")))
+int
+foo ()
+{
+  return 10;
+}
+
+__attribute__((ctarget("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..8063ee8
--- /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__((ctarget("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..2af7631
--- /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__((ctarget("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 51ebcd7..d903965 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -480,6 +480,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);

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
@ 2015-07-30 22:41 ` Evgeny Stupachenko
  2015-07-30 23:02 ` Andrew Pinski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Evgeny Stupachenko @ 2015-07-30 22:41 UTC (permalink / raw)
  To: GCC Patches

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

Forget C++ tests.

On Fri, Jul 31, 2015 at 1:19 AM, Evgeny Stupachenko <evstupac@gmail.com> wrote:
> Hi All,
>
> The patch enables new attribute 'ctarget',
> The attribute force compiler to create clones of a function with the attribute.
>
> For example:
> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
> int
> foo ()
>
> will create 3 clones of foo() optimized for corresponding targets and
> replace all foo() calls with ifunc resolver.
> The patch include new tests for the feature.
>
> Currently default ctarget means that foo() will be optimized with
> current compiler options and target.
> The other option is to switch target to target specific minimum (like
> target x86-64). Is it better?
>
> What do you think about attribute name? 'ctarget' is short but not
> informative. Other variants are 'target_clones', 'targets'...
>
> Below is ChangeLog. Attached patch passed make check on x86.
>
> Thanks,
> Evgeny
>
> 2015-07-31  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_ctarget_attribute): New.
>         * (c_common_attribute_table): Add handle_ctarget_attribute.
>         * (handle_always_inline_attribute): Add check on ctarget 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.

[-- Attachment #2: ctarget_attribute_C++tests.patch --]
[-- Type: application/octet-stream, Size: 1813 bytes --]

diff --git a/gcc/testsuite/g++.dg/ext/mvc1.C b/gcc/testsuite/g++.dg/ext/mvc1.C
new file mode 100644
index 0000000..27f2409
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mvc1.C
@@ -0,0 +1,34 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
+int
+foo ()
+{
+  return -2;
+}
+
+__attribute__((target("avx","arch=core-avx2")))
+int
+bar ()
+{
+  return 2;
+}
+
+__attribute__((target("default")))
+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/g++.dg/ext/mvc2.C b/gcc/testsuite/g++.dg/ext/mvc2.C
new file mode 100644
index 0000000..d454282
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mvc2.C
@@ -0,0 +1,8 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((ctarget("avx","arch=slm","default")))
+__attribute__((target("avx")))
+int foo (); /* { dg-warning "'target' attribute ignored as it conflict with ctarget" } */
+
+__attribute__((ctarget("avx","arch=slm","default"),always_inline))
+int bar (); /* { dg-warning "'always_inline' attribute ignored as it conflict with ctarget" } */
diff --git a/gcc/testsuite/g++.dg/ext/mvc3.C b/gcc/testsuite/g++.dg/ext/mvc3.C
new file mode 100644
index 0000000..5a7476c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/mvc3.C
@@ -0,0 +1,8 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+__attribute__((target("avx")))
+__attribute__((ctarget("avx","arch=slm","default")))
+int foo (); /* { dg-warning "'ctarget' attribute ignored as it conflict with target" } */
+
+__attribute__((always_inline,ctarget("avx","arch=slm","default")))
+int bar (); /* { dg-warning "'ctarget' attribute ignored as it assumes noinline" } */

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
  2015-07-30 22:41 ` Evgeny Stupachenko
@ 2015-07-30 23:02 ` Andrew Pinski
  2015-07-31  0:12   ` Evgeny Stupachenko
  2015-07-31  2:52 ` Joseph Myers
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Andrew Pinski @ 2015-07-30 23:02 UTC (permalink / raw)
  To: Evgeny Stupachenko; +Cc: GCC Patches

On Thu, Jul 30, 2015 at 3:19 PM, Evgeny Stupachenko <evstupac@gmail.com> wrote:
> Hi All,
>
> The patch enables new attribute 'ctarget',
> The attribute force compiler to create clones of a function with the attribute.
>
> For example:
> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
> int
> foo ()
>
> will create 3 clones of foo() optimized for corresponding targets and
> replace all foo() calls with ifunc resolver.
> The patch include new tests for the feature.
>
> Currently default ctarget means that foo() will be optimized with
> current compiler options and target.
> The other option is to switch target to target specific minimum (like
> target x86-64). Is it better?
>
> What do you think about attribute name? 'ctarget' is short but not
> informative. Other variants are 'target_clones', 'targets'...

How does this interacts with Function Multiversioning
(https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Function-Multiversioning.html)?

Thanks,
Andrew Pinski

>
> Below is ChangeLog. Attached patch passed make check on x86.
>
> Thanks,
> Evgeny
>
> 2015-07-31  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_ctarget_attribute): New.
>         * (c_common_attribute_table): Add handle_ctarget_attribute.
>         * (handle_always_inline_attribute): Add check on ctarget 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.

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 23:02 ` Andrew Pinski
@ 2015-07-31  0:12   ` Evgeny Stupachenko
  0 siblings, 0 replies; 10+ messages in thread
From: Evgeny Stupachenko @ 2015-07-31  0:12 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: GCC Patches

You can't apply both 'ctarget' and 'target' attributes to a function.
The patch uses same target specific methods to create dispatcher and
target clones.

On Fri, Jul 31, 2015 at 1:30 AM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Thu, Jul 30, 2015 at 3:19 PM, Evgeny Stupachenko <evstupac@gmail.com> wrote:
>> Hi All,
>>
>> The patch enables new attribute 'ctarget',
>> The attribute force compiler to create clones of a function with the attribute.
>>
>> For example:
>> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
>> int
>> foo ()
>>
>> will create 3 clones of foo() optimized for corresponding targets and
>> replace all foo() calls with ifunc resolver.
>> The patch include new tests for the feature.
>>
>> Currently default ctarget means that foo() will be optimized with
>> current compiler options and target.
>> The other option is to switch target to target specific minimum (like
>> target x86-64). Is it better?
>>
>> What do you think about attribute name? 'ctarget' is short but not
>> informative. Other variants are 'target_clones', 'targets'...
>
> How does this interacts with Function Multiversioning
> (https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Function-Multiversioning.html)?
>
> Thanks,
> Andrew Pinski
>
>>
>> Below is ChangeLog. Attached patch passed make check on x86.
>>
>> Thanks,
>> Evgeny
>>
>> 2015-07-31  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_ctarget_attribute): New.
>>         * (c_common_attribute_table): Add handle_ctarget_attribute.
>>         * (handle_always_inline_attribute): Add check on ctarget 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.

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
  2015-07-30 22:41 ` Evgeny Stupachenko
  2015-07-30 23:02 ` Andrew Pinski
@ 2015-07-31  2:52 ` Joseph Myers
  2015-07-31  7:28 ` Jeff Law
  2015-08-03 18:43 ` Jeff Law
  4 siblings, 0 replies; 10+ messages in thread
From: Joseph Myers @ 2015-07-31  2:52 UTC (permalink / raw)
  To: Evgeny Stupachenko; +Cc: GCC Patches

On Fri, 31 Jul 2015, Evgeny Stupachenko wrote:

> The patch enables new attribute 'ctarget',

Attributes should be documented in extend.texi.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
                   ` (2 preceding siblings ...)
  2015-07-31  2:52 ` Joseph Myers
@ 2015-07-31  7:28 ` Jeff Law
  2015-08-03 18:43 ` Jeff Law
  4 siblings, 0 replies; 10+ messages in thread
From: Jeff Law @ 2015-07-31  7:28 UTC (permalink / raw)
  To: Evgeny Stupachenko, GCC Patches

On 07/30/2015 04:19 PM, Evgeny Stupachenko wrote:
> Hi All,
>
> The patch enables new attribute 'ctarget',
> The attribute force compiler to create clones of a function with the attribute.
>
> For example:
> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
> int
> foo ()
>
> will create 3 clones of foo() optimized for corresponding targets and
> replace all foo() calls with ifunc resolver.
> The patch include new tests for the feature.
>
> Currently default ctarget means that foo() will be optimized with
> current compiler options and target.
> The other option is to switch target to target specific minimum (like
> target x86-64). Is it better?
>
> What do you think about attribute name? 'ctarget' is short but not
> informative. Other variants are 'target_clones', 'targets'...
>
> Below is ChangeLog. Attached patch passed make check on x86.
>
> Thanks,
> Evgeny
>
> 2015-07-31  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_ctarget_attribute): New.
>          * (c_common_attribute_table): Add handle_ctarget_attribute.
>          * (handle_always_inline_attribute): Add check on ctarget 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.
I have the same question as Andrew.  How is this fundamentally different 
from the function multi-versioning we currently support?

jeff
>

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

* Re: [RFC, patch] New attribute to create target clones
  2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
                   ` (3 preceding siblings ...)
  2015-07-31  7:28 ` Jeff Law
@ 2015-08-03 18:43 ` Jeff Law
  2015-08-21  1:21   ` Evgeny Stupachenko
  4 siblings, 1 reply; 10+ messages in thread
From: Jeff Law @ 2015-08-03 18:43 UTC (permalink / raw)
  To: Evgeny Stupachenko, GCC Patches

On 07/30/2015 04:19 PM, Evgeny Stupachenko wrote:
> Hi All,
>
> The patch enables new attribute 'ctarget',
> The attribute force compiler to create clones of a function with the attribute.
>
> For example:
> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
So presumably we're allowing both changing the ISA and the tuning 
options?   In fact, it looks like we're able to change any -m option, right?

What about something like -mregparm?  I think the docs need to disallow 
clones with different ABI requirements.

> Currently default ctarget means that foo() will be optimized with
> current compiler options and target.
> The other option is to switch target to target specific minimum (like
> target x86-64). Is it better?
I could make an argument for either.  Do we have anything to guide us 
from other compilers such as ICC that may have a similar capability?


>
> What do you think about attribute name? 'ctarget' is short but not
> informative. Other variants are 'target_clones', 'targets'...
target_clones seems good.

For multiple_target.c: Can you please trim down the #include set.  I 
can't believe you need all that stuff.    If you really need backend 
stuff (tm.h), then use "backend.h" instead.

It generally looks reasonable, but Jan knows the IPA code much better 
than I do and I'd like him to chime in.  You might also ask Ilya to 
review the cloning and rules around clones since he head to deal with a 
lot of that stuff in his MPX work.

jeff

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

* Re: [RFC, patch] New attribute to create target clones
  2015-08-03 18:43 ` Jeff Law
@ 2015-08-21  1:21   ` Evgeny Stupachenko
  2015-08-21 16:05     ` Jeff Law
  0 siblings, 1 reply; 10+ messages in thread
From: Evgeny Stupachenko @ 2015-08-21  1:21 UTC (permalink / raw)
  To: Jeff Law; +Cc: GCC Patches

On Mon, Aug 3, 2015 at 9:43 PM, Jeff Law <law@redhat.com> wrote:
> On 07/30/2015 04:19 PM, Evgeny Stupachenko wrote:
>>
>> Hi All,
>>
>> The patch enables new attribute 'ctarget',
>> The attribute force compiler to create clones of a function with the
>> attribute.
>>
>> For example:
>> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
>
> So presumably we're allowing both changing the ISA and the tuning options?
> In fact, it looks like we're able to change any -m option, right?
>
> What about something like -mregparm?  I think the docs need to disallow
> clones with different ABI requirements.

-mregparm is not allowed now. The
targetm.target_option.valid_attribute_p hook specify which -m option
is allowed for architecture. Here patch reuses Function
Multiversioning methods.

>
>> Currently default ctarget means that foo() will be optimized with
>> current compiler options and target.
>> The other option is to switch target to target specific minimum (like
>> target x86-64). Is it better?
>
> I could make an argument for either.  Do we have anything to guide us from
> other compilers such as ICC that may have a similar capability?
>

Not sure. However ICC has similar to Function Multiversioning:
__declcpec(cpu_specific(... where "default" is ""generic". I think for
"default" we should do the same as Function Multiversioning - keep
compiler options. That way users will be able to create target
specific minimum by passing corresponding options to command line.

>
>>
>> What do you think about attribute name? 'ctarget' is short but not
>> informative. Other variants are 'target_clones', 'targets'...
>
> target_clones seems good.
>
> For multiple_target.c: Can you please trim down the #include set.  I can't
> believe you need all that stuff.    If you really need backend stuff (tm.h),
> then use "backend.h" instead.
>
> It generally looks reasonable, but Jan knows the IPA code much better than I
> do and I'd like him to chime in.  You might also ask Ilya to review the
> cloning and rules around clones since he head to deal with a lot of that
> stuff in his MPX work.
>
> jeff

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

* Re: [RFC, patch] New attribute to create target clones
  2015-08-21  1:21   ` Evgeny Stupachenko
@ 2015-08-21 16:05     ` Jeff Law
  0 siblings, 0 replies; 10+ messages in thread
From: Jeff Law @ 2015-08-21 16:05 UTC (permalink / raw)
  To: Evgeny Stupachenko; +Cc: GCC Patches

On 08/20/2015 05:38 PM, Evgeny Stupachenko wrote:
> On Mon, Aug 3, 2015 at 9:43 PM, Jeff Law <law@redhat.com> wrote:
>> On 07/30/2015 04:19 PM, Evgeny Stupachenko wrote:
>>>
>>> Hi All,
>>>
>>> The patch enables new attribute 'ctarget',
>>> The attribute force compiler to create clones of a function with the
>>> attribute.
>>>
>>> For example:
>>> __attribute__((ctarget("avx","arch=slm","arch=core-avx2","default")))
>>
>> So presumably we're allowing both changing the ISA and the tuning options?
>> In fact, it looks like we're able to change any -m option, right?
>>
>> What about something like -mregparm?  I think the docs need to disallow
>> clones with different ABI requirements.
>
> -mregparm is not allowed now. The
> targetm.target_option.valid_attribute_p hook specify which -m option
> is allowed for architecture. Here patch reuses Function
> Multiversioning methods.
Ah, OK.  That clarifies things.

>>
>> I could make an argument for either.  Do we have anything to guide us from
>> other compilers such as ICC that may have a similar capability?
>>
>
> Not sure. However ICC has similar to Function Multiversioning:
> __declcpec(cpu_specific(... where "default" is ""generic". I think for
> "default" we should do the same as Function Multiversioning - keep
> compiler options. That way users will be able to create target
> specific minimum by passing corresponding options to command line.
That works for me.

So I think we really need Jan to chime in here.

Jeff

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

* Re: [RFC, patch] New attribute to create target clones
       [not found] <cwgri49oxp4r4pcmb23uctn3.1438343171392@email.android.com>
@ 2015-07-31 15:51 ` Jeff Law
  0 siblings, 0 replies; 10+ messages in thread
From: Jeff Law @ 2015-07-31 15:51 UTC (permalink / raw)
  To: Evgeny; +Cc: GCC Patches

On 07/31/2015 05:50 AM, Evgeny wrote:
> New ctarget attribute automatically clone function and optimize for
> corresponding target. For target attribute if you specify "avx,sse4" you
> will get only 1 function optimized for the target with higher priority,
> while ctarget will generate 2 functions: one optimized for sse4 and one
> for avx.
Ah, thanks for the explanation.  That helps a lot.

jeff

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

end of thread, other threads:[~2015-08-21 16:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-30 22:40 [RFC, patch] New attribute to create target clones Evgeny Stupachenko
2015-07-30 22:41 ` Evgeny Stupachenko
2015-07-30 23:02 ` Andrew Pinski
2015-07-31  0:12   ` Evgeny Stupachenko
2015-07-31  2:52 ` Joseph Myers
2015-07-31  7:28 ` Jeff Law
2015-08-03 18:43 ` Jeff Law
2015-08-21  1:21   ` Evgeny Stupachenko
2015-08-21 16:05     ` Jeff Law
     [not found] <cwgri49oxp4r4pcmb23uctn3.1438343171392@email.android.com>
2015-07-31 15:51 ` Jeff Law

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