tree-pass.h (opt_pass): Add IPA_PASS.

* tree-pass.h (opt_pass): Add IPA_PASS.
	(varpool_node, cgraph_node): Forward declare.
	(ipa_opt_pass): Define.
	(pass_ipa_inline): Turn into ipa_opt_pass.
	(pass_apply_inline): Remove.
	* ipa-inline.c (pass_ipa_inline): Turn into ipa_opt_pass.
	(apply_inline): Turn into ....
	(inline_transform): ... this one.
	(inline_generate_summary): New function.
	(pass_apply_inline): Remove.
	* function.h (ipa_opt_pass): Forward declare structure; typedef;
	vector.
	(struct function): Add ipa_transforms_to_apply.
	* passes.c (register_one_dump_file): Work on IPA_PASS.
	(init_optimization_passes): Remove pass_inline_parameters and
	pass_apply_inline.
	(pass_init_dump_file, pass_fini_dump_file): Break out from ....
	(execute_one_pass) ... here; apply transforms when possible.
	(add_ipa_transform_pass, execute_ipa_summary_asses,
	execute_one_ipa_transform_pass): New.
	(execute_ipa_pass_list): Update for IPA_PASS type.

From-SVN: r134859
This commit is contained in:
Jan Hubicka 2008-05-01 18:08:15 +02:00 committed by Jan Hubicka
parent bd9513ea36
commit 17653c00b9
5 changed files with 259 additions and 79 deletions

View File

@ -1,3 +1,27 @@
2008-05-01 Jan Hubicka <jh@suse.cz>
* tree-pass.h (opt_pass): Add IPA_PASS.
(varpool_node, cgraph_node): Forward declare.
(ipa_opt_pass): Define.
(pass_ipa_inline): Turn into ipa_opt_pass.
(pass_apply_inline): Remove.
* ipa-inline.c (pass_ipa_inline): Turn into ipa_opt_pass.
(apply_inline): Turn into ....
(inline_transform): ... this one.
(inline_generate_summary): New function.
(pass_apply_inline): Remove.
* function.h (ipa_opt_pass): Forward declare structure; typedef;
vector.
(struct function): Add ipa_transforms_to_apply.
* passes.c (register_one_dump_file): Work on IPA_PASS.
(init_optimization_passes): Remove pass_inline_parameters and
pass_apply_inline.
(pass_init_dump_file, pass_fini_dump_file): Break out from ....
(execute_one_pass) ... here; apply transforms when possible.
(add_ipa_transform_pass, execute_ipa_summary_asses,
execute_one_ipa_transform_pass): New.
(execute_ipa_pass_list): Update for IPA_PASS type.
2008-05-01 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_builtin_type): Add

View File

