Eliminate global state from -fsave-optimization-record

As work towards fixing PR tree-optimization/87025, this patch
eliminates global state from optinfo-emit-json.cc in favor
of adding an optional m_json_writer field to dump_context,
replacing the m_forcibly_enable_optinfo flag.

This allows for writing selftests for the interaction of the
JSON-building code with the dumpfile.c code.
In particular, the existing selftest that created optinfo
instances now exercise the JSON-building code (although no
JSON is actually written out).

The patch also simplifies the layering by replacing optinfo::emit ()
with dump_context::emit_optinfo, so that dump_context has
responsibility for keeping track of dump destinations.

gcc/ChangeLog:
	PR tree-optimization/87025
	* dump-context.h: Include "optinfo.h".
	(class optrecord_json_writer): New forward decl.
	(dump_context::forcibly_enable_optinfo_p): Delete.
	(dump_context::optinfo_enabled_p): New member function.
	(dump_context::optimization_records_enabled_p): New member
	function.
	(dump_context::set_json_writer): New member function.
	(dump_context::emit_optinfo): New member function.
	(dump_context::m_forcibly_enable_optinfo): Delete.
	(dump_context::m_json_writer): New member data.
	* dumpfile.c (dump_context::set_json_writer): New member function.
	(dump_context::finish_any_json_writer): New member function.
	(dump_context::end_scope): Replace call to
	optimization_records_maybe_pop_dump_scope with call to
	m_json_writer->pop_scope.
	(dump_context::optinfo_enabled_p): New member function.
	(dump_context::end_any_optinfo): Replace call to optinfo::emit with call
	to dump_context::emit_optinfo.
	(dump_context::emit_optinfo): New member function.
	(temp_dump_context::temp_dump_context): Replace
	m_forcibly_enable_optinfo with call to set_json_writer.
	(temp_dump_context::~temp_dump_context): Clean up any json writer.
	* optinfo-emit-json.cc (class optrecord_json_writer): Move to
	optinfo-emit-json.h
	(the_json_writer): Delete.
	(optimization_records_start): Delete.
	(optimization_records_finish): Delete.
	(optimization_records_enabled_p): Delete, in favor of
	dump_context::optimization_records_enabled_p.
	(optimization_records_maybe_record_optinfo): Delete.
	(optimization_records_maybe_pop_dump_scope): Delete.
	* optinfo-emit-json.h: Include "json.h".  Delete forward
	decl of opt_pass.
	(optimization_records_start): Delete.
	(optimization_records_finish): Delete.
	(optimization_records_enabled_p): Delete.
	(optimization_records_maybe_record_optinfo): Delete.
	(optimization_records_maybe_pop_dump_scope): Delete.
	(class optrecord_json_writer): Move here from
	optinfo-emit-json.cc.
	* optinfo.cc (optinfo::emit_for_opt_problem): Replace call
	to optinfo::emit with call to dump_context::emit_optinfo.
	(optinfo::emit): Delete, in favor of dump_context::emit_optinfo.
	(optinfo_enabled_p): Delete, in favor of
	dump_context::optinfo_enabled_p.
	(optinfo_wants_inlining_info_p): Update for conversion o
	optimization_records_enabled_p to a member function of
	dump_context.
	* optinfo.h (optinfo_enabled_p): Delete, in favor of
	dump_context::optinfo_enabled_p.
	(optinfo::emit): Delete, in favor of dump_context::emit_optinfo.
	* toplev.c: Include "dump-context.h".
	(compile_file): Replace call to optimization_records_finish with
	dump_context::finish_any_json_writer.
	(do_compile): Replace call to optimization_records_start with
	conditionally creating a optrecord_json_writer for the
	dump_context.

From-SVN: r266279
This commit is contained in:
David Malcolm 2018-11-19 16:31:03 +00:00 committed by David Malcolm
parent 4fea820523
commit 8d1af51684
8 changed files with 167 additions and 149 deletions

View File

