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:
parent
ef6ed66d16
commit
b80b0fd9c7
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
192
gcc/passes.c
192
gcc/passes.c
|
@ -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:
|
||||
|
|
189
gcc/plugin.c
189
gcc/plugin.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue