[PATCH 1/2] Eliminate global state from -fsave-optimization-record
Richard Biener
richard.guenther@gmail.com
Mon Nov 19 10:34:00 GMT 2018
On Sat, Nov 17, 2018 at 1:12 AM David Malcolm <dmalcolm@redhat.com> wrote:
>
> 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.
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu
> (in conjuction with the followup patch)
>
> OK for trunk?
OK.
Richard.
> 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.
> ---
> gcc/dump-context.h | 22 ++++++++---
> gcc/dumpfile.c | 55 ++++++++++++++++++++++++--
> gcc/optinfo-emit-json.cc | 101 -----------------------------------------------
> gcc/optinfo-emit-json.h | 42 +++++++++++++++-----
> gcc/optinfo.cc | 25 +-----------
> gcc/optinfo.h | 8 ----
> gcc/toplev.c | 8 +++-
> 7 files changed, 109 insertions(+), 152 deletions(-)
>
> diff --git a/gcc/dump-context.h b/gcc/dump-context.h
> index ace139c..2016ce7 100644
> --- a/gcc/dump-context.h
> +++ b/gcc/dump-context.h
> @@ -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;
> diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> index 86651df..014acf1 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -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 ();
> diff --git a/gcc/optinfo-emit-json.cc b/gcc/optinfo-emit-json.cc
> index 6d4502c..4fa6708 100644
> --- a/gcc/optinfo-emit-json.cc
> +++ b/gcc/optinfo-emit-json.cc
> @@ -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 {
> diff --git a/gcc/optinfo-emit-json.h b/gcc/optinfo-emit-json.h
> index 3628d56..2185c08 100644
> --- a/gcc/optinfo-emit-json.h
> +++ b/gcc/optinfo-emit-json.h
> @@ -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
>
> -class optinfo;
> -struct opt_pass;
> -
> -extern void optimization_records_start ();
> -extern void optimization_records_finish ();
> +#include "json.h"
>
> -extern bool optimization_records_enabled_p ();
> -
> -extern void optimization_records_maybe_record_optinfo (const optinfo *);
> -extern void optimization_records_maybe_pop_dump_scope ();
> +class optinfo;
>
> +/* 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;
> +};
>
> #endif /* #ifndef GCC_OPTINFO_EMIT_JSON_H */
> diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
> index de781a5..f8e08de 100644
> --- a/gcc/optinfo.cc
> +++ b/gcc/optinfo.cc
> @@ -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 ();
> }
> diff --git a/gcc/optinfo.h b/gcc/optinfo.h
> index 99bd22c..4a678ff 100644
> --- a/gcc/optinfo.h
> +++ b/gcc/optinfo.h
> @@ -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);
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 3fd4ec4..ab20cd9 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -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
> --
> 1.8.5.3
>
More information about the Gcc-patches
mailing list