@ -1,3 +1,64 @@
2018-11-19 David Malcolm <dmalcolm@redhat.com>
PR tree-optimization/87025
* dump-context.h: Include "optinfo.h".
(class optrecord_json_writer): New forward decl.
(dump_context::forcibly_enable_optinfo_p): Delete.
(dump_context::optinfo_enabled_p): New member function.
(dump_context::optimization_records_enabled_p): New member
function.
(dump_context::set_json_writer): New member function.
(dump_context::emit_optinfo): New member function.
(dump_context::m_forcibly_enable_optinfo): Delete.
(dump_context::m_json_writer): New member data.
* dumpfile.c (dump_context::set_json_writer): New member function.
(dump_context::finish_any_json_writer): New member function.
(dump_context::end_scope): Replace call to
optimization_records_maybe_pop_dump_scope with call to
m_json_writer->pop_scope.
(dump_context::optinfo_enabled_p): New member function.
(dump_context::end_any_optinfo): Replace call to optinfo::emit with call
to dump_context::emit_optinfo.
(dump_context::emit_optinfo): New member function.
(temp_dump_context::temp_dump_context): Replace
m_forcibly_enable_optinfo with call to set_json_writer.
(temp_dump_context::~temp_dump_context): Clean up any json writer.
* optinfo-emit-json.cc (class optrecord_json_writer): Move to
optinfo-emit-json.h
(the_json_writer): Delete.
(optimization_records_start): Delete.
(optimization_records_finish): Delete.
(optimization_records_enabled_p): Delete, in favor of
dump_context::optimization_records_enabled_p.
(optimization_records_maybe_record_optinfo): Delete.
(optimization_records_maybe_pop_dump_scope): Delete.
* optinfo-emit-json.h: Include "json.h". Delete forward
decl of opt_pass.
(optimization_records_start): Delete.
(optimization_records_finish): Delete.
(optimization_records_enabled_p): Delete.
(optimization_records_maybe_record_optinfo): Delete.
(optimization_records_maybe_pop_dump_scope): Delete.
(class optrecord_json_writer): Move here from
optinfo-emit-json.cc.
* optinfo.cc (optinfo::emit_for_opt_problem): Replace call
to optinfo::emit with call to dump_context::emit_optinfo.
(optinfo::emit): Delete, in favor of dump_context::emit_optinfo.
(optinfo_enabled_p): Delete, in favor of
dump_context::optinfo_enabled_p.
(optinfo_wants_inlining_info_p): Update for conversion o
optimization_records_enabled_p to a member function of
dump_context.
* optinfo.h (optinfo_enabled_p): Delete, in favor of
dump_context::optinfo_enabled_p.
(optinfo::emit): Delete, in favor of dump_context::emit_optinfo.
* toplev.c: Include "dump-context.h".
(compile_file): Replace call to optimization_records_finish with
dump_context::finish_any_json_writer.
(do_compile): Replace call to optimization_records_start with
conditionally creating a optrecord_json_writer for the
dump_context.
2018-11-19 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/88071

View File

@ -25,7 +25,9 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "pretty-print.h"
#include "selftest.h"
#include "optinfo.h"
class optrecord_json_writer;
namespace selftest { class temp_dump_context; }
/* A class for handling the various dump_* calls.
@ -95,14 +97,21 @@ class dump_context
void begin_scope (const char *name, const dump_location_t &loc);
void end_scope ();
/* For use in selftests; if true then optinfo_enabled_p is true. */
bool forcibly_enable_optinfo_p () const
/* Should optinfo instances be created?
All creation of optinfos should be guarded by this predicate.
Return true if any optinfo destinations are active. */
bool optinfo_enabled_p () const;
bool optimization_records_enabled_p () const
{
return m_forcibly_enable_optinfo;
return m_json_writer != NULL;
}
void set_json_writer (optrecord_json_writer *writer);
void finish_any_json_writer ();
void end_any_optinfo ();
void emit_optinfo (const optinfo *info);
void emit_item (optinfo_item *item, dump_flags_t dump_kind);
bool apply_dump_filter_p (dump_flags_t dump_kind, dump_flags_t filter) const;
@ -111,9 +120,6 @@ class dump_context
optinfo &ensure_pending_optinfo ();
optinfo &begin_next_optinfo (const dump_location_t &loc);
/* For use in selftests; if true then optinfo_enabled_p is true. */
bool m_forcibly_enable_optinfo;
/* The current nesting depth of dump scopes, for showing nesting
via indentation). */
unsigned int m_scope_depth;
@ -122,6 +128,10 @@ class dump_context
if any. */
optinfo *m_pending;
/* If -fsave-optimization-record is enabled, the heap-allocated JSON writer
instance, otherwise NULL. */
optrecord_json_writer *m_json_writer;
/* For use in selftests: if non-NULL, then items are to be printed
to this, using the given flags. */
pretty_printer *m_test_pp;

View File

