diff options
Diffstat (limited to 'gcc/ipa-visibility.c')
-rw-r--r-- | gcc/ipa-visibility.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c index d5a3ae56c46..3033f20e3f1 100644 --- a/gcc/ipa-visibility.c +++ b/gcc/ipa-visibility.c @@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "calls.h" #include "varasm.h" +#include "ipa-utils.h" /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */ @@ -91,13 +92,15 @@ non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { return !(node->only_called_directly_or_aliased_p () /* i386 would need update to output thunk with local calling - convetions. */ + conventions. */ && !node->thunk.thunk_p && node->definition && !DECL_EXTERNAL (node->decl) + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)) && !node->externally_visible && !node->used_from_other_partition - && !node->in_other_partition); + && !node->in_other_partition + && node->get_availability () >= AVAIL_AVAILABLE); } /* Return true when function can be marked local. */ @@ -209,6 +212,8 @@ cgraph_externally_visible_p (struct cgraph_node *node, if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl))) return true; + if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))) + return true; if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && lookup_attribute ("dllexport", DECL_ATTRIBUTES (node->decl))) @@ -613,17 +618,53 @@ function_and_variable_visibility (bool whole_program) struct cgraph_node *node; varpool_node *vnode; - /* All aliases should be procssed at this point. */ + /* All aliases should be processed at this point. */ gcc_checking_assert (!alias_pairs || !alias_pairs->length ()); +#ifdef ASM_OUTPUT_DEF + FOR_EACH_DEFINED_FUNCTION (node) + { + if (node->get_availability () != AVAIL_INTERPOSABLE + || DECL_EXTERNAL (node->decl) + || node->has_aliases_p ()) + continue; + + cgraph_node *alias = 0; + for (cgraph_edge *e = node->callees; e; e = e->next_callee) + { + /* Recursive function calls usually can't be interposed. */ + + if (!e->recursive_p ()) + continue; + + if (!alias) + { + alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ()); + gcc_assert (alias && alias != node); + } + + e->redirect_callee (alias); + if (gimple_has_body_p (e->caller->decl)) + { + push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); + e->redirect_call_stmt_to_callee (); + pop_cfun (); + } + } + } +#endif + FOR_EACH_FUNCTION (node) { int flags = flags_from_decl_or_type (node->decl); /* Optimize away PURE and CONST constructors and destructors. */ - if (optimize + if (node->analyzed + && (DECL_STATIC_CONSTRUCTOR (node->decl) + || DECL_STATIC_DESTRUCTOR (node->decl)) && (flags & (ECF_CONST | ECF_PURE)) - && !(flags & ECF_LOOPING_CONST_OR_PURE)) + && !(flags & ECF_LOOPING_CONST_OR_PURE) + && opt_for_fn (node->decl, optimize)) { DECL_STATIC_CONSTRUCTOR (node->decl) = 0; DECL_STATIC_DESTRUCTOR (node->decl) = 0; @@ -875,7 +916,7 @@ static unsigned int whole_program_function_and_variable_visibility (void) { function_and_variable_visibility (flag_whole_program); - if (optimize) + if (optimize || in_lto_p) ipa_discover_readonly_nonaddressable_vars (); return 0; } |