Skip to content

Commit

Permalink
Redirect call within specific target attribute among MV clones (PR ip…
Browse files Browse the repository at this point in the history
…a/82625).

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
  • Loading branch information
marxin authored and Martin Liska committed Oct 4, 2018
1 parent 5d98e5a commit b8ce812
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 1 deletion.
7 changes: 7 additions & 0 deletions gcc/ChangeLog
@@ -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
Expand Down
51 changes: 51 additions & 0 deletions gcc/multiple_target.c
Expand Up @@ -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)
{
Expand All @@ -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;
}

Expand Down
5 changes: 5 additions & 0 deletions gcc/testsuite/ChangeLog
@@ -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.
Expand Down
36 changes: 36 additions & 0 deletions gcc/testsuite/g++.dg/ext/pr82625.C
@@ -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" } } */
2 changes: 1 addition & 1 deletion gcc/tree-inline.c
Expand Up @@ -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)
Expand Down

0 comments on commit b8ce812

Please sign in to comment.