This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Tree profiling merge: IPA passmanager
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at redhat dot com
- Date: Thu, 17 Mar 2005 22:22:14 +0100
- Subject: Tree profiling merge: IPA passmanager
Hi,
this patch adds bare bones of IPA passmanager. Unlike version on
tree-profiling branch it don't have analyze/modify hooks since these
seems just to make things complicated until we resolve how to scale for
larger programs.
Bootstrapped/regtested i686-pc-gnu-linux, OK?
Honza
2005-03-17 Jan Hubicka <jh@suse.cz>
* 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
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1454
diff -c -3 -p -r1.1454 Makefile.in
*** Makefile.in 16 Mar 2005 06:03:18 -0000 1.1454
--- Makefile.in 17 Mar 2005 14:54:04 -0000
*************** cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM
*** 1962,1968 ****
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)
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 \
--- 1962,1968 ----
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) 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 \
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.95
diff -c -3 -p -r1.95 cgraphunit.c
*** cgraphunit.c 16 Mar 2005 17:14:55 -0000 1.95
--- cgraphunit.c 17 Mar 2005 14:54:04 -0000
*************** Software Foundation, 59 Temple Place - S
*** 189,194 ****
--- 189,195 ----
#include "intl.h"
#include "function.h"
#include "tree-gimple.h"
+ #include "tree-pass.h"
#define INSNS_PER_CALL 10
*************** cgraph_decide_recursive_inlining (struct
*** 1296,1303 ****
if (!first_call)
return;
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
"\nPerforming recursive inlining on %s\n",
cgraph_node_name (node));
--- 1297,1304 ----
if (!first_call)
return;
! if (dump_file)
! fprintf (dump_file,
"\nPerforming recursive inlining on %s\n",
cgraph_node_name (node));
*************** cgraph_decide_recursive_inlining (struct
*** 1335,1342 ****
first_call->aux = NULL;
first_call = next;
}
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
"\n Inlined %i times, body grown from %i to %i insns\n", n,
master_clone->global.insns, node->global.insns);
--- 1336,1343 ----
first_call->aux = NULL;
first_call = next;
}
! 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);
*************** cgraph_set_inline_failed (struct cgraph_
*** 1357,1364 ****
{
struct cgraph_edge *e;
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file, "Inlining failed: %s\n", reason);
for (e = node->callers; e; e = e->next_caller)
if (e->inline_failed)
e->inline_failed = reason;
--- 1358,1365 ----
{
struct cgraph_edge *e;
! 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;
*************** cgraph_decide_inlining_of_small_function
*** 1399,1414 ****
fibheap_insert (heap, cgraph_estimate_growth (node), node);
}
! if (cgraph_dump_file)
! fprintf (cgraph_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,
"\nConsidering %s with %i insns\n"
" Estimated growth is %+i insns.\n",
cgraph_node_name (node), node->global.insns,
--- 1400,1415 ----
fibheap_insert (heap, cgraph_estimate_growth (node), node);
}
! 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 (dump_file)
! fprintf (dump_file,
"\nConsidering %s with %i insns\n"
" Estimated growth is %+i insns.\n",
cgraph_node_name (node), node->global.insns,
*************** cgraph_decide_inlining_of_small_function
*** 1431,1438 ****
|| !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",
cgraph_node_name (e->caller), e->inline_failed);
continue;
}
--- 1432,1439 ----
|| !cgraph_check_inline_limits (e->caller, e->callee,
&e->inline_failed))
{
! if (dump_file)
! fprintf (dump_file, " Not inlining into %s:%s.\n",
cgraph_node_name (e->caller), e->inline_failed);
continue;
}
*************** cgraph_decide_inlining_of_small_function
*** 1445,1452 ****
fibheap_replace_key (heap, heap_node[where->uid],
cgraph_estimate_growth (where));
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
--- 1446,1453 ----
fibheap_replace_key (heap, heap_node[where->uid],
cgraph_estimate_growth (where));
! if (dump_file)
! fprintf (dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
*************** cgraph_decide_inlining_of_small_function
*** 1459,1466 ****
are now called more times; update keys. */
update_callee_keys (heap, heap_node, node);
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
--- 1460,1467 ----
are now called more times; update keys. */
update_callee_keys (heap, heap_node, node);
! if (dump_file)
! fprintf (dump_file,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
*************** cgraph_decide_inlining (void)
*** 1490,1505 ****
nnodes = cgraph_postorder (order);
! if (cgraph_dump_file)
! fprintf (cgraph_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");
/* In the first pass mark all always_inline edges. Do this with a priority
so none of our later choices will make this impossible. */
--- 1491,1506 ----
nnodes = cgraph_postorder (order);
! 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 (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. */
*************** cgraph_decide_inlining (void)
*** 1511,1518 ****
if (!node->local.disregard_inline_limits)
continue;
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
"\nConsidering %s %i insns (always inline)\n",
cgraph_node_name (node), node->global.insns);
old_insns = overall_insns;
--- 1512,1519 ----
if (!node->local.disregard_inline_limits)
continue;
! if (dump_file)
! fprintf (dump_file,
"\nConsidering %s %i insns (always inline)\n",
cgraph_node_name (node), node->global.insns);
old_insns = overall_insns;
*************** cgraph_decide_inlining (void)
*** 1525,1538 ****
&e->inline_failed))
continue;
cgraph_mark_inline_edge (e);
! if (cgraph_dump_file)
! fprintf (cgraph_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,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
--- 1526,1539 ----
&e->inline_failed))
continue;
cgraph_mark_inline_edge (e);
! 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 (dump_file)
! fprintf (dump_file,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
*************** cgraph_decide_inlining (void)
*** 1541,1548 ****
{
cgraph_decide_inlining_of_small_functions ();
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
/* And finally decide what functions are called once. */
--- 1542,1549 ----
{
cgraph_decide_inlining_of_small_functions ();
! if (dump_file)
! fprintf (dump_file, "\nDeciding on functions called once:\n");
/* And finally decide what functions are called once. */
*************** cgraph_decide_inlining (void)
*** 1565,1572 ****
ok = false;
if (ok)
{
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
"\nConsidering %s %i insns.\n"
" Called once from %s %i insns.\n",
cgraph_node_name (node), node->global.insns,
--- 1566,1573 ----
ok = false;
if (ok)
{
! 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,
*************** cgraph_decide_inlining (void)
*** 1579,1586 ****
NULL))
{
cgraph_mark_inline (node->callers);
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns"
" for a net change of %+i insns.\n",
cgraph_node_name (node->callers->caller),
--- 1580,1587 ----
NULL))
{
cgraph_mark_inline (node->callers);
! 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),
*************** cgraph_decide_inlining (void)
*** 1589,1596 ****
}
else
{
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
" Inline limit reached, not inlined.\n");
}
}
--- 1590,1597 ----
}
else
{
! if (dump_file)
! fprintf (dump_file,
" Inline limit reached, not inlined.\n");
}
}
*************** cgraph_decide_inlining (void)
*** 1603,1610 ****
inline functions. */
cgraph_remove_unreachable_nodes ();
! if (cgraph_dump_file)
! fprintf (cgraph_dump_file,
"\nInlined %i calls, eliminated %i functions, "
"%i insns turned to %i insns.\n\n",
ncalls_inlined, nfunctions_inlined, initial_insns,
--- 1604,1611 ----
inline functions. */
cgraph_remove_unreachable_nodes ();
! 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,
*************** cgraph_optimize (void)
*** 1772,1780 ****
fprintf (cgraph_dump_file, "Marked ");
dump_cgraph (cgraph_dump_file);
}
!
! if (flag_inline_trees)
! cgraph_decide_inlining ();
cgraph_global_info_ready = true;
if (cgraph_dump_file)
{
--- 1773,1779 ----
fprintf (cgraph_dump_file, "Marked ");
dump_cgraph (cgraph_dump_file);
}
! ipa_passes ();
cgraph_global_info_ready = true;
if (cgraph_dump_file)
{
*************** init_cgraph (void)
*** 1900,1902 ****
--- 1899,1925 ----
{
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 */
+ };
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.78
diff -c -3 -p -r2.78 tree-optimize.c
*** tree-optimize.c 13 Mar 2005 00:45:52 -0000 2.78
--- tree-optimize.c 17 Mar 2005 14:54:04 -0000
*************** bitmap vars_to_rename;
*** 56,62 ****
bool in_gimple_form;
/* The root of the compilation pass tree, once constructed. */
! static struct tree_opt_pass *all_passes;
/* Pass: dump the gimplified, inlined, functions. */
--- 56,62 ----
bool in_gimple_form;
/* The root of the compilation pass tree, once constructed. */
! static struct tree_opt_pass *all_passes, *all_ipa_passes;
/* Pass: dump the gimplified, inlined, functions. */
*************** static struct tree_opt_pass pass_init_da
*** 211,217 ****
enabled or not. */
static void
! register_one_dump_file (struct tree_opt_pass *pass, int n)
{
char *dot_name, *flag_name, *glob_name;
char num[10];
--- 211,217 ----
enabled or not. */
static void
! register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n)
{
char *dot_name, *flag_name, *glob_name;
char num[10];
*************** register_one_dump_file (struct tree_opt_
*** 223,229 ****
? 1 : pass->static_pass_number));
dot_name = concat (".", pass->name, num, NULL);
! if (pass->properties_provided & PROP_trees)
{
flag_name = concat ("tree-", pass->name, num, NULL);
glob_name = concat ("tree-", pass->name, NULL);
--- 223,237 ----
? 1 : pass->static_pass_number));
dot_name = concat (".", pass->name, num, NULL);
! 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);
*************** register_one_dump_file (struct tree_opt_
*** 240,246 ****
}
static int
! register_dump_files (struct tree_opt_pass *pass, int properties)
{
static int n = 0;
do
--- 248,254 ----
}
static int
! register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties)
{
static int n = 0;
do
*************** register_dump_files (struct tree_opt_pas
*** 261,267 ****
n++;
if (pass->sub)
! new_properties = register_dump_files (pass->sub, new_properties);
/* If we have a gate, combine the properties that we could have with
and without the pass being examined. */
--- 269,275 ----
n++;
if (pass->sub)
! 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. */
*************** register_dump_files (struct tree_opt_pas
*** 272,278 ****
pass->properties_provided = properties;
if (pass->name)
! register_one_dump_file (pass, pass_number);
pass = pass->next;
}
--- 280,286 ----
pass->properties_provided = properties;
if (pass->name)
! register_one_dump_file (pass, ipa, pass_number);
pass = pass->next;
}
*************** init_tree_optimization_passes (void)
*** 327,332 ****
--- 335,344 ----
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);
*************** init_tree_optimization_passes (void)
*** 429,440 ****
#undef NEXT_PASS
! /* Register the passes with the tree dump code. */
! register_dump_files (all_passes, 0);
}
- static void execute_pass_list (struct tree_opt_pass *);
-
static unsigned int last_verified;
static void
--- 441,456 ----
#undef NEXT_PASS
! 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 unsigned int last_verified;
static void
*************** execute_todo (int properties, unsigned i
*** 459,465 ****
cleanup_tree_cfg ();
}
! if ((flags & TODO_dump_func) && dump_file)
{
if (properties & PROP_trees)
dump_function_to_file (current_function_decl,
--- 475,482 ----
cleanup_tree_cfg ();
}
! if ((flags & TODO_dump_func)
! && dump_file && current_function_decl)
{
if (properties & PROP_trees)
dump_function_to_file (current_function_decl,
*************** execute_todo (int properties, unsigned i
*** 473,478 ****
--- 490,503 ----
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)
ggc_collect ();
*************** execute_one_pass (struct tree_opt_pass *
*** 511,528 ****
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)
{
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)"
! : "");
}
if (initializing_dump
--- 536,553 ----
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 && 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)"
! : "");
}
if (initializing_dump
*************** execute_pass_list (struct tree_opt_pass
*** 581,586 ****
--- 606,618 ----
}
while (pass);
}
+
+ /* Execute all IPA passes. */
+ void
+ ipa_passes (void)
+ {
+ execute_pass_list (all_ipa_passes);
+ }
/* Update recursively all inlined_to pointers of functions
Index: tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v
retrieving revision 2.29
diff -c -3 -p -r2.29 tree-pass.h
*** tree-pass.h 13 Mar 2005 00:45:53 -0000 2.29
--- tree-pass.h 17 Mar 2005 14:54:04 -0000
*************** struct dump_file_info
*** 109,119 ****
--- 109,121 ----
#define TODO_verify_stmts (1 << 5)
#define TODO_fix_def_def_chains (1 << 6) /* rewrite def-def chains */
#define TODO_cleanup_cfg (1 << 7) /* cleanup the cfg. */
+ #define TODO_dump_cgraph (1 << 8)
#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;
*************** extern struct tree_opt_pass pass_fre;
*** 169,172 ****
--- 171,176 ----
extern struct tree_opt_pass pass_linear_transform;
extern struct tree_opt_pass pass_create_structure_vars;
+ extern struct tree_opt_pass pass_ipa_inline;
+
#endif /* GCC_TREE_PASS_H */