diff options
author | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
---|---|---|
committer | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
commit | 7f4db7c80779ecbc57d1146654daf0acfe18de66 (patch) | |
tree | 3af522a3b5e149c3fd498ecb1255994daae2129a /gcc/ipa.c | |
parent | 611349f0ec42a37591db2cd02974a11a48d10edb (diff) | |
download | gcc-profile-stdlib.tar.gz |
merge from trunkprofile-stdlib
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/profile-stdlib@154052 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r-- | gcc/ipa.c | 126 |
1 files changed, 111 insertions, 15 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c index 9204caae77b..c859242fa70 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -52,7 +52,9 @@ cgraph_postorder (struct cgraph_node **order) for (pass = 0; pass < 2; pass++) for (node = cgraph_nodes; node; node = node->next) if (!node->aux - && (pass || (node->needed && !node->address_taken))) + && (pass + || (!cgraph_only_called_directly_p (node) + && !node->address_taken))) { node2 = node; if (!node->callers) @@ -132,11 +134,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) gcc_assert (!node->aux); #endif for (node = cgraph_nodes; node; node = node->next) - if (node->needed && !node->global.inlined_to + if (!cgraph_can_remove_if_no_direct_calls_p (node) && ((!DECL_EXTERNAL (node->decl)) || !node->analyzed || before_inlining_p)) { + gcc_assert (!node->global.inlined_to); node->aux = first; first = node; } @@ -248,6 +251,28 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) return changed; } +static bool +cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program) +{ + if (!node->local.finalized) + return false; + if (!DECL_COMDAT (node->decl) + && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))) + return false; + if (!whole_program) + return true; + /* COMDAT functions must be shared only if they have address taken, + otherwise we can produce our own private implementation with + -fwhole-program. */ + if (DECL_COMDAT (node->decl) && (node->address_taken || !node->analyzed)) + return true; + if (MAIN_NAME_P (DECL_NAME (node->decl))) + return true; + if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl))) + return true; + return false; +} + /* Mark visibility of all functions. A local function is one whose calls can occur only in the current @@ -260,38 +285,48 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) via visibilities for the backend point of view. */ static unsigned int -function_and_variable_visibility (void) +function_and_variable_visibility (bool whole_program) { struct cgraph_node *node; struct varpool_node *vnode; for (node = cgraph_nodes; node; node = node->next) { - if (node->reachable - && (DECL_COMDAT (node->decl) - || (!flag_whole_program - && TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl)))) - node->local.externally_visible = true; + if (cgraph_externally_visible_p (node, whole_program)) + { + gcc_assert (!node->global.inlined_to); + node->local.externally_visible = true; + } + else + node->local.externally_visible = false; if (!node->local.externally_visible && node->analyzed && !DECL_EXTERNAL (node->decl)) { - gcc_assert (flag_whole_program || !TREE_PUBLIC (node->decl)); + gcc_assert (whole_program || !TREE_PUBLIC (node->decl)); TREE_PUBLIC (node->decl) = 0; + DECL_COMDAT (node->decl) = 0; + DECL_WEAK (node->decl) = 0; } - node->local.local = (!node->needed + node->local.local = (cgraph_only_called_directly_p (node) && node->analyzed && !DECL_EXTERNAL (node->decl) && !node->local.externally_visible); } for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) { + if (!vnode->finalized) + continue; if (vnode->needed - && !flag_whole_program - && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))) - vnode->externally_visible = 1; + && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)) + && (!whole_program + || lookup_attribute ("externally_visible", + DECL_ATTRIBUTES (vnode->decl)))) + vnode->externally_visible = true; + else + vnode->externally_visible = false; if (!vnode->externally_visible) { - gcc_assert (flag_whole_program || !TREE_PUBLIC (vnode->decl)); + gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl)); TREE_PUBLIC (vnode->decl) = 0; } gcc_assert (TREE_STATIC (vnode->decl)); @@ -314,13 +349,22 @@ function_and_variable_visibility (void) return 0; } +/* Local function pass handling visibilities. This happens before LTO streaming + so in particular -fwhole-program should be ignored at this level. */ + +static unsigned int +local_function_and_variable_visibility (void) +{ + return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr); +} + struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility = { { SIMPLE_IPA_PASS, "visibility", /* name */ NULL, /* gate */ - function_and_variable_visibility, /* execute */ + local_function_and_variable_visibility,/* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ @@ -333,6 +377,58 @@ struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility = } }; +/* Do not re-run on ltrans stage. */ + +static bool +gate_whole_program_function_and_variable_visibility (void) +{ + return !flag_ltrans; +} + +/* Bring functionss local at LTO time whith -fwhole-program. */ + +static unsigned int +whole_program_function_and_variable_visibility (void) +{ + struct cgraph_node *node; + struct varpool_node *vnode; + + function_and_variable_visibility (flag_whole_program); + + for (node = cgraph_nodes; node; node = node->next) + if (node->local.externally_visible && node->local.finalized) + cgraph_mark_needed_node (node); + for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) + if (vnode->externally_visible) + varpool_mark_needed_node (vnode); + return 0; +} + +struct ipa_opt_pass_d pass_ipa_whole_program_visibility = +{ + { + IPA_PASS, + "whole-program", /* name */ + gate_whole_program_function_and_variable_visibility,/* gate */ + whole_program_function_and_variable_visibility,/* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_CGRAPHOPT, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */ + }, + NULL, /* generate_summary */ + NULL, /* write_summary */ + NULL, /* read_summary */ + NULL, /* function_read_summary */ + 0, /* TODOs */ + NULL, /* function_transform */ + NULL, /* variable_transform */ +}; /* Hash a cgraph node set element. */ |