Make redirection only for target_clones: V3 (PR ipa/85329).
2018-04-17 Martin Liska <mliska@suse.cz> PR ipa/85329 * 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 empty string. (expand_target_clones): Handle it. (ipa_target_clone): Make redirection just for target_clones functions. 2018-04-17 Martin Liska <mliska@suse.cz> PR ipa/85329 * g++.dg/ext/pr85329-2.C: New test. * g++.dg/ext/pr85329.C: New test. * gcc.target/i386/mvc12.c: New test. From-SVN: r259428
This commit is contained in:
parent
42c884b130
commit
646cf25275
|
@ -1,3 +1,15 @@
|
|||
2018-04-17 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR ipa/85329
|
||||
* 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 empty
|
||||
string.
|
||||
(expand_target_clones): Handle it.
|
||||
(ipa_target_clone): Make redirection just for target_clones
|
||||
functions.
|
||||
|
||||
2018-04-16 Cesar Philippidis <cesar@codesourcery.com>
|
||||
Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2018-04-17 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR ipa/85329
|
||||
* g++.dg/ext/pr85329-2.C: New test.
|
||||
* g++.dg/ext/pr85329.C: New test.
|
||||
* gcc.target/i386/mvc12.c: New test.
|
||||
|
||||
2018-04-16 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
PR c++/85039
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
}
|
|
@ -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]; }
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue