Redirect call within specific target attribute among MV clones (PR ipa/82625).
authorMartin Liska <mliska@suse.cz>
Thu, 4 Oct 2018 14:36:55 +0000 (16:36 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 4 Oct 2018 14:36:55 +0000 (14:36 +0000)
2018-10-04  Martin Liska  <mliska@suse.cz>

PR ipa/82625
* multiple_target.c (redirect_to_specific_clone): New function.
(ipa_target_clone): Use it.
* tree-inline.c: Fix comment.
2018-10-04  Martin Liska  <mliska@suse.cz>

PR ipa/82625
* g++.dg/ext/pr82625.C: New test.

From-SVN: r264845

gcc/ChangeLog
gcc/multiple_target.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/pr82625.C [new file with mode: 0644]
gcc/tree-inline.c

index d63b4f43efb32ffc1a37e26e49041213ee2cb30a..f7a15e34646d46aae622a0f97b350f370177e426 100644 (file)
@@ -1,3 +1,10 @@
+2018-10-04  Martin Liska  <mliska@suse.cz>
+
+       PR ipa/82625
+       * multiple_target.c (redirect_to_specific_clone): New function.
+       (ipa_target_clone): Use it.
+       * tree-inline.c: Fix comment.
+
 2018-10-04  David Malcolm  <dmalcolm@redhat.com>
 
        * dumpfile.c (gcc::dump_manager::dump_manager): Initialize new
index a610d9a3345201178e5cd01289c11e43c4e8fffd..2d892f201c5d06eda2c7b12f380bc0151d63e7e8 100644 (file)
@@ -451,6 +451,54 @@ expand_target_clones (struct cgraph_node *node, bool definition)
   return ret;
 }
 
+/* When NODE is a target clone, consider all callees and redirect
+   to a clone with equal target attributes.  That prevents multiple
+   multi-versioning dispatches and a call-chain can be optimized.  */
+
+static void
+redirect_to_specific_clone (cgraph_node *node)
+{
+  cgraph_function_version_info *fv = node->function_version ();
+  if (fv == NULL)
+    return;
+
+  tree attr_target = lookup_attribute ("target", DECL_ATTRIBUTES (node->decl));
+  if (attr_target == NULL_TREE)
+    return;
+
+  /* We need to remember NEXT_CALLER as it could be modified in the loop.  */
+  for (cgraph_edge *e = node->callees; e ; e = e->next_callee)
+    {
+      cgraph_function_version_info *fv2 = e->callee->function_version ();
+      if (!fv2)
+       continue;
+
+      tree attr_target2 = lookup_attribute ("target",
+                                           DECL_ATTRIBUTES (e->callee->decl));
+
+      /* Function is not calling proper target clone.  */
+      if (!attribute_list_equal (attr_target, attr_target2))
+       {
+         while (fv2->prev != NULL)
+           fv2 = fv2->prev;
+
+         /* Try to find a clone with equal target attribute.  */
+         for (; fv2 != NULL; fv2 = fv2->next)
+           {
+             cgraph_node *callee = fv2->this_node;
+             attr_target2 = lookup_attribute ("target",
+                                              DECL_ATTRIBUTES (callee->decl));
+             if (attribute_list_equal (attr_target, attr_target2))
+               {
+                 e->redirect_callee (callee);
+                 e->redirect_call_stmt_to_callee ();
+                 break;
+               }
+           }
+       }
+    }
+}
+
 static unsigned int
 ipa_target_clone (void)
 {
@@ -464,6 +512,9 @@ ipa_target_clone (void)
   for (unsigned i = 0; i < to_dispatch.length (); i++)
     create_dispatcher_calls (to_dispatch[i]);
 
+  FOR_EACH_FUNCTION (node)
+    redirect_to_specific_clone (node);
+
   return 0;
 }
 
index 29f4a2a8f7cbfb26819bf77a5ed80fc9d58030b0..ee8a184c26af186aeb350ed8d8f2ca872f3da41f 100644 (file)
@@ -1,3 +1,8 @@
+2018-10-04  Martin Liska  <mliska@suse.cz>
+
+       PR ipa/82625
+       * g++.dg/ext/pr82625.C: New test.
+
 2018-10-04  David Malcolm  <dmalcolm@redhat.com>
 
        * gcc.dg/plugin/dump-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/ext/pr82625.C b/gcc/testsuite/g++.dg/ext/pr82625.C
new file mode 100644 (file)
index 0000000..47bd2df
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+__attribute__ ((target ("default")))
+static unsigned foo(const char *buf, unsigned size) {
+  return 1;
+}
+
+__attribute__ ((target ("avx")))
+static unsigned foo(const char *buf, unsigned size) {
+  return 2;
+}
+
+__attribute__ ((target ("default")))
+unsigned bar() {
+  char buf[4096];
+  unsigned acc = 0;
+  for (int i = 0; i < sizeof(buf); i++) {
+    acc += foo(&buf[i], 1);
+  }
+  return acc;
+}
+
+__attribute__ ((target ("avx")))
+unsigned bar() {
+  char buf[4096];
+  unsigned acc = 0;
+  for (int i = 0; i < sizeof(buf); i++) {
+    acc += foo(&buf[i], 1);
+  }
+  return acc;
+}
+
+/* { dg-final { scan-tree-dump-times "return 4096;" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 8192;" 1 "optimized" } } */
index ff8ee8ce78fc6a54821ba0108337de1e87a6f354..913425394e076d598d747b8ea7d647fa9a88458b 100644 (file)
@@ -2631,7 +2631,7 @@ copy_loops (copy_body_data *id,
     }
 }
 
-/* Call cgraph_redirect_edge_call_stmt_to_callee on all calls in BB */
+/* Call redirect_call_stmt_to_callee on all calls in BB.  */
 
 void
 redirect_all_calls (copy_body_data * id, basic_block bb)