From 646cf2527541fb8928deee0d7eda9ca75a591328 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 17 Apr 2018 07:40:39 +0200 Subject: [PATCH] Make redirection only for target_clones: V3 (PR ipa/85329). 2018-04-17 Martin Liska 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 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 --- gcc/ChangeLog | 12 ++++++ gcc/multiple_target.c | 55 ++++++++++++++++++++------- gcc/testsuite/ChangeLog | 7 ++++ gcc/testsuite/g++.dg/ext/pr85329-2.C | 22 +++++++++++ gcc/testsuite/g++.dg/ext/pr85329.C | 19 +++++++++ gcc/testsuite/gcc.target/i386/mvc12.c | 11 ++++++ 6 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/pr85329-2.C create mode 100644 gcc/testsuite/g++.dg/ext/pr85329.C create mode 100644 gcc/testsuite/gcc.target/i386/mvc12.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index caef3054ec6..a96c8decffc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2018-04-17 Martin Liska + + 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 Tom de Vries diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c index b006a5ab6ec..a1fe09a5983 100644 --- a/gcc/multiple_target.c +++ b/gcc/multiple_target.c @@ -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 % 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 % 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 % 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 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 33258e6f4fc..a7dd355e5a5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-04-17 Martin Liska + + 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 PR c++/85039 diff --git a/gcc/testsuite/g++.dg/ext/pr85329-2.C b/gcc/testsuite/g++.dg/ext/pr85329-2.C new file mode 100644 index 00000000000..24622d404f7 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr85329-2.C @@ -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 () +{ +} diff --git a/gcc/testsuite/g++.dg/ext/pr85329.C b/gcc/testsuite/g++.dg/ext/pr85329.C new file mode 100644 index 00000000000..fb77e42cd78 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr85329.C @@ -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]; } diff --git a/gcc/testsuite/gcc.target/i386/mvc12.c b/gcc/testsuite/gcc.target/i386/mvc12.c new file mode 100644 index 00000000000..f42ae8080e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mvc12.c @@ -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(); +} -- 2.30.2