Commit 18c6ada9 by Jan Hubicka Committed by Jan Hubicka

cgraph.c: Add overall comment.

	* cgraph.c: Add overall comment.
	(cgraph_inline_hash): New global variable.
	(cgraph_create_node): Break out from ...
	(cgraph_node): ... here.
	(cgraph_edge): New function.
	(cgraph_create_edge): New CALL_EXPR argument; some sanity checking.
	(cgraph_remove_edge): Accept edge, intead of source and destination.
	(cgraph_redirect_edge_callee): New.
	(cgraph_remove_node): Update all new datastructures.
	(cgraph_record_call, cgraph_remove_call): Kill.
	(dump_cgraph_node): Break out from ... ; dump new datastructures.
	(dump_cgraph): ... here.
	(cgraph_function_possibly_inlined_p): Use new hashtable.
	(cgraph_clone_edge, cgraph_clone_node): New.
	* cgraph.h: Include hashtab.h
	(struct cgraph_global_info): Kill cloned_times, inline_once, will_be_output
	fields, add inlined_to pointer.
	(cgraph_node): Add pointer to next_clone.
	(cgraph_remove_edge, cgraph_create_edge): Update prototype.
	(cgraph_remove_call, cgraph_record_call): Kill.
	(cgraph_inline_hash): Declare.
	(dump_cgraph_node, cgraph_edge, cg4raph_clone_edge, cgraph_clone_node,
	cgraph_redirect_edge_callee): Declare.
	(cgraph_create_edges, cgraph_inline_p): Update prorotype.
	(cgraph_preserve_function_body_p, verify_cgraph, verify_cgraph_node,
	cgraph_mark_inline_edge, cgraph_clone_inlined_nodes): Declare.
	* cgraphunit.c: Add overall comment.
	(cgraph_optimize_function): Kill.
	(cgraph_assemble_pending_functions): Do not assemble inline clones.
	(cgraph_finalize_function): Update call of cgraph_remove_node
	(record_call_1): Record call sites.
	(cgraph_create_edges): Accept node instead of decl argument.
	(error_found): New static variable.
	(verify_cgraph_node_1, verify_cgraph_node, verify_cgraph): New functions.
	(cgraph_analyze_function): Update for new datastructures.
	(cgraph_finalize_compilation_unit): Plug memory leak.
	(cgraph_optimize_function): Kill.
	(cgraph_expand_function): Do not use cgraph_optimize_function.
	(INLINED_TIMES, SET_INLINED_TIMES, cgraph_inlined_into,
	cgraph_inlined_callees): Kill.
	(cgraph_remove_unreachable_nodes): Verify cgraph; update handling of
	clones.
	(estimate_growth): Simplify.
	(cgraph_clone_inlined_nodes): New function.
	(cgraph_mark_inline_edge): Re-implement.
	(cgraph_mark_inline): Likewise.
	(cgraph_check_inline_limits): Simplify.
	(cgraph_recursive_inlining_p): New.
	(update_callee_keys): Break out from ...
	(cgraph_decide_inlining_of_small_functions): ... here; simplify.
	(cgraph_decide_inlining, cgraph_decide_inlining_incrementally):
	Likewise.
	(cgraph_expand_all_functions):  Remove inline clones from the ordered
	list.
	(cgraph_preserve_function_body_p): New predicate.
	(cgraph_optimize): Verify cgraph.
	* function.h (struct function): Add fields saved_tree/saved_args.
	* timevar.def (TV_CGRAPH_VERIFY): Use verifier.
	* toplev.c (rest_of_compilation): Do not free cfun.
	* tree-inline.c: Include function.h
	(struct inline_data): Add saving_p field; replace decl/current_decl by
	node/current_node.
	(insert_decl_map): New function.
	(copy_body_r): Handle saving; update cgraph datastructure.
	(copy_body): Handle recursive inlining.
	(initialize_inlined_parameters): Likewise.
	(expand_call_inline): Propagate node attributes; update cgraph.
	(optimize_inline_calls): Verify that datastructure still match.
	(save_body): New function.
	* tree-inline.h (save_body): New.
	* tree-optimize.c (tree_rest_of_compilation): preserve function body; do inlining.
	* langhooks-def.c (LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): New.
	* langhooks.c (lang_hooks): Add update_decl_after_saving.

	* cp-lang. (LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): Define.
	* cp-tree.h (cp_update_decl_after_saving): Declare.
	* tree.c (cp_update_decl_after_saving): Define.

	* Make-lang.in (com.o): Add dependnecy on function.h
	* com.c: Include function.h
	(finish_function): Clear DECL_STRUCT_FUNCTION.

	* utils.c: Include function.h
	(end_subprog_body): Clear DECL_STRUCT_FUNCTION.