@ -179,6 +179,11 @@ struct call_site_record;
DEF_VEC_P(temp_slot_p);
DEF_VEC_ALLOC_P(temp_slot_p,gc);
struct ipa_opt_pass;
typedef struct ipa_opt_pass *ipa_opt_pass;
DEF_VEC_P(ipa_opt_pass);
DEF_VEC_ALLOC_P(ipa_opt_pass,heap);
enum function_frequency {
/* This function most likely won't be executed at all.
@ -466,6 +471,10 @@ struct function GTY(())
/* Properties used by the pass manager. */
unsigned int curr_properties;
unsigned int last_verified;
/* Interprocedural passes scheduled to have their transform functions
applied next time we execute local pass on them. We maintain it
per-function in order to allow IPA passes to introduce new functions. */
VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply;
/* Collected bit flags. */

View File

@ -1426,26 +1426,6 @@ cgraph_gate_inlining (void)
return flag_inline_trees;
}
struct simple_ipa_opt_pass pass_ipa_inline =
{
{
SIMPLE_IPA_PASS,
"inline", /* name */
cgraph_gate_inlining, /* gate */
cgraph_decide_inlining, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_INLINE_HEURISTICS, /* tv_id */
0, /* properties_required */
PROP_cfg, /* properties_provided */
0, /* properties_destroyed */
TODO_remove_functions, /* todo_flags_finish */
TODO_dump_cgraph | TODO_dump_func
| TODO_remove_functions /* todo_flags_finish */
}
};
/* Because inlining might remove no-longer reachable nodes, we need to
keep the array visible to garbage collector to avoid reading collected
out nodes. */
@ -1579,13 +1559,20 @@ struct gimple_opt_pass pass_inline_parameters =
}
};
/* Apply inline plan to the function. */
static unsigned int
apply_inline (void)
/* Note function body size. */
void
inline_generate_summary (struct cgraph_node *node ATTRIBUTE_UNUSED)
{
compute_inline_parameters ();
return;
}
/* Apply inline plan to function. */
int
inline_transform (struct cgraph_node *node)
{
unsigned int todo = 0;
struct cgraph_edge *e;
struct cgraph_node *node = cgraph_node (current_function_decl);
/* Even when not optimizing, ensure that always_inline functions get inlined.
*/
@ -1617,13 +1604,13 @@ apply_inline (void)
return todo | execute_fixup_cfg ();
}
struct gimple_opt_pass pass_apply_inline =
struct ipa_opt_pass pass_ipa_inline =
{
{
GIMPLE_PASS,
"apply_inline", /* name */
NULL, /* gate */
apply_inline, /* execute */
IPA_PASS,
"inline", /* name */
cgraph_gate_inlining, /* gate */
cgraph_decide_inlining, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
@ -1631,10 +1618,19 @@ struct gimple_opt_pass pass_apply_inline =
0, /* properties_required */
PROP_cfg, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_verify_flow
| TODO_verify_stmts /* todo_flags_finish */
}
TODO_remove_functions, /* todo_flags_finish */
TODO_dump_cgraph | TODO_dump_func
| TODO_remove_functions /* todo_flags_finish */
},
inline_generate_summary, /* function_generate_summary */
NULL, /* variable_generate_summary */
NULL, /* function_write_summary */
NULL, /* variable_write_summary */
NULL, /* function_read_summary */
NULL, /* variable_read_summary */
0, /* TODOs */
inline_transform, /* function_transform */
NULL, /* variable_transform */
};
#include "gt-ipa-inline.h"

View File

