This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Make redirection only for target_clones: V2 (PR ipa/85329).


Hi.

I'm sending V3 which we did with Honza. It's similar to V2, but properly makes
FUNCTION_DECL local for default implementation.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
Tests on ppc64le are running.

Ready to be installed?
Martin
>From 77b48cfad59dd24a5c068bfb32b1059535ae1f75 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Sat, 14 Apr 2018 09:55:35 +0200
Subject: [PATCH] Make redirection only for target_clones: V3 (PR ipa/85329).

2018-04-16  Martin Liska  <mliska@suse.cz>

	* multiple_target.c (create_dispatcher_calls): Set apostrophes
	for target_clone error message.  Make default implementation
        clone to be a local declaration.
	(separate_attrs): Add new argument and check for an emptry
	string.
	(expand_target_clones): Handle it.
	(ipa_target_clone): Make redirection just for target_clones
	functions.

gcc/testsuite/ChangeLog:

2018-04-16  Martin Liska  <mliska@suse.cz>

	* g++.dg/ext/pr85329-2.C: New test.
	* g++.dg/ext/pr85329.C: New test.
	* gcc.target/i386/mvc12.c: New test.
---
 gcc/multiple_target.c                 | 55 ++++++++++++++++++++++++++---------
 gcc/testsuite/g++.dg/ext/pr85329-2.C  | 22 ++++++++++++++
 gcc/testsuite/g++.dg/ext/pr85329.C    | 19 ++++++++++++
 gcc/testsuite/gcc.target/i386/mvc12.c | 11 +++++++
 4 files changed, 93 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/pr85329-2.C
 create mode 100644 gcc/testsuite/g++.dg/ext/pr85329.C
 create mode 100644 gcc/testsuite/gcc.target/i386/mvc12.c

diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index b006a5ab6ec..a1fe09a5983 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -88,7 +88,7 @@ create_dispatcher_calls (struct cgraph_node *node)
   if (!idecl)
     {
       error_at (DECL_SOURCE_LOCATION (node->decl),
-		"default target_clones attribute was not set");
+		"default %<target_clones%> attribute was not set");
       return;
     }
 
@@ -161,10 +161,25 @@ create_dispatcher_calls (struct cgraph_node *node)
 	}
     }
 
-  TREE_PUBLIC (node->decl) = 0;
   symtab->change_decl_assembler_name (node->decl,
 				      clone_function_name (node->decl,
 							   "default"));
+
+  /* FIXME: copy of cgraph_node::make_local that should be cleaned up
+	    in next stage1.  */
+  node->make_decl_local ();
+  node->set_section (NULL);
+  node->set_comdat_group (NULL);
+  node->externally_visible = false;
+  node->forced_by_abi = false;
+  node->set_section (NULL);
+  node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
+			|| node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+		       && !flag_incremental_link);
+  node->resolution = LDPR_PREVAILING_DEF_IRONLY;
+
+  DECL_ARTIFICIAL (node->decl) = 1;
+  node->force_output = true;
 }
 
 /* Return length of attribute names string,
@@ -216,26 +231,30 @@ get_attr_str (tree arglist, char *attr_str)
 }
 
 /* Return number of attributes separated by comma and put them into ARGS.
-   If there is no DEFAULT attribute return -1.  */
+   If there is no DEFAULT attribute return -1.  If there is an empty
+   string in attribute return -2.  */
 
 static int
-separate_attrs (char *attr_str, char **attrs)
+separate_attrs (char *attr_str, char **attrs, int attrnum)
 {
   int i = 0;
-  bool has_default = false;
+  int default_count = 0;
 
   for (char *attr = strtok (attr_str, ",");
        attr != NULL; attr = strtok (NULL, ","))
     {
       if (strcmp (attr, "default") == 0)
 	{
-	  has_default = true;
+	  default_count++;
 	  continue;
 	}
       attrs[i++] = attr;
     }
-  if (!has_default)
+  if (default_count == 0)
     return -1;
+  else if (i + default_count < attrnum)
+    return -2;
+
   return i;
 }
 
@@ -321,7 +340,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
     {
       warning_at (DECL_SOURCE_LOCATION (node->decl),
 		  0,
-		  "single target_clones attribute is ignored");
+		  "single %<target_clones%> attribute is ignored");
       return false;
     }
 
@@ -345,7 +364,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
   int attrnum = get_attr_str (arglist, attr_str);
   char **attrs = XNEWVEC (char *, attrnum);
 
-  attrnum = separate_attrs (attr_str, attrs);
+  attrnum = separate_attrs (attr_str, attrs, attrnum);
   if (attrnum == -1)
     {
       error_at (DECL_SOURCE_LOCATION (node->decl),
@@ -354,6 +373,14 @@ expand_target_clones (struct cgraph_node *node, bool definition)
       XDELETEVEC (attr_str);
       return false;
     }
+  else if (attrnum == -2)
+    {
+      error_at (DECL_SOURCE_LOCATION (node->decl),
+		"an empty string cannot be in %<target_clones%> attribute");
+      XDELETEVEC (attrs);
+      XDELETEVEC (attr_str);
+      return false;
+    }
 
   cgraph_function_version_info *decl1_v = NULL;
   cgraph_function_version_info *decl2_v = NULL;
@@ -427,14 +454,14 @@ static unsigned int
 ipa_target_clone (void)
 {
   struct cgraph_node *node;
+  auto_vec<cgraph_node *> to_dispatch;
 
-  bool target_clone_pass = false;
   FOR_EACH_FUNCTION (node)
-    target_clone_pass |= expand_target_clones (node, node->definition);
+    if (expand_target_clones (node, node->definition))
+      to_dispatch.safe_push (node);
 
-  if (target_clone_pass)
-    FOR_EACH_FUNCTION (node)
-      create_dispatcher_calls (node);
+  for (unsigned i = 0; i < to_dispatch.length (); i++)
+    create_dispatcher_calls (to_dispatch[i]);
 
   return 0;
 }
diff --git a/gcc/testsuite/g++.dg/ext/pr85329-2.C b/gcc/testsuite/g++.dg/ext/pr85329-2.C
new file mode 100644
index 00000000000..24622d404f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr85329-2.C
@@ -0,0 +1,22 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
+
+class b
+{
+public:
+  __attribute__ ((target ("aes"))) b () {}
+  __attribute__ ((target ("default"))) b () {}
+};
+class c
+{
+  b d;
+};
+void
+fn1 ()
+{
+  c a;
+}
+__attribute__ ((target_clones ("sse", "default"))) void
+e ()
+{
+}
diff --git a/gcc/testsuite/g++.dg/ext/pr85329.C b/gcc/testsuite/g++.dg/ext/pr85329.C
new file mode 100644
index 00000000000..fb77e42cd78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr85329.C
@@ -0,0 +1,19 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
+
+struct a
+{
+  __attribute__((target_clones("sse", "default"))) void operator^=(a) {}
+} * b;
+
+class c {
+public:
+  a *d();
+};
+
+class f {
+  void g();
+  c e;
+};
+
+void f::g() { *e.d() ^= b[0]; }
diff --git a/gcc/testsuite/gcc.target/i386/mvc12.c b/gcc/testsuite/gcc.target/i386/mvc12.c
new file mode 100644
index 00000000000..f42ae8080e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mvc12.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("","arch=slm","arch=core-avx2", "default")))
+int foo (); /* { dg-error "an empty string cannot be in .target_clones. attribute" } */
+
+int
+bar ()
+{
+  return foo();
+}
-- 
2.16.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]