2011-06-14 David Li * passes.c (do_per_function_toporder): Support for dump splitting. (execute_function_dump): Support for dump splitting. (pass_init_dump_file): Support for dump splitting. (execute_one_ipa_transform_pass): Support for dump splitting. (execute_one_pass): Support for dump splitting. Index: tree-dump.c =================================================================== --- tree-dump.c (revision 175032) +++ tree-dump.c (working copy) @@ -822,6 +822,10 @@ static const struct dump_option_value_in {"eh", TDF_EH}, {"alias", TDF_ALIAS}, {"nouid", TDF_NOUID}, + {"before_preparation", TDF_START}, + {"before", TDF_BEFORE}, + {"after", TDF_AFTER}, + {"after_cleanup", TDF_FINISH}, {"enumerate_locals", TDF_ENUMERATE_LOCALS}, {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE Index: tree-pass.h =================================================================== --- tree-pass.h (revision 175032) +++ tree-pass.h (working copy) @@ -83,6 +83,11 @@ enum tree_dump_index #define TDF_ALIAS (1 << 21) /* display alias information */ #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid. */ #define TDF_CSELIB (1 << 23) /* Dump cselib details. */ +#define TDF_START (1 << 24) /* Dump before TODO_start. */ +#define TDF_BEFORE (1 << 25) /* Dump before pass. */ +#define TDF_AFTER (1 << 26) /* Dump after pass. */ +#define TDF_FINISH (1 << 27) /* Dump after TODO_finish. */ + /* In tree-dump.c */ Index: passes.c =================================================================== --- passes.c (revision 175051) +++ passes.c (working copy) @@ -128,6 +128,7 @@ int dump_flags; bool in_gimple_form; bool first_pass_instance; +static FILE *dump_file_start, *dump_file_before, *dump_file_after, *dump_file_finish; /* This is called from various places for FUNCTION_DECL, VAR_DECL, and TYPE_DECL nodes. @@ -1605,21 +1606,23 @@ do_per_function_toporder (void (*callbac /* Helper function to perform function body dump. */ static void -execute_function_dump (void *data ATTRIBUTE_UNUSED) +execute_function_dump (void *data) { - if (dump_file && current_function_decl) + FILE *df = (FILE *)data; + + if (df && current_function_decl) { if (cfun->curr_properties & PROP_trees) - dump_function_to_file (current_function_decl, dump_file, dump_flags); + dump_function_to_file (current_function_decl, df, dump_flags); else { if (dump_flags & TDF_SLIM) - print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags); + print_rtl_slim_with_bb (df, get_insns (), dump_flags); else if ((cfun->curr_properties & PROP_cfg) && (dump_flags & TDF_BLOCKS)) - print_rtl_with_bb (dump_file, get_insns ()); + print_rtl_with_bb (df, get_insns ()); else - print_rtl (dump_file, get_insns ()); + print_rtl (df, get_insns ()); if ((cfun->curr_properties & PROP_cfg) && graph_dump_format != no_graph @@ -1629,7 +1632,7 @@ execute_function_dump (void *data ATTRIB /* Flush the file. If verification fails, we won't be able to close the file before aborting. */ - fflush (dump_file); + fflush (df); } } @@ -1784,6 +1787,50 @@ verify_curr_properties (void *data) } #endif + +/* Helper function to set up file descriptors for IR dumps. WHERE_FLAG + is the flag indicating where the IR come from; SUFFIX is the file suffix + of the dump file, and MODE is the file open mode. */ + +static FILE * +init_ir_dump_file (int where_flag, const char *suffix, const char *mode) +{ + if (dump_flags & where_flag) + { + char *dump_name = concat (dump_file_name, suffix, NULL); + FILE *stream = fopen (dump_name, mode); + if (!stream) + error ("could not open dump file %qs: %m", dump_name); + free (dump_name); + if (current_function_decl) + dump_function_header (stream, current_function_decl, dump_flags); + return stream; + } + else + return dump_file; +} + +/* Helper function to set up file descriptors for IR dumps. */ + +static void +pass_init_ir_dump_files (struct opt_pass *pass) +{ + struct dump_file_info *dfi; + const char *mode; + + if (!dump_file) + return; + + dfi = get_dump_file_info (pass->static_pass_number); + mode = dfi->state < 0 ? "w" : "a"; + + dump_file_start = init_ir_dump_file (TDF_START, ".before_preparation", mode); + dump_file_before = init_ir_dump_file (TDF_BEFORE, ".before", mode); + dump_file_after = init_ir_dump_file (TDF_AFTER, ".after", mode); + dump_file_finish = init_ir_dump_file (TDF_FINISH, ".after_cleanup", mode); +} + + /* Initialize pass dump file. */ /* This is non-static so that the plugins can use it. */ @@ -1798,12 +1845,35 @@ pass_init_dump_file (struct opt_pass *pa dump_file = dump_begin (pass->static_pass_number, &dump_flags); if (dump_file && current_function_decl) dump_function_header (dump_file, current_function_decl, dump_flags); + + if (dump_file) + pass_init_ir_dump_files (pass); + return initializing_dump; } else return false; } +/* Close dump files. */ + +static void +close_ir_dump_file (void) +{ + if (dump_file_start != dump_file) + fclose (dump_file_start); + dump_file_start = NULL; + if (dump_file_before != dump_file) + fclose (dump_file_before); + dump_file_before = NULL; + if (dump_file_after != dump_file) + fclose (dump_file_after); + dump_file_after = NULL; + if (dump_file_finish != dump_file) + fclose (dump_file_finish); + dump_file_finish = NULL; +} + /* Flush PASS dump file. */ /* This is non-static so that plugins can use it. */ @@ -1811,6 +1881,7 @@ void pass_fini_dump_file (struct opt_pass *pass) { /* Flush and close dump file. */ + close_ir_dump_file (); if (dump_file_name) { free (CONST_CAST (char *, dump_file_name)); @@ -1886,9 +1957,15 @@ execute_one_ipa_transform_pass (struct c pass_init_dump_file (pass); + if (dump_file && (dump_flags & TDF_START)) + do_per_function (execute_function_dump, dump_file_start); + /* Run pre-pass verification. */ execute_todo (ipa_pass->function_transform_todo_flags_start); + if (dump_file && (dump_flags & TDF_BEFORE)) + do_per_function (execute_function_dump, dump_file_before); + /* If a timevar is present, start it. */ if (pass->tv_id != TV_NONE) timevar_push (pass->tv_id); @@ -1900,11 +1977,15 @@ execute_one_ipa_transform_pass (struct c if (pass->tv_id != TV_NONE) timevar_pop (pass->tv_id); + if (dump_file && (dump_flags & TDF_AFTER)) + do_per_function (execute_function_dump, dump_file_after); + /* Run post-pass cleanup and verification. */ execute_todo (todo_after); verify_interpass_invariants (); - do_per_function (execute_function_dump, NULL); + if (dump_file) + do_per_function (execute_function_dump, dump_file_finish); pass_fini_dump_file (pass); current_pass = NULL; @@ -2005,9 +2086,15 @@ execute_one_pass (struct opt_pass *pass) initializing_dump = pass_init_dump_file (pass); + if (dump_file && (dump_flags & TDF_START)) + do_per_function (execute_function_dump, dump_file_start); + /* Run pre-pass verification. */ execute_todo (pass->todo_flags_start); + if (dump_file && (dump_flags & TDF_BEFORE)) + do_per_function (execute_function_dump, dump_file_before); + #ifdef ENABLE_CHECKING do_per_function (verify_curr_properties, (void *)(size_t)pass->properties_required); @@ -2042,10 +2129,16 @@ execute_one_pass (struct opt_pass *pass) clean_graph_dump_file (dump_file_name); } + if (dump_file && (dump_flags & TDF_AFTER)) + do_per_function (execute_function_dump, dump_file_after); + /* Run post-pass cleanup and verification. */ execute_todo (todo_after | pass->todo_flags_finish); verify_interpass_invariants (); - do_per_function (execute_function_dump, NULL); + + if (dump_file) + do_per_function (execute_function_dump, dump_file_finish); + if (pass->type == IPA_PASS) { struct cgraph_node *node;