From b48610900e267a7335dd1315e32733d8ef4092dc Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 21 Apr 2005 15:18:23 +0200 Subject: [PATCH] cgraphunit.c: Include tree-pass.h (cgraph_decide_recursive_inlining... * cgraphunit.c: Include tree-pass.h (cgraph_decide_recursive_inlining, cgraph_decide_inlining_of_small_function, cgraph_set_inline_failed, cgraph_decide_inlining): Dump goes to dump_file. (cgraph_optimize): Call ipa passes instead of inliner. (cgraph_gate_inlining, pass_ipa_inline): New. * tree-optimize.c (all_ipa_passes): New static variable. (register_one_dump_file): Dead with IPA passes. (register_dump_files): Likewise. (init_tree_optimization_passes): Initialize IPA passes. (execute_todo): Do cgraph dump when asked to, do not dump function body for IPA pass. * tree-pass.h (TODO_dump_cgraph): New macro. (ipa_passes): Declare. * Makefile.in (cgraphunit.o): Add dependency on cgraphunit.h From-SVN: r98501 --- gcc/ChangeLog | 18 ++++++++ gcc/Makefile.in | 2 +- gcc/cgraphunit.c | 101 +++++++++++++++++++++++++++----------------- gcc/tree-optimize.c | 68 +++++++++++++++++++++-------- gcc/tree-pass.h | 5 +++ 5 files changed, 136 insertions(+), 58 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab071b83cb9..fa41617d598 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2005-04-21 Jan Hubicka + + * cgraphunit.c: Include tree-pass.h + (cgraph_decide_recursive_inlining, + cgraph_decide_inlining_of_small_function, cgraph_set_inline_failed, + cgraph_decide_inlining): Dump goes to dump_file. + (cgraph_optimize): Call ipa passes instead of inliner. + (cgraph_gate_inlining, pass_ipa_inline): New. + * tree-optimize.c (all_ipa_passes): New static variable. + (register_one_dump_file): Dead with IPA passes. + (register_dump_files): Likewise. + (init_tree_optimization_passes): Initialize IPA passes. + (execute_todo): Do cgraph dump when asked to, do not dump function body + for IPA pass. + * tree-pass.h (TODO_dump_cgraph): New macro. + (ipa_passes): Declare. + * Makefile.in (cgraphunit.o): Add dependency on cgraphunit.h + 2005-04-21 Nathan Sidwell * config/i386/i386.c (type_natural_mode): Use gcc_unreachable and diff --git a/gcc/Makefile.in b/gcc/Makefile.in index d55603b2e91..e578a6d8b41 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1975,7 +1975,7 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ output.h intl.h cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ langhooks.h tree-inline.h toplev.h $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) intl.h \ - pointer-set.h function.h $(TREE_GIMPLE_H) $(TREE_FLOW_H) + pointer-set.h function.h $(TREE_GIMPLE_H) $(TREE_FLOW_H) tree-pass.h coverage.o : coverage.c gcov-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \ toplev.h $(GGC_H) $(TARGET_H) langhooks.h $(COVERAGE_H) libfuncs.h \ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 9b16e929978..bcb97194723 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -189,6 +189,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "intl.h" #include "function.h" #include "tree-gimple.h" +#include "tree-pass.h" #include "output.h" static void cgraph_expand_all_functions (void); @@ -1400,8 +1401,8 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node) if (!first_call) return; - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nPerforming recursive inlining on %s\n", cgraph_node_name (node)); @@ -1439,8 +1440,8 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node) first_call->aux = NULL; first_call = next; } - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\n Inlined %i times, body grown from %i to %i insns\n", n, master_clone->global.insns, node->global.insns); @@ -1461,8 +1462,8 @@ cgraph_set_inline_failed (struct cgraph_node *node, const char *reason) { struct cgraph_edge *e; - if (cgraph_dump_file) - fprintf (cgraph_dump_file, "Inlining failed: %s\n", reason); + if (dump_file) + fprintf (dump_file, "Inlining failed: %s\n", reason); for (e = node->callers; e; e = e->next_caller) if (e->inline_failed) e->inline_failed = reason; @@ -1503,16 +1504,16 @@ cgraph_decide_inlining_of_small_functions (void) fibheap_insert (heap, cgraph_estimate_growth (node), node); } - if (cgraph_dump_file) - fprintf (cgraph_dump_file, "\nDeciding on smaller functions:\n"); + if (dump_file) + fprintf (dump_file, "\nDeciding on smaller functions:\n"); while (overall_insns <= max_insns && (node = fibheap_extract_min (heap))) { struct cgraph_edge *e, *next; int old_insns = overall_insns; heap_node[node->uid] = NULL; - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nConsidering %s with %i insns\n" " Estimated growth is %+i insns.\n", cgraph_node_name (node), node->global.insns, @@ -1535,8 +1536,8 @@ cgraph_decide_inlining_of_small_functions (void) || !cgraph_check_inline_limits (e->caller, e->callee, &e->inline_failed)) { - if (cgraph_dump_file) - fprintf (cgraph_dump_file, " Not inlining into %s:%s.\n", + if (dump_file) + fprintf (dump_file, " Not inlining into %s:%s.\n", cgraph_node_name (e->caller), e->inline_failed); continue; } @@ -1549,8 +1550,8 @@ cgraph_decide_inlining_of_small_functions (void) fibheap_replace_key (heap, heap_node[where->uid], cgraph_estimate_growth (where)); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inlined into %s which now has %i insns.\n", cgraph_node_name (e->caller), e->caller->global.insns); @@ -1563,8 +1564,8 @@ cgraph_decide_inlining_of_small_functions (void) are now called more times; update keys. */ update_callee_keys (heap, heap_node, node); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inlined for a net change of %+i insns.\n", overall_insns - old_insns); } @@ -1594,16 +1595,16 @@ cgraph_decide_inlining (void) nnodes = cgraph_postorder (order); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nDeciding on inlining. Starting with %i insns.\n", initial_insns); for (node = cgraph_nodes; node; node = node->next) node->aux = 0; - if (cgraph_dump_file) - fprintf (cgraph_dump_file, "\nInlining always_inline functions:\n"); + if (dump_file) + fprintf (dump_file, "\nInlining always_inline functions:\n"); /* In the first pass mark all always_inline edges. Do this with a priority so none of our later choices will make this impossible. */ @@ -1615,8 +1616,8 @@ cgraph_decide_inlining (void) if (!node->local.disregard_inline_limits) continue; - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nConsidering %s %i insns (always inline)\n", cgraph_node_name (node), node->global.insns); old_insns = overall_insns; @@ -1629,14 +1630,14 @@ cgraph_decide_inlining (void) &e->inline_failed)) continue; cgraph_mark_inline_edge (e); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inlined into %s which now has %i insns.\n", cgraph_node_name (e->caller), e->caller->global.insns); } - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inlined for a net change of %+i insns.\n", overall_insns - old_insns); } @@ -1645,8 +1646,8 @@ cgraph_decide_inlining (void) { cgraph_decide_inlining_of_small_functions (); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n"); + if (dump_file) + fprintf (dump_file, "\nDeciding on functions called once:\n"); /* And finally decide what functions are called once. */ @@ -1669,8 +1670,8 @@ cgraph_decide_inlining (void) ok = false; if (ok) { - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nConsidering %s %i insns.\n" " Called once from %s %i insns.\n", cgraph_node_name (node), node->global.insns, @@ -1683,8 +1684,8 @@ cgraph_decide_inlining (void) NULL)) { cgraph_mark_inline (node->callers); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inlined into %s which now has %i insns" " for a net change of %+i insns.\n", cgraph_node_name (node->callers->caller), @@ -1693,8 +1694,8 @@ cgraph_decide_inlining (void) } else { - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, " Inline limit reached, not inlined.\n"); } } @@ -1707,8 +1708,8 @@ cgraph_decide_inlining (void) inline functions. */ cgraph_remove_unreachable_nodes (); - if (cgraph_dump_file) - fprintf (cgraph_dump_file, + if (dump_file) + fprintf (dump_file, "\nInlined %i calls, eliminated %i functions, " "%i insns turned to %i insns.\n\n", ncalls_inlined, nfunctions_inlined, initial_insns, @@ -1883,9 +1884,7 @@ cgraph_optimize (void) fprintf (cgraph_dump_file, "Marked "); dump_cgraph (cgraph_dump_file); } - - if (flag_inline_trees) - cgraph_decide_inlining (); + ipa_passes (); cgraph_global_info_ready = true; if (cgraph_dump_file) { @@ -2015,3 +2014,27 @@ init_cgraph (void) { cgraph_dump_file = dump_begin (TDI_cgraph, NULL); } + +/* When inlining shall be performed. */ +static bool +cgraph_gate_inlining (void) +{ + return flag_inline_trees; +} + +struct tree_opt_pass pass_ipa_inline = +{ + "inline", /* name */ + cgraph_gate_inlining, /* gate */ + cgraph_decide_inlining, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_INTEGRATION, /* tv_id */ + 0, /* properties_required */ + PROP_trees, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_cgraph | TODO_dump_func, /* todo_flags_finish */ + 0 /* letter */ +}; diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index 2284a798302..80c89bf2787 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -55,7 +55,7 @@ int dump_flags; bool in_gimple_form; /* The root of the compilation pass tree, once constructed. */ -static struct tree_opt_pass *all_passes; +static struct tree_opt_pass *all_passes, *all_ipa_passes; /* Pass: dump the gimplified, inlined, functions. */ @@ -210,7 +210,7 @@ static struct tree_opt_pass pass_init_datastructures = enabled or not. */ static void -register_one_dump_file (struct tree_opt_pass *pass, int n) +register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n) { char *dot_name, *flag_name, *glob_name; char num[10]; @@ -222,7 +222,15 @@ register_one_dump_file (struct tree_opt_pass *pass, int n) ? 1 : pass->static_pass_number)); dot_name = concat (".", pass->name, num, NULL); - if (pass->properties_provided & PROP_trees) + if (ipa) + { + flag_name = concat ("ipa-", pass->name, num, NULL); + glob_name = concat ("ipa-", pass->name, NULL); + /* First IPA dump is cgraph that is dumped via separate channels. */ + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_IPA, n + 1, 0); + } + else if (pass->properties_provided & PROP_trees) { flag_name = concat ("tree-", pass->name, num, NULL); glob_name = concat ("tree-", pass->name, NULL); @@ -239,7 +247,7 @@ register_one_dump_file (struct tree_opt_pass *pass, int n) } static int -register_dump_files (struct tree_opt_pass *pass, int properties) +register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties) { static int n = 0; do @@ -260,7 +268,7 @@ register_dump_files (struct tree_opt_pass *pass, int properties) n++; if (pass->sub) - new_properties = register_dump_files (pass->sub, new_properties); + new_properties = register_dump_files (pass->sub, ipa, new_properties); /* If we have a gate, combine the properties that we could have with and without the pass being examined. */ @@ -271,7 +279,7 @@ register_dump_files (struct tree_opt_pass *pass, int properties) pass->properties_provided = properties; if (pass->name) - register_one_dump_file (pass, pass_number); + register_one_dump_file (pass, ipa, pass_number); pass = pass->next; } @@ -326,6 +334,10 @@ init_tree_optimization_passes (void) struct tree_opt_pass **p; #define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS)) + /* Intraprocedural optimization passes. */ + p = &all_ipa_passes; + NEXT_PASS (pass_ipa_inline); + *p = NULL; p = &all_passes; NEXT_PASS (pass_gimple); @@ -432,12 +444,16 @@ init_tree_optimization_passes (void) #undef NEXT_PASS - /* Register the passes with the tree dump code. */ - register_dump_files (all_passes, 0); + register_dump_files (all_passes, false, PROP_gimple_any + | PROP_gimple_lcf + | PROP_gimple_leh + | PROP_cfg); + register_dump_files (all_ipa_passes, true, PROP_gimple_any + | PROP_gimple_lcf + | PROP_gimple_leh + | PROP_cfg); } -static void execute_pass_list (struct tree_opt_pass *); - static unsigned int last_verified; static void @@ -465,7 +481,8 @@ execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) cleanup_tree_cfg (); } - if ((flags & TODO_dump_func) && dump_file) + if ((flags & TODO_dump_func) + && dump_file && current_function_decl) { if (properties & PROP_trees) dump_function_to_file (current_function_decl, @@ -479,6 +496,14 @@ execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) close the file before aborting. */ fflush (dump_file); } + if ((flags & TODO_dump_cgraph) + && dump_file && !current_function_decl) + { + dump_cgraph (dump_file); + /* Flush the file. If verification fails, we won't be able to + close the file before aborting. */ + fflush (dump_file); + } if (flags & TODO_ggc_collect) { @@ -522,18 +547,18 @@ execute_one_pass (struct tree_opt_pass *pass) bool initializing_dump = !dump_initialized_p (pass->static_pass_number); dump_file_name = get_dump_file_name (pass->static_pass_number); dump_file = dump_begin (pass->static_pass_number, &dump_flags); - if (dump_file) + if (dump_file && current_function_decl) { const char *dname, *aname; dname = lang_hooks.decl_printable_name (current_function_decl, 2); aname = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl))); - fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, - cfun->function_frequency == FUNCTION_FREQUENCY_HOT - ? " (hot)" - : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED - ? " (unlikely executed)" - : ""); + fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, + cfun->function_frequency == FUNCTION_FREQUENCY_HOT + ? " (hot)" + : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED + ? " (unlikely executed)" + : ""); } if (initializing_dump @@ -592,6 +617,13 @@ execute_pass_list (struct tree_opt_pass *pass) } while (pass); } + +/* Execute all IPA passes. */ +void +ipa_passes (void) +{ + execute_pass_list (all_ipa_passes); +} /* Update recursively all inlined_to pointers of functions diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index ac1ab920887..c9fdd852ec2 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -106,6 +106,7 @@ struct dump_file_info #define TODO_verify_stmts (1 << 4) #define TODO_cleanup_cfg (1 << 5) #define TODO_verify_loops (1 << 6) +#define TODO_dump_cgraph (1 << 7) /* To-do flags for calls to update_ssa. */ @@ -153,6 +154,8 @@ struct dump_file_info #define TODO_verify_all \ (TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts) +extern void ipa_passes (void); + extern struct tree_opt_pass pass_mudflap_1; extern struct tree_opt_pass pass_mudflap_2; extern struct tree_opt_pass pass_remove_useless_stmts; @@ -214,4 +217,6 @@ extern struct tree_opt_pass pass_vrp; extern struct tree_opt_pass pass_create_structure_vars; extern struct tree_opt_pass pass_uncprop; +extern struct tree_opt_pass pass_ipa_inline; + #endif /* GCC_TREE_PASS_H */