From 38a8aecfb882072900434499696b5c32a2274515 Mon Sep 17 00:00:00 2001 From: Rong Xu Date: Mon, 21 Jul 2014 16:47:22 -0700 Subject: [4.9] Switch gcc-4.9 to use google/gcc-4_9 branch. This source drop uses svn version r212828 of google/gcc-4.9 branch. We also cherry-picked r213062, r213063 and r213064 to fix windows build issues. All gcc-4.9 patches before July 3rd are ported to google/gcc-4.9. The following prior commits has not been merged to google branch yet. (They are included in this commit). e7af147f979e657fe2df00808e5b4319b0e088c6, baf87df3cb2683649ba7e9872362a7e721117c23, and c231900e5dcc14d8296bd9f62b45997a49d4d5e7. Change-Id: I4bea3ea470387ff751c2be4cb0d4a12059b9299b --- gcc-4.9/gcc/cgraphunit.c | 191 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 179 insertions(+), 12 deletions(-) (limited to 'gcc-4.9/gcc/cgraphunit.c') diff --git a/gcc-4.9/gcc/cgraphunit.c b/gcc-4.9/gcc/cgraphunit.c index 06283fc3f..83e436f76 100644 --- a/gcc-4.9/gcc/cgraphunit.c +++ b/gcc-4.9/gcc/cgraphunit.c @@ -193,6 +193,7 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "function.h" #include "ipa-prop.h" +#include "gcov-io.h" #include "tree-iterator.h" #include "tree-pass.h" #include "tree-dump.h" @@ -203,6 +204,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-inline.h" #include "ipa-utils.h" #include "lto-streamer.h" +#include "l-ipo.h" #include "except.h" #include "cfgloop.h" #include "regset.h" /* FIXME: For reg_obstack. */ @@ -244,7 +246,8 @@ decide_is_symbol_needed (symtab_node *node) /* Double check that no one output the function into assembly file early. */ gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl) - || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); + || (L_IPO_COMP_MODE + || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))); if (!node->definition) return false; @@ -292,6 +295,12 @@ enqueue_node (symtab_node *node) queued_nodes = node; } +void +cgraph_enqueue_node (struct cgraph_node *node) +{ + enqueue_node ((symtab_node *) node); +} + /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these functions into callgraph in a way so they look like ordinary reachable functions inserted into callgraph already at construction time. */ @@ -491,6 +500,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) { gcc::pass_manager *passes = g->get_passes (); struct cgraph_node *node; + switch (cgraph_state) { case CGRAPH_STATE_PARSING: @@ -551,7 +561,6 @@ cgraph_add_new_function (tree fndecl, bool lowered) pop_cfun (); expand_function (node); break; - default: gcc_unreachable (); } @@ -972,7 +981,8 @@ analyze_functions (void) fprintf (cgraph_dump_file, "Trivially needed symbols:"); changed = true; if (cgraph_dump_file) - fprintf (cgraph_dump_file, " %s", node->asm_name ()); + fprintf (cgraph_dump_file, " %s/%d", node->asm_name (), + node->order); if (!changed && cgraph_dump_file) fprintf (cgraph_dump_file, "\n"); } @@ -1085,7 +1095,7 @@ analyze_functions (void) if (!node->aux && !referred_to_p (node)) { if (cgraph_dump_file) - fprintf (cgraph_dump_file, " %s", node->name ()); + fprintf (cgraph_dump_file, " %s/%d", node->name (), node->order); symtab_remove_node (node); continue; } @@ -1205,6 +1215,137 @@ handle_alias_pairs (void) vec_free (alias_pairs); } +/* Hash function for symbol (function) resolution. */ + +static hashval_t +hash_node_by_assembler_name (const void *p) +{ + const struct cgraph_node *n = (const struct cgraph_node *) p; + return (hashval_t) decl_assembler_name_hash ( + DECL_ASSEMBLER_NAME (n->decl)); +} + +/* Equality function for cgraph_node table. */ + +static int +eq_node_assembler_name (const void *p1, const void *p2) +{ + const struct cgraph_node *n1 = (const struct cgraph_node *) p1; + const_tree name = (const_tree)p2; + return (decl_assembler_name_equal (n1->decl, name)); +} + +/* In l-ipo mode compilation (light weight IPO), multiple bodies may + be available for the same inline declared function. cgraph linking + does not really merge them in order to keep the context (module info) + of each body. After inlining, the linkage of the function may require + them to be output (even if it is defined in an auxiliary module). This + in term may result in duplicate emission. */ + +static GTY((param_is (symtab_node))) htab_t output_node_hash = NULL; + +/* Add NODE that is expanded into the hashtable. */ + +static struct cgraph_node * +cgraph_add_output_node (struct cgraph_node *node) +{ + void **aslot; + tree name; + + if (!L_IPO_COMP_MODE) + return node; + + /* Never common non public names except for compiler + generated static functions. (they are not promoted + to globals either. */ + if (!TREE_PUBLIC (node->decl) + && !(DECL_ARTIFICIAL (node->decl) + && DECL_ASSEMBLER_NAME_SET_P (node->decl))) + return node; + + if (!output_node_hash) + output_node_hash = + htab_create_ggc (10, hash_node_by_assembler_name, + eq_node_assembler_name, NULL); + + name = DECL_ASSEMBLER_NAME (node->decl); + + aslot = htab_find_slot_with_hash (output_node_hash, name, + decl_assembler_name_hash (name), + INSERT); + if (*aslot == NULL) + { + *aslot = node; + return node; + } + else + return (struct cgraph_node *)(*aslot); +} + +#if ENABLE_CHECKING +/* Return the cgraph_node if the function symbol for NODE is + expanded in the output. Returns NULL otherwise. */ + +static struct cgraph_node * +cgraph_find_output_node (struct cgraph_node *node) +{ + void **aslot; + tree name; + + if (!L_IPO_COMP_MODE) + return node; + + /* We do not track non-public functions. */ + if (!TREE_PUBLIC (node->decl)) + return NULL; + + /* Never addedd. */ + if (!output_node_hash) + return NULL; + + name = DECL_ASSEMBLER_NAME (node->decl); + + aslot = htab_find_slot_with_hash (output_node_hash, name, + decl_assembler_name_hash (name), + NO_INSERT); + if (!aslot) + return NULL; + + return (struct cgraph_node *)(*aslot); +} +#endif + + +#if ENABLE_CHECKING +/* A function used in validation. Return true if NODE was + not expanded and its body was not reclaimed. */ + +static bool +cgraph_node_expansion_skipped (struct cgraph_node *node) +{ + struct cgraph_node *output_node; + + if (!L_IPO_COMP_MODE) + return false; + + output_node = cgraph_find_output_node (node); + + if (output_node == node) + return false; + + if (output_node) + return true; + + /* No output, no duplicate being output, and the node is not + inlined (and reclaimed) either -- check if the caller node + is output/expanded or not. */ + if (node->global.inlined_to) + return cgraph_node_expansion_skipped (node->global.inlined_to); + + /* External functions not marked for output. */ + return true; +} +#endif /* Figure out what functions we want to assemble. */ @@ -1235,8 +1376,10 @@ mark_functions_to_output (void) && !node->alias && !node->global.inlined_to && !TREE_ASM_WRITTEN (decl) - && !DECL_EXTERNAL (decl)) + && !(DECL_EXTERNAL (decl) || cgraph_is_aux_decl_external (node))) { + if (cgraph_add_output_node (node) == node) { + /* Do not fix indentation. */ node->process = 1; if (node->same_comdat_group) { @@ -1245,9 +1388,11 @@ mark_functions_to_output (void) next != node; next = cgraph (next->same_comdat_group)) if (!next->thunk.thunk_p && !next->alias + && cgraph_add_output_node (next) == next && !symtab_comdat_local_p (next)) next->process = 1; } + } } else if (node->same_comdat_group) { @@ -1266,6 +1411,7 @@ mark_functions_to_output (void) have analyzed node pointing to it. */ && !node->in_other_partition && !node->alias + && !cgraph_is_auxiliary (node->decl) && !node->clones && !DECL_EXTERNAL (decl)) { @@ -1278,13 +1424,14 @@ mark_functions_to_output (void) || node->in_other_partition || node->clones || DECL_ARTIFICIAL (decl) - || DECL_EXTERNAL (decl)); + || DECL_EXTERNAL (decl) + || cgraph_is_auxiliary (node->decl)); } } #ifdef ENABLE_CHECKING - if (check_same_comdat_groups) + if (check_same_comdat_groups && !L_IPO_COMP_MODE) FOR_EACH_FUNCTION (node) if (node->same_comdat_group && !node->process) { @@ -1297,7 +1444,8 @@ mark_functions_to_output (void) analyzed node pointing to it. */ && !node->in_other_partition && !node->clones - && !DECL_EXTERNAL (decl)) + && !(DECL_EXTERNAL (decl) || cgraph_is_aux_decl_external (node)) + && !L_IPO_COMP_MODE) { dump_cgraph_node (stderr, node); internal_error ("failed to reclaim unneeded function in same " @@ -1680,6 +1828,7 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks) #ifdef ENABLE_CHECKING verify_flow_info (); #endif + free_dominance_info (CDI_DOMINATORS); /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ @@ -1963,6 +2112,8 @@ output_in_order (void) max = symtab_order; nodes = XCNEWVEC (struct cgraph_order_sort, max); + varpool_remove_duplicate_weak_decls (); + FOR_EACH_DEFINED_FUNCTION (pf) { if (pf->process && !pf->thunk.thunk_p && !pf->alias) @@ -2058,8 +2209,11 @@ ipa_passes (void) if (!in_lto_p) { - /* Generate coverage variables and constructors. */ - coverage_finish (); + /* Generate coverage variables and constructors. + In LIPO mode, delay this until direct call profiling + is done. */ + if (!flag_dyn_ipa) + coverage_finish (); /* Process new functions added. */ set_cfun (NULL); @@ -2165,6 +2319,12 @@ compile (void) fprintf (stderr, "Performing interprocedural optimizations\n"); cgraph_state = CGRAPH_STATE_IPA; + if (L_IPO_COMP_MODE) + { + cgraph_init_gid_map (); + cgraph_add_fake_indirect_call_edges (); + } + /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */ if (flag_lto) lto_streamer_hooks_init (); @@ -2250,6 +2410,7 @@ compile (void) output_asm_statements (); expand_all_functions (); + varpool_remove_duplicate_weak_decls (); varpool_output_variables (); } @@ -2265,15 +2426,21 @@ compile (void) #ifdef ENABLE_CHECKING verify_symtab (); /* Double check that all inline clones are gone and that all - function bodies have been released from memory. */ + function bodies have been released from memory. + As an exception, allow inline clones in the callgraph if + they are auxiliary functions. This is because we don't + expand any of the auxiliary functions, which may result + in inline clones of some auxiliary functions to be left + in the callgraph. */ if (!seen_error ()) { struct cgraph_node *node; bool error_found = false; FOR_EACH_DEFINED_FUNCTION (node) - if (node->global.inlined_to + if (((node->global.inlined_to && !cgraph_is_auxiliary (node->decl)) || gimple_has_body_p (node->decl)) + && !cgraph_node_expansion_skipped (node)) { error_found = true; dump_cgraph_node (stderr, node); -- cgit v1.2.3