> Hello. > > Currently ifunc is interpreted as normal alias by IPA optimizations. That's > problematic > as should not consider ifunc alias as candidate for inlining, or redirection. > > Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. > And survives MVC tests on x86_64-linux-gnu. > > Ready to be installed?
Wasn't this supposed to go with arranging availability to be AVAIL_INTERPOSABLE (as the target will be interposed by linker to the corect target) Honza > Martin > > gcc/ChangeLog: > > 2017-06-22 Martin Liska <mli...@suse.cz> > > * ipa-inline.c (can_inline_edge_p): Return false for ifunc fns. > * ipa-visibility.c (can_replace_by_local_alias): Likewise. > > gcc/c-family/ChangeLog: > > 2017-06-22 Martin Liska <mli...@suse.cz> > > * c-attribs.c (handle_alias_ifunc_attribute): Append ifunc alias > to a function declaration. > > gcc/testsuite/ChangeLog: > > 2017-06-22 Martin Liska <mli...@suse.cz> > > * gcc.target/i386/pr81128.c: New test. > --- > gcc/c-family/c-attribs.c | 11 ++++-- > gcc/ipa-inline.c | 2 + > gcc/ipa-visibility.c | 3 +- > gcc/testsuite/gcc.target/i386/pr81128.c | 65 > +++++++++++++++++++++++++++++++++ > 4 files changed, 77 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr81128.c > > > diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c > index 2b6845f2cbd..626ffa1cde7 100644 > --- a/gcc/c-family/c-attribs.c > +++ b/gcc/c-family/c-attribs.c > @@ -1846,9 +1846,14 @@ handle_alias_ifunc_attribute (bool is_alias, tree > *node, tree name, tree args, > TREE_STATIC (decl) = 1; > > if (!is_alias) > - /* ifuncs are also aliases, so set that attribute too. */ > - DECL_ATTRIBUTES (decl) > - = tree_cons (get_identifier ("alias"), args, DECL_ATTRIBUTES (decl)); > + { > + /* ifuncs are also aliases, so set that attribute too. */ > + DECL_ATTRIBUTES (decl) > + = tree_cons (get_identifier ("alias"), args, > + DECL_ATTRIBUTES (decl)); > + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"), > + NULL, DECL_ATTRIBUTES (decl)); > + } > } > else > { > diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c > index fb20d3723cc..588fa9c41e4 100644 > --- a/gcc/ipa-inline.c > +++ b/gcc/ipa-inline.c > @@ -370,6 +370,8 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, > e->inline_failed = CIF_ATTRIBUTE_MISMATCH; > inlinable = false; > } > + else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (e->callee->decl))) > + inlinable = false; > /* Check if caller growth allows the inlining. */ > else if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl) > && !disregard_limits > diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c > index d5a3ae56c46..79d05b41085 100644 > --- a/gcc/ipa-visibility.c > +++ b/gcc/ipa-visibility.c > @@ -345,7 +345,8 @@ can_replace_by_local_alias (symtab_node *node) > > return (node->get_availability () > AVAIL_INTERPOSABLE > && !decl_binds_to_current_def_p (node->decl) > - && !node->can_be_discarded_p ()); > + && !node->can_be_discarded_p () > + && !lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->decl))); > } > > /* Return true if we can replace reference to NODE by local alias > diff --git a/gcc/testsuite/gcc.target/i386/pr81128.c > b/gcc/testsuite/gcc.target/i386/pr81128.c > new file mode 100644 > index 00000000000..90a567ad690 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr81128.c > @@ -0,0 +1,65 @@ > +/* PR ipa/81128 */ > +/* { dg-do run } */ > +/* { dg-options "-O3" } */ > +/* { dg-require-ifunc "" } */ > + > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <time.h> > + > +int resolver_fn = 0; > +int resolved_fn = 0; > + > +static inline void > +do_it_right_at_runtime_A () > +{ > + resolved_fn++; > +} > + > +static inline void > +do_it_right_at_runtime_B () > +{ > + resolved_fn++; > +} > + > +static inline void do_it_right_at_runtime (void); > + > +void do_it_right_at_runtime (void) > + __attribute__ ((ifunc ("resolve_do_it_right_at_runtime"))); > + > +static void (*resolve_do_it_right_at_runtime (void)) (void) > +{ > + srand (time (NULL)); > + int r = rand (); > + resolver_fn++; > + > + /* Use intermediate variable to get a warning for non-matching > + * prototype. */ > + typeof(do_it_right_at_runtime) *func; > + if (r & 1) > + func = do_it_right_at_runtime_A; > + else > + func = do_it_right_at_runtime_B; > + > + return (void *) func; > +} > + > +int > +main (void) > +{ > + const unsigned int ITERS = 10; > + > + for (int i = ITERS; i > 0; i--) > + { > + do_it_right_at_runtime (); > + } > + > + if (resolver_fn != 1) > + __builtin_abort (); > + > + if (resolved_fn != 10) > + __builtin_abort (); > + > + return 0; > +} >