diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-25 16:31:42 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-25 16:31:42 +0000 |
commit | da5e1e7ce7a1323e3eeeeacd3687823d83cd1025 (patch) | |
tree | 59428eb8af21f903b36ff6bf0614f87d9cb27f0d /gcc/cgraphunit.c | |
parent | 2e4c90f020156f2a6054853e25bd6e1a2b0d98e6 (diff) | |
download | gcc-da5e1e7ce7a1323e3eeeeacd3687823d83cd1025.tar.gz |
* cgraphunit.c: Update toplevel comment.
(tree_rest_of_compilation): Merge into cgraph_expand_function.
(cgraph_analyze_function): Make static.
(cgraph_decide_is_function_needed): Make static.
(cgraph_add_new_function): Use expand_function instead of
rest_of_compilation.
(clone_of_p, verify_edge_count_and_frequency, cgraph_debug_gimple_stmt,
verify_edge_corresponds_to_fndecl, verify_cgraph_node, verify_cgraph):
Move to cgraph.c
(cgraph_inline_p): Remove.
(cgraph_preserve_function_body_p): Move to ipa-inline-transform.
(init_cgraph): Add comment.
* cgraphbuild.c (record_reference, mark_address, mark_load,
mark_store): Do not call analyze_expr hook.
* cgraph.c: Update toplevel comment.
(clone_of_p, verify_edge_count_and_frequency, cgraph_debug_gimple_stmt,
verify_edge_corresponds_to_fndecl, verify_cgraph_node, verify_cgraph):
Move fere from cgraphunit.c
(cgraph_mark_force_output_node): Move to cgraph.h
* cgraph.h: Reorder so the comments match the function placement.
(cgraph_analyze_function, cgraph_decide_is_function_needed): Remove.
(cgraph_mark_force_output_node): Move here from cgraph.c
* tree.c (free_lang_data): Do not clear analyze_expr hook.
* ipa-inline-transform.c (preserve_function_body_p): New function.
(inline_transform): Update.
* langhooks.c (lhd_callgraph_analyze_expr): Remove.
* langhooks.h (lang_hooks_for_callgraph): Remove.
(lang_hooks): Remove callgraph.
* tree-inline.c (expand_call_inline): Do not use cgraph_inline_p.
* varpool.c: Remove out of date comment.
* langhooks-def.h (lhd_callgraph_analyze_expr): Remove.
(LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR): Remove.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186832 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r-- | gcc/cgraphunit.c | 640 |
1 files changed, 129 insertions, 511 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index a58cd08c0d9..60ccc82591d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1,4 +1,4 @@ -/* Callgraph based interprocedural optimizations. +/* Driver of optimization process Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Jan Hubicka @@ -19,11 +19,10 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ -/* This module implements main driver of compilation process as well as - few basic interprocedural optimizers. +/* This module implements main driver of compilation process. The main scope of this file is to act as an interface in between - tree based frontends and the backend (and middle end) + tree based frontends and the backend. The front-end is supposed to use following functionality: @@ -45,66 +44,115 @@ along with GCC; see the file COPYING3. If not see This function is called once (source level) compilation unit is finalized and it will no longer change. - In the call-graph construction and local function analysis takes - place here. Bodies of unreachable functions are released to - conserve memory usage. + The symbol table is constructed starting from the trivially needed + symbols finalized by the frontend. Functions are lowered into + GIMPLE representation and callgraph/reference lists are constructed. + Those are used to discover other neccesary functions and variables. + + At the end the bodies of unreachable functions are removed. The function can be called multiple times when multiple source level - compilation units are combined (such as in C frontend) + compilation units are combined. - cgraph_optimize - In this unit-at-a-time compilation the intra procedural analysis takes - place here. In particular the static functions whose address is never - taken are marked as local. Backend can then use this information to - modify calling conventions, do better inlining or similar optimizations. + This passes control to the back-end. Optimizations are performed and + final assembler is generated. This is done in the following way. Note + that with link time optimization the process is split into three + stages (compile time, linktime analysis and parallel linktime as + indicated bellow). + + Compile time: + + 1) Inter-procedural optimization. + (ipa_passes) + + This part is further split into: + + a) early optimizations. These are local passes executed in + the topological order on the callgraph. + + The purpose of early optimiations is to optimize away simple + things that may otherwise confuse IP analysis. Very simple + propagation across the callgraph is done i.e. to discover + functions without side effects and simple inlining is performed. + + b) early small interprocedural passes. + + Those are interprocedural passes executed only at compilation + time. These include, for exmaple, transational memory lowering, + unreachable code removal and other simple transformations. + + c) IP analysis stage. All interprocedural passes do their + analysis. + + Interprocedural passes differ from small interprocedural + passes by their ability to operate across whole program + at linktime. Their analysis stage is performed early to + both reduce linking times and linktime memory usage by + not having to represent whole program in memory. + + d) LTO sreaming. When doing LTO, everything important gets + streamed into the object file. + + Compile time and or linktime analysis stage (WPA): + + At linktime units gets streamed back and symbol table is + merged. Function bodies are not streamed in and not + available. + e) IP propagation stage. All IP passes execute their + IP propagation. This is done based on the earlier analysis + without having function bodies at hand. + f) Ltrans streaming. When doing WHOPR LTO, the program + is partitioned and streamed into multple object files. + + Compile time and/or parallel linktime stage (ltrans) - - cgraph_mark_needed_node - - varpool_mark_needed_node + Each of the object files is streamed back and compiled + separately. Now the function bodies becomes available + again. - When function or variable is referenced by some hidden way the call-graph - data structure must be updated accordingly by this function. - There should be little need to call this function and all the references - should be made explicit to cgraph code. At present these functions are - used by C++ frontend to explicitly mark the keyed methods. + 2) Virtual clone materialization + (cgraph_materialize_clone) - - analyze_expr callback + IP passes can produce copies of existing functoins (such + as versioned clones or inline clones) without actually + manipulating their bodies by creating virtual clones in + the callgraph. At this time the virtual clones are + turned into real functions + 3) IP transformation - This function is responsible for lowering tree nodes not understood by - generic code into understandable ones or alternatively marking - callgraph and varpool nodes referenced by the as needed. + All IP passes transform function bodies based on earlier + decision of the IP propagation. - ??? On the tree-ssa genericizing should take place here and we will avoid - need for these hooks (replacing them by genericizing hook) + 4) late small IP passes - Analyzing of all functions is deferred - to cgraph_finalize_compilation_unit and expansion into cgraph_optimize. + Simple IP passes working within single program partition. - In cgraph_finalize_compilation_unit the reachable functions are - analyzed. During analysis the call-graph edges from reachable - functions are constructed and their destinations are marked as - reachable. References to functions and variables are discovered too - and variables found to be needed output to the assembly file. Via - mark_referenced call in assemble_variable functions referenced by - static variables are noticed too. + 5) Expansion + (cgraph_expand_all_functions) - The intra-procedural information is produced and its existence - indicated by global_info_ready. Once this flag is set it is impossible - to change function from !reachable to reachable and thus - assemble_variable no longer call mark_referenced. + At this stage functions that needs to be output into + assembler are identified and compiled in topological order + 6) Output of variables and aliases + Now it is known what variable references was not optimized + out and thus all variables are output to the file. - Finally the call-graph is topologically sorted and all reachable functions - that has not been completely inlined or are not external are output. + Note that with -fno-toplevel-reorder passes 5 and 6 + are combined together in cgraph_output_in_order. - ??? It is possible that reference to function or variable is optimized - out. We can not deal with this nicely because topological order is not - suitable for it. For tree-ssa we may consider another pass doing - optimization and re-discovering reachable functions. + Finally there are functions to manipulate the callgraph from + backend. + - cgraph_add_new_function is used to add backend produced + functions introduced after the unit is finalized. + The functions are enqueue for later processing and inserted + into callgraph with cgraph_process_new_functions. - ??? Reorganize code so variables are output very last and only if they - really has been referenced by produced code, so we catch more cases - where reference has been optimized out. */ + - cgraph_function_versioning + produces a copy of function into new one (a version) + and apply simple transformations +*/ #include "config.h" #include "system.h" @@ -124,8 +172,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "cgraph.h" #include "diagnostic.h" -#include "tree-pretty-print.h" -#include "gimple-pretty-print.h" #include "timevar.h" #include "params.h" #include "fibheap.h" @@ -136,6 +182,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "tree-pass.h" #include "tree-dump.h" +#include "gimple-pretty-print.h" #include "output.h" #include "coverage.h" #include "plugin.h" @@ -154,7 +201,7 @@ static void cgraph_expand_all_functions (void); static void cgraph_mark_functions_to_output (void); static void cgraph_expand_function (struct cgraph_node *); static void cgraph_output_pending_asms (void); -static void tree_rest_of_compilation (struct cgraph_node *); +static void cgraph_analyze_function (struct cgraph_node *); FILE *cgraph_dump_file; @@ -166,7 +213,7 @@ static GTY (()) tree vtable_entry_type; and differs from later logic removing unnecesary functions that can take into account results of analysis, whole program info etc. */ -bool +static bool cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl) { /* If the user told us it is used, then it must be so. */ @@ -470,8 +517,8 @@ cgraph_add_new_function (tree fndecl, bool lowered) if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) execute_pass_list (pass_early_local_passes.pass.sub); bitmap_obstack_release (NULL); - tree_rest_of_compilation (node); pop_cfun (); + cgraph_expand_function (node); current_function_decl = NULL; break; @@ -486,404 +533,6 @@ cgraph_add_new_function (tree fndecl, bool lowered) DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); } -/* Return TRUE if NODE2 is equivalent to NODE or its clone. */ -static bool -clone_of_p (struct cgraph_node *node, struct cgraph_node *node2) -{ - node = cgraph_function_or_thunk_node (node, NULL); - node2 = cgraph_function_or_thunk_node (node2, NULL); - while (node != node2 && node2) - node2 = node2->clone_of; - return node2 != NULL; -} - -/* Verify edge E count and frequency. */ - -static bool -verify_edge_count_and_frequency (struct cgraph_edge *e) -{ - bool error_found = false; - if (e->count < 0) - { - error ("caller edge count is negative"); - error_found = true; - } - if (e->frequency < 0) - { - error ("caller edge frequency is negative"); - error_found = true; - } - if (e->frequency > CGRAPH_FREQ_MAX) - { - error ("caller edge frequency is too large"); - error_found = true; - } - if (gimple_has_body_p (e->caller->symbol.decl) - && !e->caller->global.inlined_to - /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out. - Remove this once edges are actualy removed from the function at that time. */ - && (e->frequency - || (inline_edge_summary_vec - && ((VEC_length(inline_edge_summary_t, inline_edge_summary_vec) - <= (unsigned) e->uid) - || !inline_edge_summary (e)->predicate))) - && (e->frequency - != compute_call_stmt_bb_frequency (e->caller->symbol.decl, - gimple_bb (e->call_stmt)))) - { - error ("caller edge frequency %i does not match BB frequency %i", - e->frequency, - compute_call_stmt_bb_frequency (e->caller->symbol.decl, - gimple_bb (e->call_stmt))); - error_found = true; - } - return error_found; -} - -/* Switch to THIS_CFUN if needed and print STMT to stderr. */ -static void -cgraph_debug_gimple_stmt (struct function *this_cfun, gimple stmt) -{ - /* debug_gimple_stmt needs correct cfun */ - if (cfun != this_cfun) - set_cfun (this_cfun); - debug_gimple_stmt (stmt); -} - -/* Verify that call graph edge E corresponds to DECL from the associated - statement. Return true if the verification should fail. */ - -static bool -verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl) -{ - struct cgraph_node *node; - - if (!decl || e->callee->global.inlined_to) - return false; - node = cgraph_get_node (decl); - - /* We do not know if a node from a different partition is an alias or what it - aliases and therefore cannot do the former_clone_of check reliably. */ - if (!node || node->symbol.in_other_partition) - return false; - node = cgraph_function_or_thunk_node (node, NULL); - - if ((e->callee->former_clone_of != node->symbol.decl - && (!node->same_body_alias - || e->callee->former_clone_of != node->thunk.alias)) - /* IPA-CP sometimes redirect edge to clone and then back to the former - function. This ping-pong has to go, eventually. */ - && (node != cgraph_function_or_thunk_node (e->callee, NULL)) - && !clone_of_p (node, e->callee) - /* If decl is a same body alias of some other decl, allow e->callee to be - a clone of a clone of that other decl too. */ - && (!node->same_body_alias - || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee))) - return true; - else - return false; -} - -/* Verify cgraph nodes of given cgraph node. */ -DEBUG_FUNCTION void -verify_cgraph_node (struct cgraph_node *node) -{ - struct cgraph_edge *e; - struct function *this_cfun = DECL_STRUCT_FUNCTION (node->symbol.decl); - basic_block this_block; - gimple_stmt_iterator gsi; - bool error_found = false; - - if (seen_error ()) - return; - - timevar_push (TV_CGRAPH_VERIFY); - error_found |= verify_symtab_base ((symtab_node) node); - for (e = node->callees; e; e = e->next_callee) - if (e->aux) - { - error ("aux field set for edge %s->%s", - identifier_to_locale (cgraph_node_name (e->caller)), - identifier_to_locale (cgraph_node_name (e->callee))); - error_found = true; - } - if (node->count < 0) - { - error ("execution count is negative"); - error_found = true; - } - if (node->global.inlined_to && node->symbol.externally_visible) - { - error ("externally visible inline clone"); - error_found = true; - } - if (node->global.inlined_to && node->symbol.address_taken) - { - error ("inline clone with address taken"); - error_found = true; - } - if (node->global.inlined_to && node->symbol.force_output) - { - error ("inline clone is forced to output"); - error_found = true; - } - for (e = node->indirect_calls; e; e = e->next_callee) - { - if (e->aux) - { - error ("aux field set for indirect edge from %s", - identifier_to_locale (cgraph_node_name (e->caller))); - error_found = true; - } - if (!e->indirect_unknown_callee - || !e->indirect_info) - { - error ("An indirect edge from %s is not marked as indirect or has " - "associated indirect_info, the corresponding statement is: ", - identifier_to_locale (cgraph_node_name (e->caller))); - cgraph_debug_gimple_stmt (this_cfun, e->call_stmt); - error_found = true; - } - } - for (e = node->callers; e; e = e->next_caller) - { - if (verify_edge_count_and_frequency (e)) - error_found = true; - if (!e->inline_failed) - { - if (node->global.inlined_to - != (e->caller->global.inlined_to - ? e->caller->global.inlined_to : e->caller)) - { - error ("inlined_to pointer is wrong"); - error_found = true; - } - if (node->callers->next_caller) - { - error ("multiple inline callers"); - error_found = true; - } - } - else - if (node->global.inlined_to) - { - error ("inlined_to pointer set for noninline callers"); - error_found = true; - } - } - for (e = node->indirect_calls; e; e = e->next_callee) - if (verify_edge_count_and_frequency (e)) - error_found = true; - if (!node->callers && node->global.inlined_to) - { - error ("inlined_to pointer is set but no predecessors found"); - error_found = true; - } - if (node->global.inlined_to == node) - { - error ("inlined_to pointer refers to itself"); - error_found = true; - } - - if (node->clone_of) - { - struct cgraph_node *n; - for (n = node->clone_of->clones; n; n = n->next_sibling_clone) - if (n == node) - break; - if (!n) - { - error ("node has wrong clone_of"); - error_found = true; - } - } - if (node->clones) - { - struct cgraph_node *n; - for (n = node->clones; n; n = n->next_sibling_clone) - if (n->clone_of != node) - break; - if (n) - { - error ("node has wrong clone list"); - error_found = true; - } - } - if ((node->prev_sibling_clone || node->next_sibling_clone) && !node->clone_of) - { - error ("node is in clone list but it is not clone"); - error_found = true; - } - if (!node->prev_sibling_clone && node->clone_of && node->clone_of->clones != node) - { - error ("node has wrong prev_clone pointer"); - error_found = true; - } - if (node->prev_sibling_clone && node->prev_sibling_clone->next_sibling_clone != node) - { - error ("double linked list of clones corrupted"); - error_found = true; - } - - if (node->analyzed && node->alias) - { - bool ref_found = false; - int i; - struct ipa_ref *ref; - - if (node->callees) - { - error ("Alias has call edges"); - error_found = true; - } - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, - i, ref); i++) - if (ref->use != IPA_REF_ALIAS) - { - error ("Alias has non-alias reference"); - error_found = true; - } - else if (ref_found) - { - error ("Alias has more than one alias reference"); - error_found = true; - } - else - ref_found = true; - if (!ref_found) - { - error ("Analyzed alias has no reference"); - error_found = true; - } - } - if (node->analyzed && node->thunk.thunk_p) - { - if (!node->callees) - { - error ("No edge out of thunk node"); - error_found = true; - } - else if (node->callees->next_callee) - { - error ("More than one edge out of thunk node"); - error_found = true; - } - if (gimple_has_body_p (node->symbol.decl)) - { - error ("Thunk is not supposed to have body"); - error_found = true; - } - } - else if (node->analyzed && gimple_has_body_p (node->symbol.decl) - && !TREE_ASM_WRITTEN (node->symbol.decl) - && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to) - && !flag_wpa) - { - if (this_cfun->cfg) - { - /* The nodes we're interested in are never shared, so walk - the tree ignoring duplicates. */ - struct pointer_set_t *visited_nodes = pointer_set_create (); - /* Reach the trees by walking over the CFG, and note the - enclosing basic-blocks in the call edges. */ - FOR_EACH_BB_FN (this_block, this_cfun) - for (gsi = gsi_start_bb (this_block); - !gsi_end_p (gsi); - gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - if (is_gimple_call (stmt)) - { - struct cgraph_edge *e = cgraph_edge (node, stmt); - tree decl = gimple_call_fndecl (stmt); - if (e) - { - if (e->aux) - { - error ("shared call_stmt:"); - cgraph_debug_gimple_stmt (this_cfun, stmt); - error_found = true; - } - if (!e->indirect_unknown_callee) - { - if (verify_edge_corresponds_to_fndecl (e, decl)) - { - error ("edge points to wrong declaration:"); - debug_tree (e->callee->symbol.decl); - fprintf (stderr," Instead of:"); - debug_tree (decl); - error_found = true; - } - } - else if (decl) - { - error ("an indirect edge with unknown callee " - "corresponding to a call_stmt with " - "a known declaration:"); - error_found = true; - cgraph_debug_gimple_stmt (this_cfun, e->call_stmt); - } - e->aux = (void *)1; - } - else if (decl) - { - error ("missing callgraph edge for call stmt:"); - cgraph_debug_gimple_stmt (this_cfun, stmt); - error_found = true; - } - } - } - pointer_set_destroy (visited_nodes); - } - else - /* No CFG available?! */ - gcc_unreachable (); - - for (e = node->callees; e; e = e->next_callee) - { - if (!e->aux) - { - error ("edge %s->%s has no corresponding call_stmt", - identifier_to_locale (cgraph_node_name (e->caller)), - identifier_to_locale (cgraph_node_name (e->callee))); - cgraph_debug_gimple_stmt (this_cfun, e->call_stmt); - error_found = true; - } - e->aux = 0; - } - for (e = node->indirect_calls; e; e = e->next_callee) - { - if (!e->aux) - { - error ("an indirect edge from %s has no corresponding call_stmt", - identifier_to_locale (cgraph_node_name (e->caller))); - cgraph_debug_gimple_stmt (this_cfun, e->call_stmt); - error_found = true; - } - e->aux = 0; - } - } - if (error_found) - { - dump_cgraph_node (stderr, node); - internal_error ("verify_cgraph_node failed"); - } - timevar_pop (TV_CGRAPH_VERIFY); -} - -/* Verify whole cgraph structure. */ -DEBUG_FUNCTION void -verify_cgraph (void) -{ - struct cgraph_node *node; - - if (seen_error ()) - return; - - FOR_EACH_FUNCTION (node) - verify_cgraph_node (node); -} - /* Output all asm statements we have stored up to be output. */ static void @@ -900,11 +549,13 @@ cgraph_output_pending_asms (void) } /* Analyze the function scheduled to be output. */ -void +static void cgraph_analyze_function (struct cgraph_node *node) { tree save = current_function_decl; tree decl = node->symbol.decl; + location_t saved_loc = input_location; + input_location = DECL_SOURCE_LOCATION (decl); if (node->alias && node->thunk.alias) { @@ -917,6 +568,7 @@ cgraph_analyze_function (struct cgraph_node *node) { error ("function %q+D part of alias cycle", node->symbol.decl); node->alias = false; + input_location = saved_loc; return; } if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references)) @@ -1002,6 +654,7 @@ cgraph_analyze_function (struct cgraph_node *node) node->analyzed = true; current_function_decl = save; + input_location = saved_loc; } /* C++ frontend produce same body aliases all over the place, even before PCH @@ -1888,15 +1541,23 @@ assemble_thunks_and_aliases (struct cgraph_node *node) } } -/* Perform IPA transforms and all further optimizations and compilation - for FNDECL. */ +/* Expand function specified by NODE. */ static void -tree_rest_of_compilation (struct cgraph_node *node) +cgraph_expand_function (struct cgraph_node *node) { - tree fndecl = node->symbol.decl; + tree decl = node->symbol.decl; location_t saved_loc; + /* We ought to not compile any inline clones. */ + gcc_assert (!node->global.inlined_to); + + announce_function (decl); + node->process = 0; + gcc_assert (node->lowered); + + /* Generate RTL for the body of DECL. */ + timevar_push (TV_REST_OF_COMPILATION); gcc_assert (cgraph_global_info_ready); @@ -1905,10 +1566,10 @@ tree_rest_of_compilation (struct cgraph_node *node) bitmap_obstack_initialize (NULL); /* Initialize the RTL code for the function. */ - current_function_decl = fndecl; + current_function_decl = decl; saved_loc = input_location; - input_location = DECL_SOURCE_LOCATION (fndecl); - init_function_start (fndecl); + input_location = DECL_SOURCE_LOCATION (decl); + init_function_start (decl); gimple_register_cfg_hooks (); @@ -1936,9 +1597,9 @@ tree_rest_of_compilation (struct cgraph_node *node) /* If requested, warn about function definitions where the function will return a value (usually of some struct or union type) which itself will take up a lot of stack space. */ - if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl)) + if (warn_larger_than && !DECL_EXTERNAL (decl) && TREE_TYPE (decl)) { - tree ret_type = TREE_TYPE (TREE_TYPE (fndecl)); + tree ret_type = TREE_TYPE (TREE_TYPE (decl)); if (ret_type && TYPE_SIZE_UNIT (ret_type) && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST @@ -1950,53 +1611,34 @@ tree_rest_of_compilation (struct cgraph_node *node) if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes", - fndecl, size_as_int); + decl, size_as_int); else warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes", - fndecl, larger_than_size); + decl, larger_than_size); } } - gimple_set_body (fndecl, NULL); - if (DECL_STRUCT_FUNCTION (fndecl) == 0 - && !cgraph_get_node (fndecl)->origin) + gimple_set_body (decl, NULL); + if (DECL_STRUCT_FUNCTION (decl) == 0 + && !cgraph_get_node (decl)->origin) { /* Stop pointing to the local nodes about to be freed. But DECL_INITIAL must remain nonzero so we know this was an actual function definition. For a nested function, this is done in c_pop_function_context. If rest_of_compilation set this to 0, leave it 0. */ - if (DECL_INITIAL (fndecl) != 0) - DECL_INITIAL (fndecl) = error_mark_node; + if (DECL_INITIAL (decl) != 0) + DECL_INITIAL (decl) = error_mark_node; } input_location = saved_loc; ggc_collect (); timevar_pop (TV_REST_OF_COMPILATION); -} - -/* Expand function specified by NODE. */ - -static void -cgraph_expand_function (struct cgraph_node *node) -{ - tree decl = node->symbol.decl; - - /* We ought to not compile any inline clones. */ - gcc_assert (!node->global.inlined_to); - - announce_function (decl); - node->process = 0; - gcc_assert (node->lowered); - - /* Generate RTL for the body of DECL. */ - tree_rest_of_compilation (node); /* Make sure that BE didn't give up on compiling. */ gcc_assert (TREE_ASM_WRITTEN (decl)); current_function_decl = NULL; - gcc_assert (!cgraph_preserve_function_body_p (node)); /* It would make a lot more sense to output thunks before function body to get more forward and lest backwarding jumps. This is however would need solving problem @@ -2011,16 +1653,6 @@ cgraph_expand_function (struct cgraph_node *node) cgraph_node_remove_callees (node); } -/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */ - -bool -cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason) -{ - *reason = e->inline_failed; - return !e->inline_failed; -} - - /* Expand all functions that must be output. @@ -2166,20 +1798,6 @@ cgraph_output_in_order (void) free (nodes); } -/* Return true when function body of DECL still needs to be kept around - for later re-use. */ -bool -cgraph_preserve_function_body_p (struct cgraph_node *node) -{ - gcc_assert (cgraph_global_info_ready); - gcc_assert (!node->alias && !node->thunk.thunk_p); - - /* Look if there is any clone around. */ - if (node->clones) - return true; - return false; -} - static void ipa_passes (void) { @@ -2277,7 +1895,7 @@ output_weakrefs (void) : get_alias_symbol (vnode->symbol.decl)); } - +/* Initialize callgraph dump file. */ void init_cgraph (void) |