Fix -fopt-info for plugin passes
Attempts to dump via -fopt-info from a plugin pass fail, due to the dfi->alt_state for such passes never being set. This is because the -fopt-info options were being set up per-pass during option-parsing (via gcc::dump_manager::opt_info_enable_passes), but this data was not retained or used it for passes created later (for plugins and target-specific passes). This patch fixes the issue by storing the -fopt-info options into gcc::dump_manager, refactoring the dfi-setup code out of opt_info_enable_passes, and reusing it for such passes, fixing the issue. The patch adds a demo plugin to test that dumping from a plugin works. gcc/ChangeLog: * dumpfile.c (gcc::dump_manager::dump_manager): Initialize new fields. (gcc::dump_manager::~dump_manager): Free m_optinfo_filename. (gcc::dump_manager::register_pass): New member function, adapted from loop body in gcc::pass_manager::register_pass, adding a call to update_dfi_for_opt_info. (gcc::dump_manager::opt_info_enable_passes): Store the -fopt-info options into the new fields. Move the loop bodies into... (gcc::dump_manager::update_dfi_for_opt_info): ...this new member function. * dumpfile.h (struct opt_pass): New forward decl. (gcc::dump_manager::register_pass): New decl. (gcc::dump_manager::update_dfi_for_opt_info): New decl. (class gcc::dump_manager): Add fields "m_optgroup_flags", "m_optinfo_flags", and "m_optinfo_filename". * passes.c (gcc::pass_manager::register_pass): Move all of the dump-handling code to gcc::dump_manager::register_pass. gcc/testsuite/ChangeLog: * gcc.dg/plugin/dump-1.c: New test. * gcc.dg/plugin/dump_plugin.c: New test plugin. * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above. From-SVN: r264844
This commit is contained in:
parent
c19bc1a083
commit
5d98e5a6bc
|
@ -1,3 +1,24 @@
|
|||
2018-10-04 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* dumpfile.c (gcc::dump_manager::dump_manager): Initialize new
|
||||
fields.
|
||||
(gcc::dump_manager::~dump_manager): Free m_optinfo_filename.
|
||||
(gcc::dump_manager::register_pass): New member function, adapted
|
||||
from loop body in gcc::pass_manager::register_pass, adding a
|
||||
call to update_dfi_for_opt_info.
|
||||
(gcc::dump_manager::opt_info_enable_passes): Store the
|
||||
-fopt-info options into the new fields. Move the loop
|
||||
bodies into...
|
||||
(gcc::dump_manager::update_dfi_for_opt_info): ...this new member
|
||||
function.
|
||||
* dumpfile.h (struct opt_pass): New forward decl.
|
||||
(gcc::dump_manager::register_pass): New decl.
|
||||
(gcc::dump_manager::update_dfi_for_opt_info): New decl.
|
||||
(class gcc::dump_manager): Add fields "m_optgroup_flags",
|
||||
"m_optinfo_flags", and "m_optinfo_filename".
|
||||
* passes.c (gcc::pass_manager::register_pass): Move all of the
|
||||
dump-handling code to gcc::dump_manager::register_pass.
|
||||
|
||||
2018-10-04 Peter Bergner <bergner@linux.ibm.com>
|
||||
|
||||
PR rtl-optimization/87466
|
||||
|
|
120
gcc/dumpfile.c
120
gcc/dumpfile.c
|
@ -177,12 +177,16 @@ gcc::dump_manager::dump_manager ():
|
|||
m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
|
||||
m_extra_dump_files (NULL),
|
||||
m_extra_dump_files_in_use (0),
|
||||
m_extra_dump_files_alloced (0)
|
||||
m_extra_dump_files_alloced (0),
|
||||
m_optgroup_flags (OPTGROUP_NONE),
|
||||
m_optinfo_flags (TDF_NONE),
|
||||
m_optinfo_filename (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
gcc::dump_manager::~dump_manager ()
|
||||
{
|
||||
free (m_optinfo_filename);
|
||||
for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
|
||||
{
|
||||
dump_file_info *dfi = &m_extra_dump_files[i];
|
||||
|
@ -1512,6 +1516,50 @@ dump_flag_name (int phase) const
|
|||
return dfi->swtch;
|
||||
}
|
||||
|
||||
/* Handle -fdump-* and -fopt-info for a pass added after
|
||||
command-line options are parsed (those from plugins and
|
||||
those from backends).
|
||||
|
||||
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. This is done here.
|
||||
|
||||
Similarly, the saved -fopt-info options are wired up to the new pass. */
|
||||
|
||||
void
|
||||
gcc::dump_manager::register_pass (opt_pass *pass)
|
||||
{
|
||||
gcc_assert (pass);
|
||||
|
||||
register_one_dump_file (pass);
|
||||
|
||||
dump_file_info *pass_dfi = get_dump_file_info (pass->static_pass_number);
|
||||
gcc_assert (pass_dfi);
|
||||
|
||||
enum tree_dump_index tdi;
|
||||
if (pass->type == SIMPLE_IPA_PASS
|
||||
|| pass->type == IPA_PASS)
|
||||
tdi = TDI_ipa_all;
|
||||
else if (pass->type == GIMPLE_PASS)
|
||||
tdi = TDI_tree_all;
|
||||
else
|
||||
tdi = TDI_rtl_all;
|
||||
const dump_file_info *tdi_dfi = get_dump_file_info (tdi);
|
||||
gcc_assert (tdi_dfi);
|
||||
|
||||
/* Check if dump-all flag is specified. */
|
||||
if (tdi_dfi->pstate)
|
||||
{
|
||||
pass_dfi->pstate = tdi_dfi->pstate;
|
||||
pass_dfi->pflags = tdi_dfi->pflags;
|
||||
}
|
||||
|
||||
update_dfi_for_opt_info (pass_dfi);
|
||||
}
|
||||
|
||||
/* Finish a tree dump for PHASE. STREAM is the stream created by
|
||||
dump_begin. */
|
||||
|
||||
|
@ -1587,47 +1635,47 @@ opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
|
|||
const char *filename)
|
||||
{
|
||||
int n = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
|
||||
{
|
||||
if ((dump_files[i].optgroup_flags & optgroup_flags))
|
||||
{
|
||||
const char *old_filename = dump_files[i].alt_filename;
|
||||
/* Since this file is shared among different passes, it
|
||||
should be opened in append mode. */
|
||||
dump_files[i].alt_state = 1;
|
||||
dump_files[i].alt_flags |= flags;
|
||||
n++;
|
||||
/* Override the existing filename. */
|
||||
if (filename)
|
||||
dump_files[i].alt_filename = xstrdup (filename);
|
||||
if (old_filename && filename != old_filename)
|
||||
free (CONST_CAST (char *, old_filename));
|
||||
}
|
||||
}
|
||||
m_optgroup_flags = optgroup_flags;
|
||||
m_optinfo_flags = flags;
|
||||
m_optinfo_filename = xstrdup (filename);
|
||||
|
||||
for (i = 0; i < m_extra_dump_files_in_use; i++)
|
||||
{
|
||||
if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
|
||||
{
|
||||
const char *old_filename = m_extra_dump_files[i].alt_filename;
|
||||
/* Since this file is shared among different passes, it
|
||||
should be opened in append mode. */
|
||||
m_extra_dump_files[i].alt_state = 1;
|
||||
m_extra_dump_files[i].alt_flags |= flags;
|
||||
n++;
|
||||
/* Override the existing filename. */
|
||||
if (filename)
|
||||
m_extra_dump_files[i].alt_filename = xstrdup (filename);
|
||||
if (old_filename && filename != old_filename)
|
||||
free (CONST_CAST (char *, old_filename));
|
||||
}
|
||||
}
|
||||
for (size_t i = TDI_none + 1; i < (size_t) TDI_end; i++)
|
||||
if (update_dfi_for_opt_info (&dump_files[i]))
|
||||
n++;
|
||||
|
||||
for (size_t i = 0; i < m_extra_dump_files_in_use; i++)
|
||||
if (update_dfi_for_opt_info (&m_extra_dump_files[i]))
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Use the saved -fopt-info options to update DFI.
|
||||
Return true if the dump is enabled. */
|
||||
|
||||
bool
|
||||
gcc::dump_manager::update_dfi_for_opt_info (dump_file_info *dfi) const
|
||||
{
|
||||
gcc_assert (dfi);
|
||||
|
||||
if (!(dfi->optgroup_flags & m_optgroup_flags))
|
||||
return false;
|
||||
|
||||
const char *old_filename = dfi->alt_filename;
|
||||
/* Since this file is shared among different passes, it
|
||||
should be opened in append mode. */
|
||||
dfi->alt_state = 1;
|
||||
dfi->alt_flags |= m_optinfo_flags;
|
||||
/* Override the existing filename. */
|
||||
if (m_optinfo_filename)
|
||||
dfi->alt_filename = xstrdup (m_optinfo_filename);
|
||||
if (old_filename && m_optinfo_filename != old_filename)
|
||||
free (CONST_CAST (char *, old_filename));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse ARG as a dump switch. Return nonzero if it is, and store the
|
||||
relevant details in the dump_files array. */
|
||||
|
||||
|
|
|
@ -566,6 +566,8 @@ extern void dump_combine_total_stats (FILE *);
|
|||
/* In cfghooks.c */
|
||||
extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
|
||||
|
||||
struct opt_pass;
|
||||
|
||||
namespace gcc {
|
||||
|
||||
/* A class for managing all of the various dump files used by the
|
||||
|
@ -634,6 +636,8 @@ public:
|
|||
const char *
|
||||
dump_flag_name (int phase) const;
|
||||
|
||||
void register_pass (opt_pass *pass);
|
||||
|
||||
private:
|
||||
|
||||
int
|
||||
|
@ -649,6 +653,8 @@ private:
|
|||
opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
|
||||
const char *filename);
|
||||
|
||||
bool update_dfi_for_opt_info (dump_file_info *dfi) const;
|
||||
|
||||
private:
|
||||
|
||||
/* Dynamically registered dump files and switches. */
|
||||
|
@ -657,6 +663,12 @@ private:
|
|||
size_t m_extra_dump_files_in_use;
|
||||
size_t m_extra_dump_files_alloced;
|
||||
|
||||
/* Stored values from -fopt-info, for handling passes created after
|
||||
option-parsing (by backends and by plugins). */
|
||||
optgroup_flags_t m_optgroup_flags;
|
||||
dump_flags_t m_optinfo_flags;
|
||||
char *m_optinfo_filename;
|
||||
|
||||
/* Grant access to dump_enable_all. */
|
||||
friend bool ::enable_rtl_dump_file (void);
|
||||
|
||||
|
|
30
gcc/passes.c
30
gcc/passes.c
|
@ -1404,7 +1404,6 @@ void
|
|||
pass_manager::register_pass (struct register_pass_info *pass_info)
|
||||
{
|
||||
bool all_instances, success;
|
||||
gcc::dump_manager *dumps = m_ctxt->get_dumps ();
|
||||
|
||||
/* The checks below could fail in buggy plugins. Existing GCC
|
||||
passes should never fail these checks, so we mention plugin in
|
||||
|
@ -1442,33 +1441,16 @@ pass_manager::register_pass (struct register_pass_info *pass_info)
|
|||
|
||||
/* 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
|
||||
While doing so, we also delete the pass_list_node
|
||||
objects created during pass positioning. */
|
||||
gcc::dump_manager *dumps = m_ctxt->get_dumps ();
|
||||
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 (dumps->get_dump_file_info (tdi)->pstate)
|
||||
{
|
||||
dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
|
||||
->pstate = dumps->get_dump_file_info (tdi)->pstate;
|
||||
dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
|
||||
->pflags = dumps->get_dump_file_info (tdi)->pflags;
|
||||
}
|
||||
|
||||
/* Handle -fdump-* and -fopt-info. */
|
||||
dumps->register_pass (added_pass_nodes->pass);
|
||||
|
||||
XDELETE (added_pass_nodes);
|
||||
added_pass_nodes = next_node;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2018-10-04 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/plugin/dump-1.c: New test.
|
||||
* gcc.dg/plugin/dump_plugin.c: New test plugin.
|
||||
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above.
|
||||
|
||||
2018-10-04 Peter Bergner <bergner@linux.ibm.com>
|
||||
|
||||
PR rtl-optimization/87466
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-fopt-info-note" } */
|
||||
|
||||
extern void test_string_literal (void);
|
||||
extern void test_tree (void);
|
||||
extern void test_gimple (int);
|
||||
extern void test_cgraph_node (void);
|
||||
extern void test_wide_int (void);
|
||||
extern void test_poly_int (void);
|
||||
extern void test_scopes (void);
|
||||
|
||||
void test_remarks (void)
|
||||
{
|
||||
test_string_literal (); /* { dg-message "test of dump for 'test_string_literal'" } */
|
||||
test_tree (); /* { dg-message "test of tree: 0" } */
|
||||
test_gimple (42); /* { dg-message "test of gimple: test_gimple \\(42\\);" } */
|
||||
test_cgraph_node (); /* { dg-message "test of callgraph node: test_cgraph_node/\[0-9\]+" } */
|
||||
test_wide_int (); /* { dg-message "test of wide int: 0" } */
|
||||
test_poly_int (); /* { dg-message "test of poly int: 42" } */
|
||||
|
||||
test_scopes (); /* { dg-line test_scopes_line } */
|
||||
/* { dg-message "=== outer scope ===" "" { target *-*-* } test_scopes_line } */
|
||||
/* { dg-message " at outer scope" "" { target *-*-* } test_scopes_line } */
|
||||
/* { dg-message " === middle scope ===" "" { target *-*-* } test_scopes_line } */
|
||||
/* { dg-message " at middle scope" "" { target *-*-* } test_scopes_line } */
|
||||
/* { dg-message " === innermost scope ===" "" { target *-*-* } test_scopes_line } */
|
||||
/* { dg-message " at innermost scope" "" { target *-*-* } test_scopes_line } */
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* Plugin for testing dumpfile.c. */
|
||||
|
||||
#include "gcc-plugin.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
#include "tree-pass.h"
|
||||
#include "intl.h"
|
||||
#include "plugin-version.h"
|
||||
#include "diagnostic.h"
|
||||
#include "context.h"
|
||||
#include "optinfo.h"
|
||||
#include "gimple.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "cgraph.h"
|
||||
|
||||
int plugin_is_GPL_compatible;
|
||||
|
||||
const pass_data pass_data_test_dumping =
|
||||
{
|
||||
GIMPLE_PASS, /* type */
|
||||
"test_dumping", /* name */
|
||||
OPTGROUP_LOOP, /* optinfo_flags */
|
||||
TV_NONE, /* tv_id */
|
||||
PROP_ssa, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
0, /* todo_flags_finish */
|
||||
};
|
||||
|
||||
class pass_test_dumping : public gimple_opt_pass
|
||||
{
|
||||
public:
|
||||
pass_test_dumping (gcc::context *ctxt)
|
||||
: gimple_opt_pass (pass_data_test_dumping, ctxt)
|
||||
{}
|
||||
|
||||
/* opt_pass methods: */
|
||||
bool gate (function *) { return true; }
|
||||
virtual unsigned int execute (function *);
|
||||
|
||||
}; // class pass_test_dumping
|
||||
|
||||
unsigned int
|
||||
pass_test_dumping::execute (function *fun)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
if (!dump_enabled_p ())
|
||||
return 0;
|
||||
|
||||
FOR_ALL_BB_FN (bb, fun)
|
||||
for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
|
||||
!gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
gcall *call = dyn_cast <gcall *> (stmt);
|
||||
if (!call)
|
||||
continue;
|
||||
tree callee_decl = gimple_call_fndecl (call);
|
||||
if (!callee_decl)
|
||||
continue;
|
||||
tree callee_name = DECL_NAME (callee_decl);
|
||||
if (!callee_name)
|
||||
continue;
|
||||
const char *callee = IDENTIFIER_POINTER (callee_name);
|
||||
|
||||
/* Various dumping tests, done at callsites,
|
||||
controlled by the callee name. */
|
||||
if (strcmp (callee, "test_string_literal") == 0)
|
||||
dump_printf_loc (MSG_NOTE, stmt, "test of dump for %qs\n",
|
||||
callee);
|
||||
else if (strcmp (callee, "test_tree") == 0)
|
||||
dump_printf_loc (MSG_NOTE, stmt, "test of tree: %T\n",
|
||||
integer_zero_node);
|
||||
else if (strcmp (callee, "test_gimple") == 0)
|
||||
dump_printf_loc (MSG_NOTE, stmt, "test of gimple: %G", stmt);
|
||||
else if (strcmp (callee, "test_cgraph_node") == 0)
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, stmt, "test of callgraph node: ");
|
||||
dump_symtab_node (MSG_NOTE, cgraph_node::get (callee_decl));
|
||||
dump_printf (MSG_NOTE, "\n");
|
||||
}
|
||||
else if (strcmp (callee, "test_wide_int") == 0)
|
||||
{
|
||||
HOST_WIDE_INT val = 0;
|
||||
dump_printf_loc (MSG_NOTE, stmt,
|
||||
"test of wide int: " HOST_WIDE_INT_PRINT_DEC "\n",
|
||||
val);
|
||||
}
|
||||
else if (strcmp (callee, "test_poly_int") == 0)
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, stmt, "test of poly int: ");
|
||||
dump_dec (MSG_NOTE, poly_int64 (42));
|
||||
dump_printf (MSG_NOTE, "\n");
|
||||
}
|
||||
else if (strcmp (callee, "test_scopes") == 0)
|
||||
{
|
||||
AUTO_DUMP_SCOPE ("outer scope", stmt);
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, stmt, "at outer scope\n");
|
||||
AUTO_DUMP_SCOPE ("middle scope", stmt);
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, stmt, "at middle scope\n");
|
||||
AUTO_DUMP_SCOPE ("innermost scope", stmt);
|
||||
dump_printf_loc (MSG_NOTE, stmt, "at innermost scope\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gimple_opt_pass *
|
||||
make_pass_test_dumping (gcc::context *ctxt)
|
||||
{
|
||||
return new pass_test_dumping (ctxt);
|
||||
}
|
||||
|
||||
int
|
||||
plugin_init (struct plugin_name_args *plugin_info,
|
||||
struct plugin_gcc_version *version)
|
||||
{
|
||||
struct register_pass_info pass_info;
|
||||
const char *plugin_name = plugin_info->base_name;
|
||||
int argc = plugin_info->argc;
|
||||
struct plugin_argument *argv = plugin_info->argv;
|
||||
|
||||
if (!plugin_default_version_check (version, &gcc_version))
|
||||
return 1;
|
||||
|
||||
pass_info.pass = make_pass_test_dumping (g);
|
||||
pass_info.reference_pass_name = "ssa";
|
||||
pass_info.ref_pass_instance_number = 1;
|
||||
pass_info.pos_op = PASS_POS_INSERT_AFTER;
|
||||
register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
|
||||
&pass_info);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -101,6 +101,8 @@ set plugin_test_list [list \
|
|||
must-tail-call-2.c } \
|
||||
{ expensive_selftests_plugin.c \
|
||||
expensive-selftests-1.c } \
|
||||
{ dump_plugin.c \
|
||||
dump-1.c } \
|
||||
]
|
||||
|
||||
foreach plugin_test $plugin_test_list {
|
||||
|
|
Loading…
Reference in New Issue