On 02/02/2017 02:18 PM, Martin Liška wrote:
> Ok, I spent more time with understanding how that pass works and I believe it 
> can be
> significantly simplified. I guess target_clones are very close to 'target' 
> attribute
> that is handled by C++ FE. It creates cgraph_function_version_info and 
> function dispatcher
> is generated.
> 
> I hope doing the very same by an early simple IPA pass should be the right 
> approach.
> Works fine apart from an assert it triggers:

After reading of the original thread, it's still unclear why 2 passes we 
introduced.
As I read the original patch, there was just one. Having pre-approved patch by 
Honza,
I'll install that after testing.

Martin

> 
> $ ./xgcc -B. 
> /home/marxin/Programming/gcc/gcc/testsuite/gcc.target/i386/mvc9.c -flto -O1
> lto1: internal compiler error: in binds_to_current_def_p, at symtab.c:2239
> 0x8c580a symtab_node::binds_to_current_def_p(symtab_node*)
>       ../../gcc/symtab.c:2239
> 0x18cb40b worse_state
>       ../../gcc/ipa-pure-const.c:477
> 0x18cd61f propagate_pure_const
>       ../../gcc/ipa-pure-const.c:1346
> 0x18ce304 execute
>       ../../gcc/ipa-pure-const.c:1679
> 
> triggered for foo.ifunc:
> 
> foo.ifunc/6 (foo.ifunc) @0x7f9535b138a0
>   Type: function definition analyzed alias
>   Visibility: prevailing_def_ironly artificial
>   References: foo.resolver/7 (alias)
>   Referring: 
>   Read from file: /tmp/ccdj2ikS.o
>   Availability: overwritable
>   First run: 0
>   Function flags:
>   Called by: main/2 (1.00 per call) 
>   Calls: 
> 
> The assert is removed in attached patch, but maybe there's a better approach?
> 
> Thanks,
> Martin
> 

>From e2ff9bb3ebe8f005e7334780ede92dab6afb1a07 Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Tue, 24 Jan 2017 13:41:25 +0100
Subject: [PATCH] Simplify creation of target_clones (PR lto/66295)

gcc/ChangeLog:

2017-01-24  Martin Liska  <mli...@suse.cz>

	* multiple_target.c (create_dispatcher_calls): Redirect edge
	from a caller of a dispatcher.
	(expand_target_clones): Make the clones local.
	(ipa_target_clone): Do both target clones and resolvers.
	(ipa_dispatcher_calls): Remove the pass.
	(pass_dispatcher_calls::gate): Likewise.
	(make_pass_dispatcher_calls): Likewise.
	* passes.def (pass_target_clone): Put as very first IPA early
	pass.

gcc/testsuite/ChangeLog:

2017-01-24  Martin Liska  <mli...@suse.cz>

	* gcc.target/i386/mvc9.c: New test.
---
 gcc/multiple_target.c                | 71 +++++-------------------------------
 gcc/passes.def                       |  3 +-
 gcc/testsuite/gcc.target/i386/mvc9.c | 28 ++++++++++++++
 3 files changed, 39 insertions(+), 63 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/mvc9.c

diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 5be3980db20..7b735ae81ae 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -87,6 +87,7 @@ create_dispatcher_calls (struct cgraph_node *node)
 	inode->resolve_alias (cgraph_node::get (resolver_decl));
 
       e->redirect_callee (inode);
+      e->redirect_call_stmt_to_callee ();
       /*  Since REDIRECT_CALLEE modifies NEXT_CALLER field we move to
 	  previously set NEXT_CALLER.  */
       e = NULL;
@@ -283,6 +284,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
       create_new_asm_name (attr, suffix);
       /* Create new target clone.  */
       cgraph_node *new_node = create_target_clone (node, definition, suffix);
+      new_node->local.local = false;
       XDELETEVEC (suffix);
 
       /* Set new attribute for the clone.  */
@@ -334,17 +336,19 @@ expand_target_clones (struct cgraph_node *node, bool definition)
   return ret;
 }
 
-static bool target_clone_pass;
-
 static unsigned int
 ipa_target_clone (void)
 {
   struct cgraph_node *node;
 
-  target_clone_pass = false;
+  bool target_clone_pass = false;
   FOR_EACH_FUNCTION (node)
-    if (node->definition)
-      target_clone_pass |= expand_target_clones (node, true);
+    target_clone_pass |= expand_target_clones (node, node->definition);
+
+  if (target_clone_pass)
+    FOR_EACH_FUNCTION (node)
+      create_dispatcher_calls (node);
+
   return 0;
 }
 
@@ -360,7 +364,7 @@ const pass_data pass_data_target_clone =
   0,				/* properties_provided */
   0,				/* properties_destroyed */
   0,				/* todo_flags_start */
-  0				/* todo_flags_finish */
+  TODO_update_ssa		/* todo_flags_finish */
 };
 
 class pass_target_clone : public simple_ipa_opt_pass
@@ -388,58 +392,3 @@ make_pass_target_clone (gcc::context *ctxt)
 {
   return new pass_target_clone (ctxt);
 }
-
-static unsigned int
-ipa_dispatcher_calls (void)
-{
-  struct cgraph_node *node;
-
-  FOR_EACH_FUNCTION (node)
-    if (!node->definition)
-      target_clone_pass |= expand_target_clones (node, false);
-  if (target_clone_pass)
-    FOR_EACH_FUNCTION (node)
-      create_dispatcher_calls (node);
-  return 0;
-}
-
-namespace {
-
-const pass_data pass_data_dispatcher_calls =
-{
-  SIMPLE_IPA_PASS,		/* type */
-  "dispatchercalls",		/* 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_dispatcher_calls : public simple_ipa_opt_pass
-{
-public:
-  pass_dispatcher_calls (gcc::context *ctxt)
-    : simple_ipa_opt_pass (pass_data_dispatcher_calls, ctxt)
-  {}
-
-  /* opt_pass methods: */
-  virtual bool gate (function *);
-  virtual unsigned int execute (function *) { return ipa_dispatcher_calls (); }
-};
-
-bool
-pass_dispatcher_calls::gate (function *)
-{
-  return true;
-}
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_dispatcher_calls (gcc::context *ctxt)
-{
-  return new pass_dispatcher_calls (ctxt);
-}
diff --git a/gcc/passes.def b/gcc/passes.def
index 131d659e7a0..c09ec220d70 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -136,6 +136,7 @@ along with GCC; see the file COPYING3.  If not see
       POP_INSERT_PASSES ()
   POP_INSERT_PASSES ()
 
+  NEXT_PASS (pass_target_clone);
   NEXT_PASS (pass_ipa_chkp_produce_thunks);
   NEXT_PASS (pass_ipa_auto_profile);
   NEXT_PASS (pass_ipa_free_inline_summary);
@@ -155,7 +156,6 @@ along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_ipa_devirt);
   NEXT_PASS (pass_ipa_cp);
   NEXT_PASS (pass_ipa_cdtor_merge);
-  NEXT_PASS (pass_target_clone);
   NEXT_PASS (pass_ipa_hsa);
   NEXT_PASS (pass_ipa_inline);
   NEXT_PASS (pass_ipa_pure_const);
@@ -174,7 +174,6 @@ along with GCC; see the file COPYING3.  If not see
   INSERT_PASSES_AFTER (all_late_ipa_passes)
   NEXT_PASS (pass_materialize_all_clones);
   NEXT_PASS (pass_ipa_pta);
-  NEXT_PASS (pass_dispatcher_calls);
   NEXT_PASS (pass_omp_simd_clone);
   TERMINATE_PASS_LIST (all_late_ipa_passes)
 
diff --git a/gcc/testsuite/gcc.target/i386/mvc9.c b/gcc/testsuite/gcc.target/i386/mvc9.c
new file mode 100644
index 00000000000..69e3cefb7d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mvc9.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-flto -O2" { target lto } } */
+
+__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;
+}
-- 
2.11.0

Reply via email to