From-SVN: r80334
parent e8632777
2004-04-02 Jan Hubicka <jh@suse.cz>
* cgraph.c: Add overall comment.
(cgraph_inline_hash): New global variable.
(cgraph_create_node): Break out from ...
(cgraph_node): ... here.
(cgraph_edge): New function.
(cgraph_create_edge): New CALL_EXPR argument; some sanity checking.
(cgraph_remove_edge): Accept edge, intead of source and destination.
(cgraph_redirect_edge_callee): New.
(cgraph_remove_node): Update all new datastructures.
(cgraph_record_call, cgraph_remove_call): Kill.
(dump_cgraph_node): Break out from ... ; dump new datastructures.
(dump_cgraph): ... here.
(cgraph_function_possibly_inlined_p): Use new hashtable.
(cgraph_clone_edge, cgraph_clone_node): New.
* cgraph.h: Include hashtab.h
(struct cgraph_global_info): Kill cloned_times, inline_once, will_be_output
fields, add inlined_to pointer.
(cgraph_node): Add pointer to next_clone.
(cgraph_remove_edge, cgraph_create_edge): Update prototype.
(cgraph_remove_call, cgraph_record_call): Kill.
(cgraph_inline_hash): Declare.
(dump_cgraph_node, cgraph_edge, cg4raph_clone_edge, cgraph_clone_node,
cgraph_redirect_edge_callee): Declare.
(cgraph_create_edges, cgraph_inline_p): Update prorotype.
(cgraph_preserve_function_body_p, verify_cgraph, verify_cgraph_node,
cgraph_mark_inline_edge, cgraph_clone_inlined_nodes): Declare.
* cgraphunit.c: Add overall comment.
(cgraph_optimize_function): Kill.
(cgraph_assemble_pending_functions): Do not assemble inline clones.
(cgraph_finalize_function): Update call of cgraph_remove_node
(record_call_1): Record call sites.
(cgraph_create_edges): Accept node instead of decl argument.
(error_found): New static variable.
(verify_cgraph_node_1, verify_cgraph_node, verify_cgraph): New functions.
(cgraph_analyze_function): Update for new datastructures.
(cgraph_finalize_compilation_unit): Plug memory leak.
(cgraph_optimize_function): Kill.
(cgraph_expand_function): Do not use cgraph_optimize_function.
(INLINED_TIMES, SET_INLINED_TIMES, cgraph_inlined_into,
cgraph_inlined_callees): Kill.
(cgraph_remove_unreachable_nodes): Verify cgraph; update handling of
clones.
(estimate_growth): Simplify.
(cgraph_clone_inlined_nodes): New function.
(cgraph_mark_inline_edge): Re-implement.
(cgraph_mark_inline): Likewise.
(cgraph_check_inline_limits): Simplify.
(cgraph_recursive_inlining_p): New.
(update_callee_keys): Break out from ...
(cgraph_decide_inlining_of_small_functions): ... here; simplify.
(cgraph_decide_inlining, cgraph_decide_inlining_incrementally):
Likewise.
(cgraph_expand_all_functions): Remove inline clones from the ordered
list.
(cgraph_preserve_function_body_p): New predicate.
(cgraph_optimize): Verify cgraph.
* function.h (struct function): Add fields saved_tree/saved_args.
* timevar.def (TV_CGRAPH_VERIFY): Use verifier.
* toplev.c (rest_of_compilation): Do not free cfun.
* tree-inline.c: Include function.h
(struct inline_data): Add saving_p field; replace decl/current_decl by
node/current_node.
(insert_decl_map): New function.
(copy_body_r): Handle saving; update cgraph datastructure.
(copy_body): Handle recursive inlining.
(initialize_inlined_parameters): Likewise.
(expand_call_inline): Propagate node attributes; update cgraph.
(optimize_inline_calls): Verify that datastructure still match.
(save_body): New function.
* tree-inline.h (save_body): New.
* tree-optimize.c (tree_rest_of_compilation): preserve function body; do inlining.
* langhooks-def.c (LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): New.
* langhooks.c (lang_hooks): Add update_decl_after_saving.
2004-04-01 Serge Belyshev <1319@bot.ru> 2004-04-01 Serge Belyshev <1319@bot.ru>
PR target/14702 PR target/14702
......
...@@ -1510,7 +1510,7 @@ tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ ...@@ -1510,7 +1510,7 @@ tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h \ $(TREE_H) $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h \
$(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \ $(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
langhooks.h $(C_COMMON_H) tree-inline.h cgraph.h intl.h langhooks.h $(C_COMMON_H) tree-inline.h cgraph.h intl.h function.h
tree-optimize.o : tree-optimize.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ tree-optimize.o : tree-optimize.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) toplev.h langhooks.h cgraph.h $(TIMEVAR_H) function.h $(GGC_H) $(TREE_H) toplev.h langhooks.h cgraph.h $(TIMEVAR_H) function.h $(GGC_H)
......
2004-04-02 Jan Hubicka <jh@suse.cz>
* utils.c: Include function.h
(end_subprog_body): Clear DECL_STRUCT_FUNCTION.
2004-04-01 Arnaud Charlet <charlet@act-europe.fr> 2004-04-01 Arnaud Charlet <charlet@act-europe.fr>
PR ada/14150 PR ada/14150
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "debug.h" #include "debug.h"
#include "convert.h" #include "convert.h"
#include "target.h" #include "target.h"
#include "function.h"
#include "ada.h" #include "ada.h"
#include "types.h" #include "types.h"
...@@ -1920,7 +1921,15 @@ end_subprog_body (void) ...@@ -1920,7 +1921,15 @@ end_subprog_body (void)
/* If we're only annotating types, don't actually compile this /* If we're only annotating types, don't actually compile this
function. */ function. */
if (!type_annotate_only) if (!type_annotate_only)
rest_of_compilation (current_function_decl); {
rest_of_compilation (current_function_decl);
if (! DECL_DEFER_OUTPUT (current_function_decl))
{
free_after_compilation (cfun);
DECL_STRUCT_FUNCTION (current_function_decl) = 0;
}
cfun = 0;
}
if (function_nesting_depth > 1) if (function_nesting_depth > 1)
ggc_pop_context (); ggc_pop_context ();
......
...@@ -21,6 +21,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -21,6 +21,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_CGRAPH_H #ifndef GCC_CGRAPH_H
#define GCC_CGRAPH_H #define GCC_CGRAPH_H
#include "hashtab.h"
/* Information about the function collected locally. /* Information about the function collected locally.
Available after function is analyzed. */ Available after function is analyzed. */
...@@ -50,21 +51,13 @@ struct cgraph_local_info GTY(()) ...@@ -50,21 +51,13 @@ struct cgraph_local_info GTY(())
struct cgraph_global_info GTY(()) struct cgraph_global_info GTY(())
{ {
/* For inline clones this points to the function they will be inlined into. */
struct cgraph_node *inlined_to;
/* Estimated size of the function after inlining. */ /* Estimated size of the function after inlining. */
int insns; int insns;
/* Number of times given function will be cloned during output. */ /* Set iff the function has been inlined at least once. */
int cloned_times;
/* Set when the function will be inlined exactly once. */
bool inline_once;
/* Set to true for all reachable functions before inlining is decided.
Once we inline all calls to the function and the function is local,
it is set to false. */
bool will_be_output;
/* Set iff at least one of the caller edges has inline_call flag set. */
bool inlined; bool inlined;
}; };
...@@ -97,6 +90,8 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) ...@@ -97,6 +90,8 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
struct cgraph_node *next_nested; struct cgraph_node *next_nested;
/* Pointer to the next function in cgraph_nodes_queue. */ /* Pointer to the next function in cgraph_nodes_queue. */
struct cgraph_node *next_needed; struct cgraph_node *next_needed;
/* Pointer to the next clone. */
struct cgraph_node *next_clone;
PTR GTY ((skip)) aux; PTR GTY ((skip)) aux;
struct cgraph_local_info local; struct cgraph_local_info local;
...@@ -117,12 +112,14 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) ...@@ -117,12 +112,14 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
bool output; bool output;
}; };
struct cgraph_edge GTY(()) struct cgraph_edge GTY((chain_next ("%h.next_caller")))
{ {
struct cgraph_node *caller; struct cgraph_node *caller;
struct cgraph_node *callee; struct cgraph_node *callee;
struct cgraph_edge *next_caller; struct cgraph_edge *next_caller;
struct cgraph_edge *next_callee; struct cgraph_edge *next_callee;
tree call_expr;
PTR GTY ((skip (""))) aux;
/* When NULL, inline this call. When non-NULL, points to the explanation /* When NULL, inline this call. When non-NULL, points to the explanation
why function was not inlined. */ why function was not inlined. */
const char *inline_failed; const char *inline_failed;
...@@ -155,27 +152,34 @@ extern FILE *cgraph_dump_file; ...@@ -155,27 +152,34 @@ extern FILE *cgraph_dump_file;
extern GTY(()) int cgraph_varpool_n_nodes; extern GTY(()) int cgraph_varpool_n_nodes;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue; extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
extern GTY((param_is (union tree_node))) htab_t cgraph_inline_hash;
/* In cgraph.c */ /* In cgraph.c */
void dump_cgraph (FILE *); void dump_cgraph (FILE *);
void cgraph_remove_edge (struct cgraph_node *, struct cgraph_node *); void dump_cgraph_node (FILE *, struct cgraph_node *);
void cgraph_remove_call (tree, tree); void cgraph_remove_edge (struct cgraph_edge *);
void cgraph_remove_node (struct cgraph_node *); void cgraph_remove_node (struct cgraph_node *);
struct cgraph_edge *cgraph_record_call (tree, tree); struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *,
tree);
struct cgraph_node *cgraph_node (tree decl); struct cgraph_node *cgraph_node (tree decl);
struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree call_expr);
struct cgraph_node *cgraph_node_for_identifier (tree id); struct cgraph_node *cgraph_node_for_identifier (tree id);
bool cgraph_calls_p (tree, tree); bool cgraph_calls_p (tree, tree);
struct cgraph_local_info *cgraph_local_info (tree); struct cgraph_local_info *cgraph_local_info (tree);
struct cgraph_global_info *cgraph_global_info (tree); struct cgraph_global_info *cgraph_global_info (tree);
struct cgraph_rtl_info *cgraph_rtl_info (tree); struct cgraph_rtl_info *cgraph_rtl_info (tree);
const char * cgraph_node_name (struct cgraph_node *); const char * cgraph_node_name (struct cgraph_node *);
struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node *, tree);
struct cgraph_node * cgraph_clone_node (struct cgraph_node *);
struct cgraph_varpool_node *cgraph_varpool_node (tree decl); struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
struct cgraph_varpool_node *cgraph_varpool_node_for_identifier (tree id); struct cgraph_varpool_node *cgraph_varpool_node_for_identifier (tree id);
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *); void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
void cgraph_varpool_finalize_decl (tree); void cgraph_varpool_finalize_decl (tree);
bool cgraph_varpool_assemble_pending_decls (void); bool cgraph_varpool_assemble_pending_decls (void);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
bool cgraph_function_possibly_inlined_p (tree); bool cgraph_function_possibly_inlined_p (tree);
...@@ -183,10 +187,15 @@ bool cgraph_function_possibly_inlined_p (tree); ...@@ -183,10 +187,15 @@ bool cgraph_function_possibly_inlined_p (tree);
bool cgraph_assemble_pending_functions (void); bool cgraph_assemble_pending_functions (void);
void cgraph_finalize_function (tree, bool); void cgraph_finalize_function (tree, bool);
void cgraph_finalize_compilation_unit (void); void cgraph_finalize_compilation_unit (void);
void cgraph_create_edges (tree, tree); void cgraph_create_edges (struct cgraph_node *, tree);
void cgraph_optimize (void); void cgraph_optimize (void);
void cgraph_mark_needed_node (struct cgraph_node *); void cgraph_mark_needed_node (struct cgraph_node *);
void cgraph_mark_reachable_node (struct cgraph_node *); void cgraph_mark_reachable_node (struct cgraph_node *);
bool cgraph_inline_p (tree, tree, const char **reason); bool cgraph_inline_p (struct cgraph_edge *, const char **reason);
bool cgraph_preserve_function_body_p (tree);
void verify_cgraph (void);
void verify_cgraph_node (struct cgraph_node *);
void cgraph_mark_inline_edge (struct cgraph_edge *e);
void cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate);
#endif /* GCC_CGRAPH_H */ #endif /* GCC_CGRAPH_H */
2004-04-02 Jan Hubicka <jh@suse.cz>
* cp-lang. (LANG_HOOKS_UPDATE_DECL_AFTER_SAVING): Define.
* cp-tree.h (cp_update_decl_after_saving): Declare.
* tree.c (cp_update_decl_after_saving): Define.
2004-04-01 Mark Mitchell <mark@codesourcery.com> 2004-04-01 Mark Mitchell <mark@codesourcery.com>
PR c++/14803 PR c++/14803
......
...@@ -112,6 +112,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *); ...@@ -112,6 +112,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing #define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
#undef LANG_HOOKS_DECL_UNINIT #undef LANG_HOOKS_DECL_UNINIT
#define LANG_HOOKS_DECL_UNINIT c_decl_uninit #define LANG_HOOKS_DECL_UNINIT c_decl_uninit
#undef LANG_HOOKS_UPDATE_DECL_AFTER_SAVING
#define LANG_HOOKS_UPDATE_DECL_AFTER_SAVING cp_update_decl_after_saving
#undef LANG_HOOKS_FUNCTION_INIT #undef LANG_HOOKS_FUNCTION_INIT
......
...@@ -4161,6 +4161,7 @@ extern int cp_is_overload_p (tree); ...@@ -4161,6 +4161,7 @@ extern int cp_is_overload_p (tree);
extern int cp_auto_var_in_fn_p (tree,tree); extern int cp_auto_var_in_fn_p (tree,tree);
extern tree cp_copy_res_decl_for_inlining (tree, tree, tree, void*, extern tree cp_copy_res_decl_for_inlining (tree, tree, tree, void*,
int*, tree); int*, tree);
extern void cp_update_decl_after_saving (tree, void *);
/* in typeck.c */ /* in typeck.c */
extern int string_conv_p (tree, tree, int); extern int string_conv_p (tree, tree, int);
......
...@@ -2206,6 +2206,20 @@ cp_copy_res_decl_for_inlining (tree result, ...@@ -2206,6 +2206,20 @@ cp_copy_res_decl_for_inlining (tree result,
return var; return var;
} }
/* FN body has been duplicated. Update language specific fields. */
void
cp_update_decl_after_saving (tree fn,
void* decl_map_)
{
splay_tree decl_map = (splay_tree)decl_map_;
tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
if (nrv)
{
DECL_SAVED_FUNCTION_DATA (fn)->x_return_value
= (tree) splay_tree_lookup (decl_map, (splay_tree_key) nrv)->value;
}
}
/* Initialize tree.c. */ /* Initialize tree.c. */
void void
......
2004-04-02 Jan Hubicka <jh@suse.cz>
* Make-lang.in (com.o): Add dependnecy on function.h
* com.c: Include function.h
(finish_function): Clear DECL_STRUCT_FUNCTION.
2004-04-01 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> 2004-04-01 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* com.c (ffe_truthvalue_conversion, case COMPONENT_REF): * com.c (ffe_truthvalue_conversion, case COMPONENT_REF):
......
...@@ -374,7 +374,7 @@ f/com.o: f/com.c f/proj.h $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \ ...@@ -374,7 +374,7 @@ f/com.o: f/com.c f/proj.h $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \
f/intrin.def f/lab.h f/symbol.h f/symbol.def f/equiv.h f/storag.h f/global.h \ f/intrin.def f/lab.h f/symbol.h f/symbol.def f/equiv.h f/storag.h f/global.h \
f/name.h f/expr.h f/implic.h f/src.h f/st.h $(GGC_H) toplev.h diagnostic.h \ f/name.h f/expr.h f/implic.h f/src.h f/st.h $(GGC_H) toplev.h diagnostic.h \
$(LANGHOOKS_DEF) langhooks.h intl.h real.h debug.h gt-f-com.h gtype-f.h \ $(LANGHOOKS_DEF) langhooks.h intl.h real.h debug.h gt-f-com.h gtype-f.h \
coretypes.h $(TM_H) coretypes.h $(TM_H) function.h
f/data.o: f/data.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/data.h f/bld.h f/bld-op.def \ f/data.o: f/data.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/data.h f/bld.h f/bld-op.def \
f/bit.h f/malloc.h f/com.h f/com-rt.def $(TREE_H) f/info.h f/info-b.def \ f/bit.h f/malloc.h f/com.h f/com-rt.def $(TREE_H) f/info.h f/info-b.def \
f/info-k.def f/info-w.def f/target.h f/bad.h f/bad.def f/where.h glimits.h \ f/info-k.def f/info-w.def f/target.h f/bad.h f/bad.def f/where.h glimits.h \
......
...@@ -136,6 +136,7 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t; ...@@ -136,6 +136,7 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t;
#include "target.h" #include "target.h"
#include "top.h" #include "top.h"
#include "type.h" #include "type.h"
#include "function.h"
/* Externals defined here. */ /* Externals defined here. */
...@@ -13591,6 +13592,12 @@ finish_function (int nested) ...@@ -13591,6 +13592,12 @@ finish_function (int nested)
/* Run the optimizers and output the assembler code for this function. */ /* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl); rest_of_compilation (fndecl);
if (! DECL_DEFER_OUTPUT (fndecl))
{
free_after_compilation (cfun);
DECL_STRUCT_FUNCTION (fndecl) = 0;
}
cfun = 0;
/* Undo the GC context switch. */ /* Undo the GC context switch. */
if (nested) if (nested)
......
...@@ -181,6 +181,13 @@ struct function GTY(()) ...@@ -181,6 +181,13 @@ struct function GTY(())
struct emit_status *emit; struct emit_status *emit;
struct varasm_status *varasm; struct varasm_status *varasm;
/* For tree-optimize.c. */
/* Saved tree and arguments during tree optimization. Used later for
inlining */
tree saved_tree;
tree saved_args;
/* For function.c. */ /* For function.c. */
/* Points to the FUNCTION_DECL of this function. */ /* Points to the FUNCTION_DECL of this function. */
......
...@@ -124,6 +124,7 @@ extern tree lhd_callgraph_analyze_expr (tree *, int *, tree); ...@@ -124,6 +124,7 @@ extern tree lhd_callgraph_analyze_expr (tree *, int *, tree);
#define LANG_HOOKS_EXPR_SIZE lhd_expr_size #define LANG_HOOKS_EXPR_SIZE lhd_expr_size
#define LANG_HOOKS_DECL_UNINIT lhd_decl_uninit #define LANG_HOOKS_DECL_UNINIT lhd_decl_uninit
#define LANG_HOOKS_TREE_SIZE lhd_tree_size #define LANG_HOOKS_TREE_SIZE lhd_tree_size
#define LANG_HOOKS_UPDATE_DECL_AFTER_SAVING NULL
#define LANG_HOOKS_FUNCTION_INIT lhd_do_nothing_f #define LANG_HOOKS_FUNCTION_INIT lhd_do_nothing_f
#define LANG_HOOKS_FUNCTION_FINAL lhd_do_nothing_f #define LANG_HOOKS_FUNCTION_FINAL lhd_do_nothing_f
...@@ -304,6 +305,7 @@ extern tree lhd_make_node (enum tree_code); ...@@ -304,6 +305,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_PRINT_ERROR_FUNCTION, \ LANG_HOOKS_PRINT_ERROR_FUNCTION, \
LANG_HOOKS_EXPR_SIZE, \ LANG_HOOKS_EXPR_SIZE, \
LANG_HOOKS_DECL_UNINIT, \ LANG_HOOKS_DECL_UNINIT, \
LANG_HOOKS_UPDATE_DECL_AFTER_SAVING, \
LANG_HOOKS_ATTRIBUTE_TABLE, \ LANG_HOOKS_ATTRIBUTE_TABLE, \
LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \ LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
......
...@@ -396,6 +396,9 @@ struct lang_hooks ...@@ -396,6 +396,9 @@ struct lang_hooks
uninitialized based on DECL_INITIAL. */ uninitialized based on DECL_INITIAL. */
bool (*decl_uninit) (tree); bool (*decl_uninit) (tree);
/* Update lang specific fields after duplicating function body. */
void (*update_decl_after_saving) (tree, void *);
/* Pointers to machine-independent attribute tables, for front ends /* Pointers to machine-independent attribute tables, for front ends
using attribs.c. If one is NULL, it is ignored. Respectively, a using attribs.c. If one is NULL, it is ignored. Respectively, a
table of attributes specific to the language, a table of table of attributes specific to the language, a table of
......
...@@ -2109,12 +2109,6 @@ rest_of_compilation (tree decl) ...@@ -2109,12 +2109,6 @@ rest_of_compilation (tree decl)
/* We're done with this function. Free up memory if we can. */ /* We're done with this function. Free up memory if we can. */
free_after_parsing (cfun); free_after_parsing (cfun);
if (! DECL_DEFER_OUTPUT (decl))
{
free_after_compilation (cfun);
DECL_STRUCT_FUNCTION (decl) = 0;
}
cfun = 0;
ggc_collect (); ggc_collect ();
......
...@@ -61,6 +61,7 @@ DEFTIMEVAR (TV_PARSE , "parser") ...@@ -61,6 +61,7 @@ DEFTIMEVAR (TV_PARSE , "parser")
DEFTIMEVAR (TV_NAME_LOOKUP , "name lookup") DEFTIMEVAR (TV_NAME_LOOKUP , "name lookup")
DEFTIMEVAR (TV_OVERLOAD , "overload resolution") DEFTIMEVAR (TV_OVERLOAD , "overload resolution")
DEFTIMEVAR (TV_TEMPLATE_INSTANTIATION, "template instantiation") DEFTIMEVAR (TV_TEMPLATE_INSTANTIATION, "template instantiation")
DEFTIMEVAR (TV_CGRAPH_VERIFY , "callgraph verifier")
DEFTIMEVAR (TV_EXPAND , "expand") DEFTIMEVAR (TV_EXPAND , "expand")
DEFTIMEVAR (TV_VARCONST , "varconst") DEFTIMEVAR (TV_VARCONST , "varconst")
DEFTIMEVAR (TV_INTEGRATION , "integration") DEFTIMEVAR (TV_INTEGRATION , "integration")
......
...@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */
#include "cgraph.h" #include "cgraph.h"
#include "intl.h" #include "intl.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "function.h"
/* This should be eventually be generalized to other languages, but /* This should be eventually be generalized to other languages, but
this would require a shared function-as-trees infrastructure. */ this would require a shared function-as-trees infrastructure. */
...@@ -100,12 +101,15 @@ typedef struct inline_data ...@@ -100,12 +101,15 @@ typedef struct inline_data
distinguish between those two situations. This flag is true if distinguish between those two situations. This flag is true if
we are cloning, rather than inlining. */ we are cloning, rather than inlining. */
bool cloning_p; bool cloning_p;
/* Similarly for saving function body. */
bool saving_p;
/* Hash table used to prevent walk_tree from visiting the same node /* Hash table used to prevent walk_tree from visiting the same node
umpteen million times. */ umpteen million times. */
htab_t tree_pruner; htab_t tree_pruner;
/* Decl of function we are inlining into. */ /* Callgraph node of function we are inlining into. */
tree decl; struct cgraph_node *node;
tree current_decl; /* Callgraph node of currently inlined function. */
struct cgraph_node *current_node;
} inline_data; } inline_data;
/* Prototypes. */ /* Prototypes. */
...@@ -537,9 +541,9 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) ...@@ -537,9 +541,9 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a /* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */ GOTO_STMT with the RET_LABEL as its target. */
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label) if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label && !id->saving_p)
#else /* INLINER_FOR_JAVA */ #else /* INLINER_FOR_JAVA */
if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label) if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label && !id->saving_p)
#endif /* INLINER_FOR_JAVA */ #endif /* INLINER_FOR_JAVA */
{ {
tree return_stmt = *tp; tree return_stmt = *tp;
...@@ -646,6 +650,8 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) ...@@ -646,6 +650,8 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
knows not to copy VAR_DECLs, etc., so this is safe. */ knows not to copy VAR_DECLs, etc., so this is safe. */
else else
{ {
tree old_node = *tp;
if (TREE_CODE (*tp) == MODIFY_EXPR if (TREE_CODE (*tp) == MODIFY_EXPR
&& TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1)
&& (lang_hooks.tree_inlining.auto_var_in_fn_p && (lang_hooks.tree_inlining.auto_var_in_fn_p
...@@ -693,6 +699,32 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) ...@@ -693,6 +699,32 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
copy_tree_r (tp, walk_subtrees, NULL); copy_tree_r (tp, walk_subtrees, NULL);
if (TREE_CODE (*tp) == CALL_EXPR && id->node && get_callee_fndecl (*tp))
{
if (id->saving_p)
{
struct cgraph_node *node;
struct cgraph_edge *edge;
for (node = id->node->next_clone; node; node = node->next_clone)
{
edge = cgraph_edge (node, old_node);
if (edge)
edge->call_expr = *tp;
else
abort ();
}
}
else if (!id->cloning_p)
{
struct cgraph_edge *edge;
edge = cgraph_edge (id->current_node, old_node);
if (edge)
cgraph_clone_edge (edge, id->node, *tp);
}
}
TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id); TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
/* The copied TARGET_EXPR has never been expanded, even if the /* The copied TARGET_EXPR has never been expanded, even if the
...@@ -715,8 +747,13 @@ static tree ...@@ -715,8 +747,13 @@ static tree
copy_body (inline_data *id) copy_body (inline_data *id)
{ {
tree body; tree body;
tree fndecl = VARRAY_TOP_TREE (id->fns);
body = DECL_SAVED_TREE (VARRAY_TOP_TREE (id->fns)); if (fndecl == current_function_decl
&& cfun->saved_tree)
body = cfun->saved_tree;
else
body = DECL_SAVED_TREE (fndecl);
walk_tree (&body, copy_body_r, id, NULL); walk_tree (&body, copy_body_r, id, NULL);
return body; return body;
...@@ -742,8 +779,9 @@ initialize_inlined_parameters (inline_data *id, tree args, tree fn, tree block) ...@@ -742,8 +779,9 @@ initialize_inlined_parameters (inline_data *id, tree args, tree fn, tree block)
int argnum = 0; int argnum = 0;
/* Figure out what the parameters are. */ /* Figure out what the parameters are. */
parms = parms = DECL_ARGUMENTS (fn);
DECL_ARGUMENTS (fn); if (fn == current_function_decl && cfun->saved_args)
parms = cfun->saved_args;
/* Start with no initializations whatsoever. */ /* Start with no initializations whatsoever. */
init_stmts = NULL_TREE; init_stmts = NULL_TREE;
...@@ -1254,6 +1292,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) ...@@ -1254,6 +1292,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
splay_tree st; splay_tree st;
tree args; tree args;
tree return_slot_addr; tree return_slot_addr;
struct cgraph_edge *edge;
const char *reason; const char *reason;
/* See what we've got. */ /* See what we've got. */
...@@ -1333,9 +1372,30 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) ...@@ -1333,9 +1372,30 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
&& DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn))) && DECL_SAVED_TREE (DECL_ABSTRACT_ORIGIN (fn)))
fn = DECL_ABSTRACT_ORIGIN (fn); fn = DECL_ABSTRACT_ORIGIN (fn);
/* Objective C and fortran still calls tree_rest_of_compilation directly.
Kill this check once this is fixed. */
if (!id->current_node->analyzed)
return NULL_TREE;
edge = cgraph_edge (id->current_node, t);
/* Constant propagation on argument done during previous inlining
may create new direct call. Produce an edge for it. */
if (!edge)
{
struct cgraph_node *dest = cgraph_node (fn);
/* FN must have address taken so it can be passed as argument. */
if (!dest->needed)
abort ();
cgraph_create_edge (id->node, dest, t)->inline_failed
= N_("originally indirect function call not considered for inlining");
return NULL_TREE;
}
/* Don't try to inline functions that are not well-suited to /* Don't try to inline functions that are not well-suited to
inlining. */ inlining. */
if (!cgraph_inline_p (id->current_decl, fn, &reason)) if (!cgraph_inline_p (edge, &reason))
{ {
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))) if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
{ {
...@@ -1352,6 +1412,11 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) ...@@ -1352,6 +1412,11 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE; return NULL_TREE;
} }
#ifdef ENABLE_CHECKING
if (edge->callee->decl != id->node->decl)
verify_cgraph_node (edge->callee);
#endif
if (! lang_hooks.tree_inlining.start_inlining (fn)) if (! lang_hooks.tree_inlining.start_inlining (fn))
return NULL_TREE; return NULL_TREE;
...@@ -1487,23 +1552,29 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) ...@@ -1487,23 +1552,29 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
/* After we've initialized the parameters, we insert the body of the /* After we've initialized the parameters, we insert the body of the
function itself. */ function itself. */
{
struct cgraph_node *old_node = id->current_node;
id->current_node = edge->callee;
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
inlined_body = &COMPOUND_BODY (stmt); inlined_body = &COMPOUND_BODY (stmt);
while (*inlined_body) while (*inlined_body)
inlined_body = &TREE_CHAIN (*inlined_body); inlined_body = &TREE_CHAIN (*inlined_body);
*inlined_body = copy_body (id); *inlined_body = copy_body (id);
#else /* INLINER_FOR_JAVA */ #else /* INLINER_FOR_JAVA */
{ {
tree new_body; tree new_body;
java_inlining_map_static_initializers (fn, id->decl_map); java_inlining_map_static_initializers (fn, id->decl_map);
new_body = copy_body (id); new_body = copy_body (id);
TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn)); TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
BLOCK_EXPR_BODY (expr) BLOCK_EXPR_BODY (expr)
= add_stmt_to_compound (BLOCK_EXPR_BODY (expr), = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
TREE_TYPE (new_body), new_body); TREE_TYPE (new_body), new_body);
inlined_body = &BLOCK_EXPR_BODY (expr); inlined_body = &BLOCK_EXPR_BODY (expr);
} }
#endif /* INLINER_FOR_JAVA */ #endif /* INLINER_FOR_JAVA */
id->current_node = old_node;
}
/* After the body of the function comes the RET_LABEL. This must come /* After the body of the function comes the RET_LABEL. This must come
before we evaluate the returned value below, because that evaluation before we evaluate the returned value below, because that evaluation
...@@ -1574,19 +1645,10 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) ...@@ -1574,19 +1645,10 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
TREE_USED (*tp) = 1; TREE_USED (*tp) = 1;
/* Update callgraph if needed. */ /* Update callgraph if needed. */
if (id->decl) cgraph_remove_node (edge->callee);
{
cgraph_remove_call (id->decl, fn);
cgraph_create_edges (id->decl, *inlined_body);
}
/* Recurse into the body of the just inlined function. */ /* Recurse into the body of the just inlined function. */
{ expand_calls_inline (inlined_body, id);
tree old_decl = id->current_decl;
id->current_decl = fn;
expand_calls_inline (inlined_body, id);
id->current_decl = old_decl;
}
VARRAY_POP (id->fns); VARRAY_POP (id->fns);
/* Don't walk into subtrees. We've already handled them above. */ /* Don't walk into subtrees. We've already handled them above. */
...@@ -1629,8 +1691,7 @@ optimize_inline_calls (tree fn) ...@@ -1629,8 +1691,7 @@ optimize_inline_calls (tree fn)
/* Clear out ID. */ /* Clear out ID. */
memset (&id, 0, sizeof (id)); memset (&id, 0, sizeof (id));
id.decl = fn; id.current_node = id.node = cgraph_node (fn);
id.current_decl = fn;
/* Don't allow recursion into FN. */ /* Don't allow recursion into FN. */
VARRAY_TREE_INIT (id.fns, 32, "fns"); VARRAY_TREE_INIT (id.fns, 32, "fns");
VARRAY_PUSH_TREE (id.fns, fn); VARRAY_PUSH_TREE (id.fns, fn);
...@@ -1669,6 +1730,18 @@ optimize_inline_calls (tree fn) ...@@ -1669,6 +1730,18 @@ optimize_inline_calls (tree fn)
VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree)); VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
DECL_INLINED_FNS (fn) = ifn; DECL_INLINED_FNS (fn) = ifn;
} }
#ifdef ENABLE_CHECKING
{
struct cgraph_edge *e;
verify_cgraph_node (id.node);
/* Double check that we inlined everything we are supposed to inline. */
for (e = id.node->callees; e; e = e->next_callee)
if (!e->inline_failed)
abort ();
}
#endif
} }
/* FN is a function that has a complete body, and CLONE is a function /* FN is a function that has a complete body, and CLONE is a function
...@@ -1698,6 +1771,42 @@ clone_body (tree clone, tree fn, void *arg_map) ...@@ -1698,6 +1771,42 @@ clone_body (tree clone, tree fn, void *arg_map)
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id); TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
} }
/* Save duplicate of body in FN. MAP is used to pass around splay tree
used to update arguments in restore_body. */
tree
save_body (tree fn, tree *arg_copy)
{
inline_data id;
tree body, *parg;
memset (&id, 0, sizeof (id));
VARRAY_TREE_INIT (id.fns, 1, "fns");
VARRAY_PUSH_TREE (id.fns, fn);
id.node = cgraph_node (fn);
id.saving_p = true;
id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
*arg_copy = DECL_ARGUMENTS (fn);
for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
{
tree new = copy_node (*parg);
(*lang_hooks.dup_lang_specific_decl) (new);
DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*parg);
insert_decl_map (&id, *parg, new);
TREE_CHAIN (new) = TREE_CHAIN (*parg);
*parg = new;
}
insert_decl_map (&id, DECL_RESULT (fn), DECL_RESULT (fn));
/* Actually copy the body. */
body = copy_body (&id);
if (lang_hooks.update_decl_after_saving)
lang_hooks.update_decl_after_saving (fn, id.decl_map);
/* Clean up. */
splay_tree_delete (id.decl_map);
return body;
}
/* Apply FUNC to all the sub-trees of TP in a pre-order traversal. /* Apply FUNC to all the sub-trees of TP in a pre-order traversal.
FUNC is called with the DATA and the address of each sub-tree. If FUNC is called with the DATA and the address of each sub-tree. If
FUNC returns a non-NULL value, the traversal is aborted, and the FUNC returns a non-NULL value, the traversal is aborted, and the
......
...@@ -30,6 +30,7 @@ tree walk_tree (tree*, walk_tree_fn, void*, void*); ...@@ -30,6 +30,7 @@ tree walk_tree (tree*, walk_tree_fn, void*, void*);
tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*); tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
tree copy_tree_r (tree*, int*, void*); tree copy_tree_r (tree*, int*, void*);
void clone_body (tree, tree, void*); void clone_body (tree, tree, void*);
tree save_body (tree, tree *);
void remap_save_expr (tree*, void*, tree, int*); void remap_save_expr (tree*, void*, tree, int*);
/* 0 if we should not perform inlining. /* 0 if we should not perform inlining.
......
...@@ -96,6 +96,7 @@ void ...@@ -96,6 +96,7 @@ void
tree_rest_of_compilation (tree fndecl, bool nested_p) tree_rest_of_compilation (tree fndecl, bool nested_p)
{ {
location_t saved_loc; location_t saved_loc;
struct cgraph_node *node, *saved_node = NULL;
timevar_push (TV_EXPAND); timevar_push (TV_EXPAND);
...@@ -118,6 +119,39 @@ tree_rest_of_compilation (tree fndecl, bool nested_p) ...@@ -118,6 +119,39 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
immediate_size_expand = 0; immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1; cfun->x_dont_save_pending_sizes_p = 1;
node = cgraph_node (fndecl);
/* We might need the body of this function so that we can expand
it inline somewhere else. This means not lowering some constructs
such as exception handling. */
if (cgraph_preserve_function_body_p (fndecl))
{
if (!flag_unit_at_a_time)
{
struct cgraph_edge *e;
saved_node = cgraph_clone_node (node);
for (e = saved_node->callees; e; e = e->next_callee)
if (!e->inline_failed)
cgraph_clone_inlined_nodes (e, true);
}
cfun->saved_tree = save_body (fndecl, &cfun->saved_args);
}
if (flag_inline_trees)
{
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
if (!e->inline_failed || warn_inline)
break;
if (e)
{
timevar_push (TV_INTEGRATION);
optimize_inline_calls (fndecl);
timevar_pop (TV_INTEGRATION);
}
}
/* If the function has a variably modified type, there may be /* If the function has a variably modified type, there may be
SAVE_EXPRs in the parameter types. Their context must be set to SAVE_EXPRs in the parameter types. Their context must be set to
refer to this function; they cannot be expanded in the containing refer to this function; they cannot be expanded in the containing
...@@ -167,6 +201,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p) ...@@ -167,6 +201,7 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
/* Run the optimizers and output the assembler code for this function. */ /* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl); rest_of_compilation (fndecl);
/* Undo the GC context switch. */ /* Undo the GC context switch. */
if (nested_p) if (nested_p)
ggc_pop_context (); ggc_pop_context ();
...@@ -205,11 +240,31 @@ tree_rest_of_compilation (tree fndecl, bool nested_p) ...@@ -205,11 +240,31 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
clear_decl_rtl, clear_decl_rtl,
fndecl); fndecl);
if (!cgraph_function_possibly_inlined_p (fndecl)) /* Restore original body if still needed. */
if (cfun->saved_tree)
{
DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
DECL_ARGUMENTS (fndecl) = cfun->saved_args;
/* When not in unit-at-a-time mode, we must preserve out of line copy
representing node before inlining. Restore original outgoing edges
using clone we created earlier. */
if (!flag_unit_at_a_time)
{
struct cgraph_edge *e;
while (node->callees)
cgraph_remove_edge (node->callees);
node->callees = saved_node->callees;
saved_node->callees = NULL;
for (e = saved_node->callees; e; e = e->next_callee)
e->caller = node;
cgraph_remove_node (saved_node);
}
}
else
{ {
DECL_SAVED_TREE (fndecl) = NULL; DECL_SAVED_TREE (fndecl) = NULL;
if (DECL_STRUCT_FUNCTION (fndecl) == 0 if (cgraph_node (fndecl)->origin)
&& !cgraph_node (fndecl)->origin)
{ {
/* Stop pointing to the local nodes about to be freed. /* Stop pointing to the local nodes about to be freed.
But DECL_INITIAL must remain nonzero so we know this But DECL_INITIAL must remain nonzero so we know this
...@@ -220,6 +275,9 @@ tree_rest_of_compilation (tree fndecl, bool nested_p) ...@@ -220,6 +275,9 @@ tree_rest_of_compilation (tree fndecl, bool nested_p)
DECL_INITIAL (fndecl) = error_mark_node; DECL_INITIAL (fndecl) = error_mark_node;
} }
} }
free_after_compilation (cfun);
cfun = 0;
DECL_STRUCT_FUNCTION (fndecl) = 0;
input_location = saved_loc; input_location = saved_loc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment