tree-pass.h (register_pass_info): New structure.

* tree-pass.h (register_pass_info): New structure.	
	(pass_positioning_ops): Move enum from gcc-plugin.h.
	(register_pass): New function.
	* gcc-plugin.h (plugin_pass): Delete structure.
	(pass_positioning_ops): Delete enum.
	* plugin.c (regsiter_pass): Delete function.
	(position_pass): Delete function.
	(added_pass_nodes): Delete variable.
	(prev_added_pass_nodes): Delete variable.
	(pass_list_node): Delete structure.
	* passes.c (make_pass_instance): New function.
	(next_pass_1): Change to call make_pass_instance.
	(pass_list_node): Move structure from gcc-plugin.h.
	(added_pass_nodes): Move variable from plugin.c.
	(prev_added_pass_nodes): Move variable from plugin.c.
	(position_pass): New function.
	(register_pass): New function.

From-SVN: r152257
This commit is contained in:
Sriraman Tallam 2009-09-28 23:15:35 +00:00 committed by Ian Lance Taylor
parent ef6ed66d16
commit b80b0fd9c7
5 changed files with 223 additions and 218 deletions

View File

@ -1,3 +1,23 @@
2009-09-28 Sriraman Tallam <tmsriram@google.com>
* tree-pass.h (register_pass_info): New structure.
(pass_positioning_ops): Move enum from gcc-plugin.h.
(register_pass): New function.
* gcc-plugin.h (plugin_pass): Delete structure.
(pass_positioning_ops): Delete enum.
* plugin.c (regsiter_pass): Delete function.
(position_pass): Delete function.
(added_pass_nodes): Delete variable.
(prev_added_pass_nodes): Delete variable.
(pass_list_node): Delete structure.
* passes.c (make_pass_instance): New function.
(next_pass_1): Change to call make_pass_instance.
(pass_list_node): Move structure from gcc-plugin.h.
(added_pass_nodes): Move variable from plugin.c.
(prev_added_pass_nodes): Move variable from plugin.c.
(position_pass): New function.
(register_pass): New function.
2009-09-28 Easwaran Raman <eraman@google.com>
* ifcvt.c (noce_try_abs): Recognize pattern and call

View File

@ -55,24 +55,6 @@ struct plugin_argument
char *value; /* value is optional and can be NULL. */
};
enum pass_positioning_ops
{
PASS_POS_INSERT_AFTER, /* Insert after the reference pass. */
PASS_POS_INSERT_BEFORE, /* Insert before the reference pass. */
PASS_POS_REPLACE /* Replace the reference pass. */
};
struct plugin_pass
{
struct opt_pass *pass; /* New pass provided by the plugin. */
const char *reference_pass_name; /* Name of the reference pass for hooking
up the new pass. */
int ref_pass_instance_number; /* Insert the pass at the specified
instance number of the reference pass.
Do it for every instance if it is 0. */
enum pass_positioning_ops pos_op; /* how to insert the new pass. */
};
/* Additional information about the plugin. Used by --help and --version. */
struct plugin_info

View File