@ -515,6 +515,28 @@ dump_context::~dump_context ()
delete m_pending;
}
void
dump_context::set_json_writer (optrecord_json_writer *writer)
{
delete m_json_writer;
m_json_writer = writer;
}
/* Perform cleanup activity for -fsave-optimization-record.
Currently, the file is written out here in one go, before cleaning
up. */
void
dump_context::finish_any_json_writer ()
{
if (!m_json_writer)
return;
m_json_writer->write ();
delete m_json_writer;
m_json_writer = NULL;
}
/* Update the "dumps_are_enabled" global; to be called whenever dump_file
or alt_dump_file change, or when changing dump_context in selftests. */
@ -1121,7 +1143,19 @@ dump_context::end_scope ()
{
end_any_optinfo ();
m_scope_depth--;
optimization_records_maybe_pop_dump_scope ();
if (m_json_writer)
m_json_writer->pop_scope ();
}
/* Should optinfo instances be created?
All creation of optinfos should be guarded by this predicate.
Return true if any optinfo destinations are active. */
bool
dump_context::optinfo_enabled_p () const
{
return (optimization_records_enabled_p ());
}
/* Return the optinfo currently being accumulated, creating one if
@ -1154,11 +1188,23 @@ void
dump_context::end_any_optinfo ()
{
if (m_pending)
m_pending->emit ();
emit_optinfo (m_pending);
delete m_pending;
m_pending = NULL;
}
/* Emit the optinfo to all of the "non-immediate" destinations
(emission to "immediate" destinations is done by
dump_context::emit_item). */
void
dump_context::emit_optinfo (const optinfo *info)
{
/* -fsave-optimization-record. */
if (m_json_writer)
m_json_writer->add_record (info);
}
/* Emit ITEM to all item destinations (those that don't require
consolidation into optinfo instances). */
@ -2004,7 +2050,8 @@ temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
m_saved (&dump_context ().get ())
{
dump_context::s_current = &m_context;
m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
if (forcibly_enable_optinfo)
m_context.set_json_writer (new optrecord_json_writer ());
/* Conditionally enable the test dump, so that we can verify both the
dump_enabled_p and the !dump_enabled_p cases in selftests. */
if (forcibly_enable_dumping)
@ -2020,6 +2067,8 @@ temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo,
temp_dump_context::~temp_dump_context ()
{
m_context.set_json_writer (NULL);
dump_context::s_current = m_saved;
dump_context::get ().refresh_dumps_are_enabled ();

View File

@ -47,38 +47,6 @@ along with GCC; see the file COPYING3. If not see
#include "dump-context.h"
#include <zlib.h>
/* A class for writing out optimization records in JSON format. */
class optrecord_json_writer
{
public:
optrecord_json_writer ();
~optrecord_json_writer ();
void write () const;
void add_record (const optinfo *optinfo);
void pop_scope ();
void add_record (json::object *obj);
json::object *impl_location_to_json (dump_impl_location_t loc);
json::object *location_to_json (location_t loc);
json::object *profile_count_to_json (profile_count count);
json::string *get_id_value_for_pass (opt_pass *pass);
json::object *pass_to_json (opt_pass *pass);
json::value *inlining_chain_to_json (location_t loc);
json::object *optinfo_to_json (const optinfo *optinfo);
void add_pass_list (json::array *arr, opt_pass *pass);
private:
/* The root value for the JSON file.
Currently the JSON values are stored in memory, and flushed when the
compiler exits. It would probably be better to simply write out
the JSON as we go. */
json::array *m_root_tuple;
/* The currently open scopes, for expressing nested optimization records. */
auto_vec<json::array *> m_scopes;
};
/* optrecord_json_writer's ctor. Populate the top-level parts of the
in-memory JSON representation. */
@ -471,75 +439,6 @@ optrecord_json_writer::add_pass_list (json::array *arr, opt_pass *pass)
while (pass);
}
/* File-level interface to rest of compiler (to avoid exposing
class optrecord_json_writer outside of this file). */
static optrecord_json_writer *the_json_writer;
/* Perform startup activity for -fsave-optimization-record. */
void
optimization_records_start ()
{
/* Bail if recording not enabled. */
if (!flag_save_optimization_record)
return;
the_json_writer = new optrecord_json_writer ();
}
/* Perform cleanup activity for -fsave-optimization-record.
Currently, the file is written out here in one go, before cleaning
up. */
void
optimization_records_finish ()
{
/* Bail if recording not enabled. */
if (!the_json_writer)
return;
the_json_writer->write ();
delete the_json_writer;
the_json_writer = NULL;
}
/* Did the user request optimization records to be written out? */
bool
optimization_records_enabled_p ()
{
return the_json_writer != NULL;
}
/* If optimization records were requested, then add a record for OPTINFO
to the queue of records to be written. */
void
optimization_records_maybe_record_optinfo (const optinfo *optinfo)
{
/* Bail if recording not enabled. */
if (!the_json_writer)
return;
the_json_writer->add_record (optinfo);
}
/* Handling for the end of a dump scope for the
optimization records sink. */
void
optimization_records_maybe_pop_dump_scope ()
{
/* Bail if recording not enabled. */
if (!the_json_writer)
return;
the_json_writer->pop_scope ();
}
#if CHECKING_P
namespace selftest {

View File

@ -21,16 +21,40 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_OPTINFO_EMIT_JSON_H
#define GCC_OPTINFO_EMIT_JSON_H
#include "json.h"
class optinfo;
struct opt_pass;
extern void optimization_records_start ();
extern void optimization_records_finish ();
/* A class for writing out optimization records in JSON format. */
extern bool optimization_records_enabled_p ();
class optrecord_json_writer
{
public:
optrecord_json_writer ();
~optrecord_json_writer ();
void write () const;
void add_record (const optinfo *optinfo);
void pop_scope ();
extern void optimization_records_maybe_record_optinfo (const optinfo *);
extern void optimization_records_maybe_pop_dump_scope ();
void add_record (json::object *obj);
json::object *impl_location_to_json (dump_impl_location_t loc);
json::object *location_to_json (location_t loc);
json::object *profile_count_to_json (profile_count count);
json::string *get_id_value_for_pass (opt_pass *pass);
json::object *pass_to_json (opt_pass *pass);
json::value *inlining_chain_to_json (location_t loc);
json::object *optinfo_to_json (const optinfo *optinfo);
void add_pass_list (json::array *arr, opt_pass *pass);
private:
/* The root value for the JSON file.
Currently the JSON values are stored in memory, and flushed when the
compiler exits. It would probably be better to simply write out
the JSON as we go. */
json::array *m_root_tuple;
/* The currently open scopes, for expressing nested optimization records. */
auto_vec<json::array *> m_scopes;
};
#endif /* #ifndef GCC_OPTINFO_EMIT_JSON_H */

View File

@ -125,18 +125,7 @@ optinfo::emit_for_opt_problem () const
dump_context::get ().emit_item (item, dump_kind);
/* Re-emit to "non-immediate" destinations. */
emit ();
}
/* Emit the optinfo to all of the "non-immediate" destinations
(emission to "immediate" destinations is done by
dump_context::emit_item). */
void
optinfo::emit () const
{
/* -fsave-optimization-record. */
optimization_records_maybe_record_optinfo (this);
dump_context::get ().emit_optinfo (this);
}
/* Update the optinfo's kind based on DUMP_KIND. */
@ -152,21 +141,11 @@ optinfo::handle_dump_file_kind (dump_flags_t dump_kind)
m_kind = OPTINFO_KIND_NOTE;
}
/* Should optinfo instances be created?
All creation of optinfos should be guarded by this predicate.
Return true if any optinfo destinations are active. */
bool optinfo_enabled_p ()
{
return (dump_context::get ().forcibly_enable_optinfo_p ()
|| optimization_records_enabled_p ());
}
/* Return true if any of the active optinfo destinations make use
of inlining information.
(if true, then the information is preserved). */
bool optinfo_wants_inlining_info_p ()
{
return optimization_records_enabled_p ();
return dump_context::get ().optimization_records_enabled_p ();
}

