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:
parent
bd9513ea36
commit
17653c00b9
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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"
|
||||
|
203
gcc/passes.c
203
gcc/passes.c
@ -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 ();
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user