@ -437,11 +437,11 @@ register_dump_files (struct opt_pass *pass,int properties)
register_dump_files_1 (pass, properties);
}
/* Add a pass to the pass list. Duplicate the pass if it's already
in the list. */
/* Look at the static_pass_number and duplicate the pass
if it is already added to a list. */
static struct opt_pass **
next_pass_1 (struct opt_pass **list, struct opt_pass *pass)
static struct opt_pass *
make_pass_instance (struct opt_pass *pass, bool track_duplicates)
{
/* A nonzero static_pass_number indicates that the
pass is already in the list. */
@ -459,25 +459,193 @@ next_pass_1 (struct opt_pass **list, struct opt_pass *pass)
and so it should rename the dump file. The first instance will
be -1, and be number of duplicates = -static_pass_number - 1.
Subsequent instances will be > 0 and just the duplicate number. */
if (pass->name)
if (pass->name || track_duplicates)
{
pass->static_pass_number -= 1;
new_pass->static_pass_number = -pass->static_pass_number;
}
*list = new_pass;
return new_pass;
}
else
{
pass->todo_flags_start |= TODO_mark_first_instance;
pass->static_pass_number = -1;
*list = pass;
}
return &(*list)->next;
}
return pass;
}
/* Add a pass to the pass list. Duplicate the pass if it's already
in the list. */
static struct opt_pass **
next_pass_1 (struct opt_pass **list, struct opt_pass *pass)
{
*list = make_pass_instance (pass, false);
return &(*list)->next;
}
/* List node for an inserted pass instance. We need to keep track of all
the newly-added pass instances (with 'added_pass_nodes' defined below)
so that we can register their dump files after pass-positioning is finished.
Registering dumping files needs to be post-processed or the
static_pass_number of the opt_pass object would be modified and mess up
the dump file names of future pass instances to be added. */
struct pass_list_node
{
struct opt_pass *pass;
struct pass_list_node *next;
};
static struct pass_list_node *added_pass_nodes = NULL;
static struct pass_list_node *prev_added_pass_node;
/* Insert the pass at the proper position. Return true if the pass
is successfully added.
NEW_PASS_INFO - new pass to be inserted
PASS_LIST - root of the pass list to insert the new pass to */
static bool
position_pass (struct register_pass_info *new_pass_info,
struct opt_pass **pass_list)
{
struct opt_pass *pass = *pass_list, *prev_pass = NULL;
bool success = false;
for ( ; pass; prev_pass = pass, pass = pass->next)
{
/* Check if the current pass is of the same type as the new pass and
matches the name and the instance number of the reference pass. */
if (pass->type == new_pass_info->pass->type
&& pass->name
&& !strcmp (pass->name, new_pass_info->reference_pass_name)
&& ((new_pass_info->ref_pass_instance_number == 0)
|| (new_pass_info->ref_pass_instance_number ==
pass->static_pass_number)
|| (new_pass_info->ref_pass_instance_number == 1
&& pass->todo_flags_start & TODO_mark_first_instance)))
{
struct opt_pass *new_pass;
struct pass_list_node *new_pass_node;
new_pass = make_pass_instance (new_pass_info->pass, true);
/* Insert the new pass instance based on the positioning op. */
switch (new_pass_info->pos_op)
{
case PASS_POS_INSERT_AFTER:
new_pass->next = pass->next;
pass->next = new_pass;
/* Skip newly inserted pass to avoid repeated
insertions in the case where the new pass and the
existing one have the same name. */
pass = new_pass;
break;
case PASS_POS_INSERT_BEFORE:
new_pass->next = pass;
if (prev_pass)
prev_pass->next = new_pass;
else
*pass_list = new_pass;
break;
case PASS_POS_REPLACE:
new_pass->next = pass->next;
if (prev_pass)
prev_pass->next = new_pass;
else
*pass_list = new_pass;
new_pass->sub = pass->sub;
new_pass->tv_id = pass->tv_id;
pass = new_pass;
break;
default:
error ("Invalid pass positioning operation");
return false;
}
/* Save the newly added pass (instance) in the added_pass_nodes
list so that we can register its dump file later. Note that
we cannot register the dump file now because doing so will modify
the static_pass_number of the opt_pass object and therefore
mess up the dump file name of future instances. */
new_pass_node = XCNEW (struct pass_list_node);
new_pass_node->pass = new_pass;
if (!added_pass_nodes)
added_pass_nodes = new_pass_node;
else
prev_added_pass_node->next = new_pass_node;
prev_added_pass_node = new_pass_node;
success = true;
}
if (pass->sub && position_pass (new_pass_info, &pass->sub))
success = true;
}
return success;
}
/* Hooks a new pass into the pass lists.
PASS_INFO - pass information that specifies the opt_pass object,
reference pass, instance number, and how to position
the pass */
void
register_pass (struct register_pass_info *pass_info)
{
if (!pass_info->pass)
{
gcc_unreachable ();
}
if (!pass_info->reference_pass_name)
{
gcc_unreachable ();
}
/* Try to insert the new pass to the pass lists. We need to check all
three lists as the reference pass could be in one (or all) of them. */
if (!position_pass (pass_info, &all_lowering_passes)
&& !position_pass (pass_info, &all_ipa_passes)
&& !position_pass (pass_info, &all_passes))
gcc_unreachable ();
else
{
/* OK, we have successfully inserted the new pass. We need to register
the dump files for the newly added pass and its duplicates (if any).
Because the registration of plugin/backend passes happens after the
command-line options are parsed, the options that specify single
pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
passes. Therefore we currently can only enable dumping of
new passes when the 'dump-all' flags (e.g. -fdump-tree-all)
are specified. While doing so, we also delete the pass_list_node
objects created during pass positioning. */
while (added_pass_nodes)
{
struct pass_list_node *next_node = added_pass_nodes->next;
enum tree_dump_index tdi;
register_one_dump_file (added_pass_nodes->pass);
if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS
|| added_pass_nodes->pass->type == IPA_PASS)
tdi = TDI_ipa_all;
else if (added_pass_nodes->pass->type == GIMPLE_PASS)
tdi = TDI_tree_all;
else
tdi = TDI_rtl_all;
/* Check if dump-all flag is specified. */
if (get_dump_file_info (tdi)->state)
get_dump_file_info (added_pass_nodes->pass->static_pass_number)
->state = get_dump_file_info (tdi)->state;
XDELETE (added_pass_nodes);
added_pass_nodes = next_node;
}
}
}
/* Construct the pass tree. The sequencing of passes is driven by
the cgraph routines:

View File

@ -78,20 +78,6 @@ struct callback_info
/* An array of lists of 'callback_info' objects indexed by the event id. */
static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
/* List node for an inserted pass instance. We need to keep track of all
the newly-added pass instances (with 'added_pass_nodes' defined below)
so that we can register their dump files after pass-positioning is finished.
Registering dumping files needs to be post-processed or the
static_pass_number of the opt_pass object would be modified and mess up
the dump file names of future pass instances to be added. */
struct pass_list_node
{
struct opt_pass *pass;
struct pass_list_node *next;
};
static struct pass_list_node *added_pass_nodes = NULL;
static struct pass_list_node *prev_added_pass_node;
#ifdef ENABLE_PLUGIN
/* Each plugin should define an initialization function with exactly
@ -287,179 +273,6 @@ parse_plugin_arg_opt (const char *arg)
XDELETEVEC (name);
}
/* Insert the plugin pass at the proper position. Return true if the pass
is successfully added.
PLUGIN_PASS_INFO - new pass to be inserted
PASS_LIST - root of the pass list to insert the new pass to */
static bool
position_pass (struct plugin_pass *plugin_pass_info,
struct opt_pass **pass_list)
{
struct opt_pass *pass = *pass_list, *prev_pass = NULL;
bool success = false;
for ( ; pass; prev_pass = pass, pass = pass->next)
{
/* Check if the current pass is of the same type as the new pass and
matches the name and the instance number of the reference pass. */
if (pass->type == plugin_pass_info->pass->type
&& pass->name
&& !strcmp (pass->name, plugin_pass_info->reference_pass_name)
&& ((plugin_pass_info->ref_pass_instance_number == 0)
|| (plugin_pass_info->ref_pass_instance_number ==
pass->static_pass_number)
|| (plugin_pass_info->ref_pass_instance_number == 1
&& pass->todo_flags_start & TODO_mark_first_instance)))
{
struct opt_pass *new_pass = plugin_pass_info->pass;
struct pass_list_node *new_pass_node;
/* The following code (if-statement) is adopted from next_pass_1. */
if (new_pass->static_pass_number)
{
new_pass = XNEW (struct opt_pass);
memcpy (new_pass, plugin_pass_info->pass, sizeof (*new_pass));
new_pass->next = NULL;
new_pass->todo_flags_start &= ~TODO_mark_first_instance;
plugin_pass_info->pass->static_pass_number -= 1;
new_pass->static_pass_number =
-plugin_pass_info->pass->static_pass_number;
}
else
{
new_pass->todo_flags_start |= TODO_mark_first_instance;
new_pass->static_pass_number = -1;
}
/* Insert the new pass instance based on the positioning op. */
switch (plugin_pass_info->pos_op)
{
case PASS_POS_INSERT_AFTER:
new_pass->next = pass->next;
pass->next = new_pass;
/* Skip newly inserted pass to avoid repeated
insertions in the case where the new pass and the
existing one have the same name. */
pass = new_pass;
break;
case PASS_POS_INSERT_BEFORE:
new_pass->next = pass;
if (prev_pass)
prev_pass->next = new_pass;
else
*pass_list = new_pass;
break;
case PASS_POS_REPLACE:
new_pass->next = pass->next;
if (prev_pass)
prev_pass->next = new_pass;
else
*pass_list = new_pass;
new_pass->sub = pass->sub;
new_pass->tv_id = pass->tv_id;
pass = new_pass;
break;
default:
error ("Invalid pass positioning operation");
return false;
}
/* Save the newly added pass (instance) in the added_pass_nodes
list so that we can register its dump file later. Note that
we cannot register the dump file now because doing so will modify
the static_pass_number of the opt_pass object and therefore
mess up the dump file name of future instances. */
new_pass_node = XCNEW (struct pass_list_node);
new_pass_node->pass = new_pass;
if (!added_pass_nodes)
added_pass_nodes = new_pass_node;
else
prev_added_pass_node->next = new_pass_node;
prev_added_pass_node = new_pass_node;
success = true;
}
if (pass->sub && position_pass (plugin_pass_info, &pass->sub))
success = true;
}
return success;
}
/* Hook into the pass lists (trees) a new pass registered by a plugin.
PLUGIN_NAME - display name for the plugin
PASS_INFO - plugin pass information that specifies the opt_pass object,
reference pass, instance number, and how to position
the pass */
static void
register_pass (const char *plugin_name, struct plugin_pass *pass_info)
{
if (!pass_info->pass)
{
error ("No pass specified when registering a new pass in plugin %s",
plugin_name);
return;
}
if (!pass_info->reference_pass_name)
{
error ("No reference pass specified for positioning the pass "
" from plugin %s", plugin_name);
return;
}
/* Try to insert the new pass to the pass lists. We need to check all
three lists as the reference pass could be in one (or all) of them. */
if (!position_pass (pass_info, &all_lowering_passes)
&& !position_pass (pass_info, &all_ipa_passes)
&& !position_pass (pass_info, &all_passes))
error ("Failed to position pass %s registered by plugin %s. "
"Cannot find the (specified instance of) reference pass %s",
pass_info->pass->name, plugin_name, pass_info->reference_pass_name);
else
{
/* OK, we have successfully inserted the new pass. We need to register
the dump files for the newly added pass and its duplicates (if any).
Because the registration of plugin passes happens after the
command-line options are parsed, the options that specify single
pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
plugin passes. Therefore we currently can only enable dumping of
new plugin passes when the 'dump-all' flags (e.g. -fdump-tree-all)
are specified. While doing so, we also delete the pass_list_node
objects created during pass positioning. */
while (added_pass_nodes)
{
struct pass_list_node *next_node = added_pass_nodes->next;
enum tree_dump_index tdi;
register_one_dump_file (added_pass_nodes->pass);
if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS
|| added_pass_nodes->pass->type == IPA_PASS)
tdi = TDI_ipa_all;
else if (added_pass_nodes->pass->type == GIMPLE_PASS)
tdi = TDI_tree_all;
else
tdi = TDI_rtl_all;
/* Check if dump-all flag is specified. */
if (get_dump_file_info (tdi)->state)
get_dump_file_info (added_pass_nodes->pass->static_pass_number)
->state = get_dump_file_info (tdi)->state;
XDELETE (added_pass_nodes);
added_pass_nodes = next_node;
}
}
}
/* Register additional plugin information. NAME is the name passed to
plugin_init. INFO is the information that should be registered. */
@ -490,7 +303,7 @@ register_callback (const char *plugin_name,
{
case PLUGIN_PASS_MANAGER_SETUP:
gcc_assert (!callback);
register_pass (plugin_name, (struct plugin_pass *) user_data);
register_pass ((struct register_pass_info *) user_data);
break;
case PLUGIN_INFO:
gcc_assert (!callback);

View File

@ -308,6 +308,27 @@ struct dump_file_info
#define TODO_verify_all \
(TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts)
/* Register pass info. */
enum pass_positioning_ops
{
PASS_POS_INSERT_AFTER, /* Insert after the reference pass. */
PASS_POS_INSERT_BEFORE, /* Insert before the reference pass. */
PASS_POS_REPLACE /* Replace the reference pass. */
};
struct register_pass_info
{
struct opt_pass *pass; /* New pass to register. */
const char *reference_pass_name; /* Name of the reference pass for hooking
up the new pass. */
int ref_pass_instance_number; /* Insert the pass at the specified
instance number of the reference pass.
Do it for every instance if it is 0. */
enum pass_positioning_ops pos_op; /* how to insert the new pass. */
};
extern void tree_lowering_passes (tree decl);
extern struct gimple_opt_pass pass_mudflap_1;
@ -545,6 +566,7 @@ extern void print_current_pass (FILE *);
extern void debug_pass (void);
extern void register_one_dump_file (struct opt_pass *);
extern bool function_called_by_processed_nodes_p (void);
extern void register_pass (struct register_pass_info *);
/* Set to true if the pass is called the first time during compilation of the
current function. Note that using this information in the optimization