View File

@ -68,12 +68,6 @@ along with GCC; see the file COPYING3. If not see
struct opt_pass;
class optinfo_item;
/* Should optinfo instances be created?
All creation of optinfos should be guarded by this predicate.
Return true if any optinfo destinations are active. */
extern bool optinfo_enabled_p ();
/* Return true if any of the active optinfo destinations make use
of inlining information.
(if true, then the information is preserved). */
@ -130,8 +124,6 @@ class optinfo
void emit_for_opt_problem () const;
private:
void emit () const;
/* Pre-canned ways of manipulating the optinfo, for use by friend class
dump_context. */
void handle_dump_file_kind (dump_flags_t);

View File

@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "dumpfile.h"
#include "ipa-fnsummary.h"
#include "dump-context.h"
#include "optinfo-emit-json.h"
#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
@ -488,7 +489,7 @@ compile_file (void)
if (lang_hooks.decls.post_compilation_parsing_cleanups)
lang_hooks.decls.post_compilation_parsing_cleanups ();
optimization_records_finish ();
dump_context::get ().finish_any_json_writer ();
if (seen_error ())
return;
@ -2131,7 +2132,10 @@ do_compile ()
timevar_start (TV_PHASE_SETUP);
optimization_records_start ();
if (flag_save_optimization_record)
{
dump_context::get ().set_json_writer (new optrecord_json_writer ());
}
/* This must be run always, because it is needed to compute the FP
predefined macros, such as __LDBL_MAX__, for targets using non