Hi.

Following restricts cgraph redirection done in multiple_target.c just
to clones that are created in the IPA pass.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Martin

gcc/ChangeLog:

2018-04-11  Martin Liska  <mli...@suse.cz>

        PR ipa/85329
        * multiple_target.c (create_dispatcher_calls): Rename to ...
        (redirect_target_clone_callers): ... this.
        (expand_target_clones): Record created clones.
        (ipa_target_clone): Call redirect_target_clone_callers only
        for these clones.
---
 gcc/multiple_target.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)


diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index b006a5ab6ec..5bd88fbd83c 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -58,11 +58,11 @@ replace_function_decl (tree *op, int *walk_subtrees, void *data)
   return NULL;
 }
 
-/* If the call in NODE has multiple target attribute with multiple fields,
-   replace it with dispatcher call and create dispatcher (once).  */
+/* If the call in NODE is a target_clone attribute clone, redirect all
+   edges and references that point to cgraph NODE.  */
 
 static void
-create_dispatcher_calls (struct cgraph_node *node)
+redirect_target_clone_callers (struct cgraph_node *node)
 {
   ipa_ref *ref;
 
@@ -300,10 +300,12 @@ create_target_clone (cgraph_node *node, bool definition, char *name)
 }
 
 /* If the function in NODE has multiple target attributes
-   create the appropriate clone for each valid target attribute.  */
+   create the appropriate clone for each valid target attribute.
+   TO_REDIRECT is a vector where we place all newly created clones.  */
 
 static bool
-expand_target_clones (struct cgraph_node *node, bool definition)
+expand_target_clones (struct cgraph_node *node, bool definition,
+		      auto_vec <cgraph_node *> &to_redirect)
 {
   int i;
   /* Parsing target attributes separated by comma.  */
@@ -404,6 +406,8 @@ expand_target_clones (struct cgraph_node *node, bool definition)
       before->next = after;
       after->prev = before;
       DECL_FUNCTION_VERSIONED (new_node->decl) = 1;
+
+      to_redirect.safe_push (new_node);
     }
 
   XDELETEVEC (attrs);
@@ -420,6 +424,8 @@ expand_target_clones (struct cgraph_node *node, bool definition)
     = targetm.target_option.valid_attribute_p (node->decl, NULL,
 					       TREE_VALUE (attributes), 0);
   input_location = saved_loc;
+  to_redirect.safe_push (node);
+
   return ret;
 }
 
@@ -428,13 +434,12 @@ ipa_target_clone (void)
 {
   struct cgraph_node *node;
 
-  bool target_clone_pass = false;
+  auto_vec <cgraph_node *> nodes_to_redirect;
   FOR_EACH_FUNCTION (node)
-    target_clone_pass |= expand_target_clones (node, node->definition);
+    expand_target_clones (node, node->definition, nodes_to_redirect);
 
-  if (target_clone_pass)
-    FOR_EACH_FUNCTION (node)
-      create_dispatcher_calls (node);
+  for (unsigned i = 0; i < nodes_to_redirect.length (); i++)
+    redirect_target_clone_callers (nodes_to_redirect[i]);
 
   return 0;
 }

Reply via email to