@ -352,7 +352,7 @@ register_one_dump_file (struct opt_pass *pass)
? 1 : pass->static_pass_number));
dot_name = concat (".", pass->name, num, NULL);
if (pass->type == SIMPLE_IPA_PASS)
if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
prefix = "ipa-", flags = TDF_IPA;
else if (pass->type == GIMPLE_PASS)
prefix = "tree-", flags = TDF_TREE;
@ -538,7 +538,6 @@ init_optimization_passes (void)
NEXT_PASS (pass_release_ssa_names);
}
NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_inline_parameters);
}
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
@ -554,7 +553,6 @@ init_optimization_passes (void)
/* These passes are run after IPA passes on every function that is being
output to the assembler file. */
p = &all_passes;
NEXT_PASS (pass_apply_inline);
NEXT_PASS (pass_all_optimizations);
{
struct opt_pass **p = &pass_all_optimizations.pass.sub;
@ -1054,8 +1052,58 @@ verify_curr_properties (void *data)
}
#endif
/* Initialize pass dump file. */
static bool
pass_init_dump_file (struct opt_pass *pass)
{
/* If a dump file name is present, open it if enabled. */
if (pass->static_pass_number != -1)
{
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;; Apply transform to function %s (%s)%s\n\n", dname, aname,
cfun->function_frequency == FUNCTION_FREQUENCY_HOT
? " (hot)"
: cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
? " (unlikely executed)"
: "");
}
return initializing_dump;
}
else
return false;
}
/* Flush PASS dump file. */
static void
pass_fini_dump_file (struct opt_pass *pass)
{
/* Flush and close dump file. */
if (dump_file_name)
{
free (CONST_CAST (char *, dump_file_name));
dump_file_name = NULL;
}
if (dump_file)
{
dump_end (pass->static_pass_number, dump_file);
dump_file = NULL;
}
}
/* After executing the pass, apply expected changes to the function
properties. */
static void
update_properties_after_pass (void *data)
{
@ -1064,6 +1112,80 @@ update_properties_after_pass (void *data)
& ~pass->properties_destroyed;
}
/* Schedule IPA transform pass DATA for CFUN. */
static void
add_ipa_transform_pass (void *data)
{
struct ipa_opt_pass *ipa_pass = (struct ipa_opt_pass *) data;
VEC_safe_push (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply, ipa_pass);
}
/* Execute IPA pass function summary generation. DATA is pointer to
pass list to execute. */
static void
execute_ipa_summary_passes (void *data)
{
struct ipa_opt_pass *ipa_pass = (struct ipa_opt_pass *)data;
struct cgraph_node *node = cgraph_node (cfun->decl);
while (ipa_pass && ipa_pass->pass.type == IPA_PASS)
{
struct opt_pass *pass = &ipa_pass->pass;
if (!pass->gate || pass->gate ())
{
pass_init_dump_file (pass);
ipa_pass->function_generate_summary (node);
pass_fini_dump_file (pass);
}
ipa_pass = (struct ipa_opt_pass *)ipa_pass->pass.next;
}
}
/* Execute IPA_PASS function transform on NODE. */
static void
execute_one_ipa_transform_pass (struct cgraph_node *node,
struct ipa_opt_pass *ipa_pass)
{
struct opt_pass *pass = &ipa_pass->pass;
unsigned int todo_after = 0;
current_pass = pass;
if (!ipa_pass->function_transform)
return;
/* Note that the folders should only create gimple expressions.
This is a hack until the new folder is ready. */
in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
pass_init_dump_file (pass);
/* Run pre-pass verification. */
execute_todo (pass->todo_flags_start);
/* If a timevar is present, start it. */
if (pass->tv_id)
timevar_push (pass->tv_id);
/* Do it! */
todo_after = ipa_pass->function_transform (node);
/* Stop timevar. */
if (pass->tv_id)
timevar_pop (pass->tv_id);
/* Run post-pass cleanup and verification. */
execute_todo (todo_after);
verify_interpass_invariants ();
pass_fini_dump_file (pass);
current_pass = NULL;
/* Reset in_gimple_form to not break non-unit-at-a-time mode. */
in_gimple_form = false;
}
static bool
execute_one_pass (struct opt_pass *pass)
{
@ -1072,11 +1194,26 @@ execute_one_pass (struct opt_pass *pass)
/* IPA passes are executed on whole program, so cfun should be NULL.
Ohter passes needs function context set. */
if (pass->type == SIMPLE_IPA_PASS)
if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
gcc_assert (!cfun && !current_function_decl);
else
gcc_assert (cfun && current_function_decl);
if (cfun && cfun->ipa_transforms_to_apply)
{
unsigned int i;
struct cgraph_node *node = cgraph_node (current_function_decl);
for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply);
i++)
execute_one_ipa_transform_pass (node,
VEC_index (ipa_opt_pass,
cfun->ipa_transforms_to_apply,
i));
VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply);
cfun->ipa_transforms_to_apply = NULL;
}
current_pass = pass;
/* See if we're supposed to run this pass. */
if (pass->gate && !pass->gate ())
@ -1100,28 +1237,7 @@ execute_one_pass (struct opt_pass *pass)
(void *)(size_t)pass->properties_required);
#endif
/* If a dump file name is present, open it if enabled. */
if (pass->static_pass_number != -1)
{
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)"
: "");
}
}
else
initializing_dump = false;
initializing_dump = pass_init_dump_file (pass);
/* If a timevar is present, start it. */
if (pass->tv_id)
@ -1154,24 +1270,15 @@ execute_one_pass (struct opt_pass *pass)
/* Run post-pass cleanup and verification. */
execute_todo (todo_after | pass->todo_flags_finish);
verify_interpass_invariants ();
if (pass->type == IPA_PASS)
do_per_function (add_ipa_transform_pass, pass);
if (!current_function_decl)
cgraph_process_new_functions ();
/* Flush and close dump file. */
if (dump_file_name)
{
free (CONST_CAST (char *, dump_file_name));
dump_file_name = NULL;
}
pass_fini_dump_file (pass);
if (dump_file)
{
dump_end (pass->static_pass_number, dump_file);
dump_file = NULL;
}
if (pass->type != SIMPLE_IPA_PASS)
if (pass->type != SIMPLE_IPA_PASS && pass->type != IPA_PASS)
gcc_assert (!(cfun->curr_properties & PROP_trees)
|| pass->type != RTL_PASS);
@ -1201,17 +1308,31 @@ execute_pass_list (struct opt_pass *pass)
void
execute_ipa_pass_list (struct opt_pass *pass)
{
bool summaries_generated = false;
do
{
gcc_assert (!current_function_decl);
gcc_assert (!cfun);
gcc_assert (pass->type == SIMPLE_IPA_PASS);
gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
if (pass->type == IPA_PASS && (!pass->gate || pass->gate ()))
{
if (!summaries_generated)
{
if (!quiet_flag && !cfun)
fprintf (stderr, " <summary generate>");
do_per_function_toporder (execute_ipa_summary_passes, pass);
}
summaries_generated = true;
}
else
summaries_generated = false;
if (execute_one_pass (pass) && pass->sub)
{
if (pass->sub->type == GIMPLE_PASS)
do_per_function_toporder ((void (*)(void *))execute_pass_list,
pass->sub);
else if (pass->sub->type == SIMPLE_IPA_PASS)
else if (pass->sub->type == SIMPLE_IPA_PASS
|| pass->sub->type == IPA_PASS)
execute_ipa_pass_list (pass->sub);
else
gcc_unreachable ();

View File

@ -96,7 +96,8 @@ struct opt_pass
enum opt_pass_type {
GIMPLE_PASS,
RTL_PASS,
SIMPLE_IPA_PASS
SIMPLE_IPA_PASS,
IPA_PASS
} type;
/* Terse name of the pass used as a fragment of the dump file name. */
const char *name;
@ -133,7 +134,7 @@ struct opt_pass
unsigned int todo_flags_finish;
};
/* Description or GIMPLE pass. */
/* Description of GIMPLE pass. */
struct gimple_opt_pass
{
struct opt_pass pass;
@ -145,7 +146,36 @@ struct rtl_opt_pass
struct opt_pass pass;
};
/* Description if simple IPA pass. Simple IPA passes have just one execute
struct varpool_node;
struct cgraph_node;
/* Description of IPA pass with generate summary, write, execute, read and
transform stages. */
struct ipa_opt_pass
{
struct opt_pass pass;
/* IPA passes can analyze function body and variable initializers using this
hook and produce summary. */
void (*function_generate_summary) (struct cgraph_node *);
void (*variable_generate_summary) (struct varpool_node *);
/* These hooks will be used to serialize IPA summaries on disk. For a moment
they are just placeholders. */
void (*function_write_summary) (struct cgraph_node *);
void (*variable_write_summary) (struct varpool_node *);
void (*function_read_summary) (struct cgraph_node *);
void (*variable_read_summary) (struct varpool_node *);
/* Results of interprocedural propagation of an IPA pass is applied to
function body via this hook. */
unsigned int function_transform_todo_flags_start;
unsigned int (*function_transform) (struct cgraph_node *);
void (*variable_transform) (struct varpool_node *);
};
/* Description of simple IPA pass. Simple IPA passes have just one execute
hook. */
struct simple_ipa_opt_pass
{
@ -353,9 +383,10 @@ extern struct gimple_opt_pass pass_build_cgraph_edges;
extern struct gimple_opt_pass pass_reset_cc_flags;
/* IPA Passes */
extern struct ipa_opt_pass pass_ipa_inline;
extern struct simple_ipa_opt_pass pass_ipa_matrix_reorg;
extern struct simple_ipa_opt_pass pass_ipa_cp;
extern struct simple_ipa_opt_pass pass_ipa_inline;
extern struct simple_ipa_opt_pass pass_ipa_early_inline;
extern struct simple_ipa_opt_pass pass_ipa_reference;
extern struct simple_ipa_opt_pass pass_ipa_pure_const;
@ -471,7 +502,6 @@ extern struct rtl_opt_pass pass_rtl_seqabstr;
extern struct gimple_opt_pass pass_release_ssa_names;
extern struct gimple_opt_pass pass_early_inline;
extern struct gimple_opt_pass pass_inline_parameters;
extern struct gimple_opt_pass pass_apply_inline;
extern struct gimple_opt_pass pass_all_early_optimizations;
extern struct gimple_opt_pass pass_update_address_taken;