Add "optinfo" framework

This patch implements a way to consolidate dump_* calls into
optinfo objects, as enabling work towards being able to write out
optimization records to a file.

The patch adds the support for building optinfo instances from dump_*
calls, but leaves implementing any *users* of them to followup patches.

gcc/ChangeLog:
	* Makefile.in (OBJS): Add optinfo.o.
	* coretypes.h (class symtab_node): New forward decl.
	(struct cgraph_node): New forward decl.
	(class varpool_node): New forward decl.
	* dump-context.h: New file.
	* dumpfile.c: Include "optinfo.h", "dump-context.h", "cgraph.h",
	"tree-pass.h".
	(refresh_dumps_are_enabled): Use optinfo_enabled_p.
	(set_dump_file): Call dumpfile_ensure_any_optinfo_are_flushed.
	(set_alt_dump_file): Likewise.
	(dump_context::~dump_context): New dtor.
	(dump_gimple_stmt): Move implementation to...
	(dump_context::dump_gimple_stmt): ...this new member function.
	Add the stmt to any pending optinfo, creating one if need be.
	(dump_gimple_stmt_loc): Move implementation to...
	(dump_context::dump_gimple_stmt_loc): ...this new member function.
	Start a new optinfo and add the stmt to it.
	(dump_gimple_expr): Move implementation to...
	(dump_context::dump_gimple_expr): ...this new member function.
	Add the stmt to any pending optinfo, creating one if need be.
	(dump_gimple_expr_loc): Move implementation to...
	(dump_context::dump_gimple_expr_loc): ...this new member function.
	Start a new optinfo and add the stmt to it.
	(dump_generic_expr): Move implementation to...
	(dump_context::dump_generic_expr): ...this new member function.
	Add the tree to any pending optinfo, creating one if need be.
	(dump_generic_expr_loc): Move implementation to...
	(dump_context::dump_generic_expr_loc): ...this new member
	function.  Add the tree to any pending optinfo, creating one if
	need be.
	(dump_printf): Move implementation to...
	(dump_context::dump_printf_va): ...this new member function.  Add
	the text to any pending optinfo, creating one if need be.
	(dump_printf_loc): Move implementation to...
	(dump_context::dump_printf_loc_va): ...this new member function.
	Start a new optinfo and add the stmt to it.
	(dump_dec): Move implementation to...
	(dump_context::dump_dec): ...this new member function.  Add the
	value to any pending optinfo, creating one if need be.
	(dump_context::dump_symtab_node): New member function.
	(dump_context::get_scope_depth): New member function.
	(dump_context::begin_scope): New member function.
	(dump_context::end_scope): New member function.
	(dump_context::ensure_pending_optinfo): New member function.
	(dump_context::begin_next_optinfo): New member function.
	(dump_context::end_any_optinfo): New member function.
	(dump_context::s_current): New global.
	(dump_context::s_default): New global.
	(dump_scope_depth): Delete global.
	(dumpfile_ensure_any_optinfo_are_flushed): New function.
	(dump_symtab_node): New function.
	(get_dump_scope_depth): Reimplement in terms of dump_context.
	(dump_begin_scope): Likewise.
	(dump_end_scope): Likewise.
	(selftest::temp_dump_context::temp_dump_context): New ctor.
	(selftest::temp_dump_context::~temp_dump_context): New dtor.
	(selftest::verify_item): New function.
	(ASSERT_IS_TEXT): New macro.
	(ASSERT_IS_TREE): New macro.
	(ASSERT_IS_GIMPLE): New macro.
	(selftest::test_capture_of_dump_calls): New test.
	(selftest::dumpfile_c_tests): Call it.
	* dumpfile.h (dump_printf, dump_printf_loc, dump_basic_block)
	(dump_generic_expr_loc, dump_generic_expr, dump_gimple_stmt_loc)
	(dump_gimple_stmt, dump_dec): Gather these related decls and add a
	descriptive comment.
	(dump_function, print_combine_total_stats, enable_rtl_dump_file)
	(dump_node, dump_bb): Move these unrelated decls.
	(class dump_manager): Add leading comment.
	* optinfo.cc: New file.
	* optinfo.h: New file.

From-SVN: r262891
This commit is contained in:
David Malcolm 2018-07-19 20:49:25 +00:00 committed by David Malcolm
parent 30c4605355
commit 4df3629eb7
8 changed files with 1278 additions and 70 deletions

View File

@ -1,3 +1,77 @@
2018-07-19 David Malcolm <dmalcolm@redhat.com>
* Makefile.in (OBJS): Add optinfo.o.
* coretypes.h (class symtab_node): New forward decl.
(struct cgraph_node): New forward decl.
(class varpool_node): New forward decl.
* dump-context.h: New file.
* dumpfile.c: Include "optinfo.h", "dump-context.h", "cgraph.h",
"tree-pass.h".
(refresh_dumps_are_enabled): Use optinfo_enabled_p.
(set_dump_file): Call dumpfile_ensure_any_optinfo_are_flushed.
(set_alt_dump_file): Likewise.
(dump_context::~dump_context): New dtor.
(dump_gimple_stmt): Move implementation to...
(dump_context::dump_gimple_stmt): ...this new member function.
Add the stmt to any pending optinfo, creating one if need be.
(dump_gimple_stmt_loc): Move implementation to...
(dump_context::dump_gimple_stmt_loc): ...this new member function.
Start a new optinfo and add the stmt to it.
(dump_gimple_expr): Move implementation to...
(dump_context::dump_gimple_expr): ...this new member function.
Add the stmt to any pending optinfo, creating one if need be.
(dump_gimple_expr_loc): Move implementation to...
(dump_context::dump_gimple_expr_loc): ...this new member function.
Start a new optinfo and add the stmt to it.
(dump_generic_expr): Move implementation to...
(dump_context::dump_generic_expr): ...this new member function.
Add the tree to any pending optinfo, creating one if need be.
(dump_generic_expr_loc): Move implementation to...
(dump_context::dump_generic_expr_loc): ...this new member
function. Add the tree to any pending optinfo, creating one if
need be.
(dump_printf): Move implementation to...
(dump_context::dump_printf_va): ...this new member function. Add
the text to any pending optinfo, creating one if need be.
(dump_printf_loc): Move implementation to...
(dump_context::dump_printf_loc_va): ...this new member function.
Start a new optinfo and add the stmt to it.
(dump_dec): Move implementation to...
(dump_context::dump_dec): ...this new member function. Add the
value to any pending optinfo, creating one if need be.
(dump_context::dump_symtab_node): New member function.
(dump_context::get_scope_depth): New member function.
(dump_context::begin_scope): New member function.
(dump_context::end_scope): New member function.
(dump_context::ensure_pending_optinfo): New member function.
(dump_context::begin_next_optinfo): New member function.
(dump_context::end_any_optinfo): New member function.
(dump_context::s_current): New global.
(dump_context::s_default): New global.
(dump_scope_depth): Delete global.
(dumpfile_ensure_any_optinfo_are_flushed): New function.
(dump_symtab_node): New function.
(get_dump_scope_depth): Reimplement in terms of dump_context.
(dump_begin_scope): Likewise.
(dump_end_scope): Likewise.
(selftest::temp_dump_context::temp_dump_context): New ctor.
(selftest::temp_dump_context::~temp_dump_context): New dtor.
(selftest::verify_item): New function.
(ASSERT_IS_TEXT): New macro.
(ASSERT_IS_TREE): New macro.
(ASSERT_IS_GIMPLE): New macro.
(selftest::test_capture_of_dump_calls): New test.
(selftest::dumpfile_c_tests): Call it.
* dumpfile.h (dump_printf, dump_printf_loc, dump_basic_block)
(dump_generic_expr_loc, dump_generic_expr, dump_gimple_stmt_loc)
(dump_gimple_stmt, dump_dec): Gather these related decls and add a
descriptive comment.
(dump_function, print_combine_total_stats, enable_rtl_dump_file)
(dump_node, dump_bb): Move these unrelated decls.
(class dump_manager): Add leading comment.
* optinfo.cc: New file.
* optinfo.h: New file.
2018-07-19 Michael Collison <michael.collison@arm.com>
Richard Henderson <rth@redhat.com>

View File

@ -1427,6 +1427,7 @@ OBJS = \
optabs-libfuncs.o \
optabs-query.o \
optabs-tree.o \
optinfo.o \
options-save.o \
opts-global.o \
passes.o \

View File

@ -134,6 +134,13 @@ struct gomp_single;
struct gomp_target;
struct gomp_teams;
/* Subclasses of symtab_node, using indentation to show the class
hierarchy. */
class symtab_node;
struct cgraph_node;
class varpool_node;
union section;
typedef union section section;
struct gcc_options;

138
gcc/dump-context.h Normal file
View File

@ -0,0 +1,138 @@
/* Support code for handling the various dump_* calls in dumpfile.h
Copyright (C) 2018 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_DUMP_CONTEXT_H
#define GCC_DUMP_CONTEXT_H 1
/* A class for handling the various dump_* calls.
In particular, this class has responsibility for consolidating
the "dump_*" calls into optinfo instances (delimited by "dump_*_loc"
calls), and emitting them.
Putting this in a class (rather than as global state) allows
for selftesting of this code. */
class dump_context
{
friend class temp_dump_context;
public:
static dump_context &get () { return *s_current; }
~dump_context ();
void dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc);
void dump_gimple_stmt_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
gimple *gs, int spc);
void dump_gimple_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc);
void dump_gimple_expr_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
gimple *gs,
int spc);
void dump_generic_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
tree t);
void dump_generic_expr_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
tree t);
void dump_printf_va (dump_flags_t dump_kind, const char *format,
va_list ap) ATTRIBUTE_PRINTF (3, 0);
void dump_printf_loc_va (dump_flags_t dump_kind, const dump_location_t &loc,
const char *format, va_list ap)
ATTRIBUTE_PRINTF (4, 0);
template<unsigned int N, typename C>
void dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value);
void dump_symtab_node (dump_flags_t dump_kind, symtab_node *node);
/* Managing nested scopes. */
unsigned int get_scope_depth () const;
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
{
return m_forcibly_enable_optinfo;
}
void end_any_optinfo ();
private:
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;
/* The optinfo currently being accumulated since the last dump_*_loc call,
if any. */
optinfo *m_pending;
/* The currently active dump_context, for use by the dump_* API calls. */
static dump_context *s_current;
/* The default active context. */
static dump_context s_default;
};
#if CHECKING_P
/* An RAII-style class for use in selftests for temporarily using a different
dump_context. */
class temp_dump_context
{
public:
temp_dump_context (bool forcibly_enable_optinfo);
~temp_dump_context ();
/* Support for selftests. */
optinfo *get_pending_optinfo () const { return m_context.m_pending; }
private:
dump_context m_context;
dump_context *m_saved;
bool m_saved_flag_remarks;
};
#endif /* CHECKING_P */
#endif /* GCC_DUMP_CONTEXT_H */

View File

@ -33,6 +33,10 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h" /* for dump_user_location_t ctor. */
#include "rtl.h" /* for dump_user_location_t ctor. */
#include "selftest.h"
#include "optinfo.h"
#include "dump-context.h"
#include "cgraph.h"
#include "tree-pass.h" /* for "current_pass". */
/* If non-NULL, return one past-the-end of the matching SUBPART of
the WHOLE string. */
@ -64,7 +68,7 @@ bool dumps_are_enabled = false;
static void
refresh_dumps_are_enabled ()
{
dumps_are_enabled = (dump_file || alt_dump_file);
dumps_are_enabled = (dump_file || alt_dump_file || optinfo_enabled_p ());
}
/* Set global "dump_file" to NEW_DUMP_FILE, refreshing the "dumps_are_enabled"
@ -73,6 +77,7 @@ refresh_dumps_are_enabled ()
void
set_dump_file (FILE *new_dump_file)
{
dumpfile_ensure_any_optinfo_are_flushed ();
dump_file = new_dump_file;
refresh_dumps_are_enabled ();
}
@ -83,6 +88,7 @@ set_dump_file (FILE *new_dump_file)
static void
set_alt_dump_file (FILE *new_alt_dump_file)
{
dumpfile_ensure_any_optinfo_are_flushed ();
alt_dump_file = new_alt_dump_file;
refresh_dumps_are_enabled ();
}
@ -465,25 +471,44 @@ dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
}
}
/* Implementation of dump_context member functions. */
/* dump_context's dtor. */
dump_context::~dump_context ()
{
delete m_pending;
}
/* Dump gimple statement GS with SPC indentation spaces and
EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
void
dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc)
dump_context::dump_gimple_stmt (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
if (dump_file && (dump_kind & pflags))
print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
if (alt_dump_file && (dump_kind & alt_flags))
print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
}
}
/* Similar to dump_gimple_stmt, except additionally print source location. */
void
dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, gimple *gs, int spc)
dump_context::dump_gimple_stmt_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
location_t srcloc = loc.get_location_t ();
if (dump_file && (dump_kind & pflags))
@ -497,6 +522,13 @@ dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_loc (dump_kind, alt_dump_file, srcloc);
print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
}
if (optinfo_enabled_p ())
{
optinfo &info = begin_next_optinfo (loc);
info.handle_dump_file_kind (dump_kind);
info.add_gimple_stmt (gs, spc, dump_flags | extra_dump_flags);
}
}
/* Dump gimple statement GS with SPC indentation spaces and
@ -504,21 +536,32 @@ dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
Do not terminate with a newline or semicolon. */
void
dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc)
dump_context::dump_gimple_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
if (dump_file && (dump_kind & pflags))
print_gimple_expr (dump_file, gs, spc, dump_flags | extra_dump_flags);
if (alt_dump_file && (dump_kind & alt_flags))
print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
}
}
/* Similar to dump_gimple_expr, except additionally print source location. */
void
dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, gimple *gs, int spc)
dump_context::dump_gimple_expr_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
gimple *gs,
int spc)
{
location_t srcloc = loc.get_location_t ();
if (dump_file && (dump_kind & pflags))
@ -532,6 +575,13 @@ dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_loc (dump_kind, alt_dump_file, srcloc);
print_gimple_expr (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
}
if (optinfo_enabled_p ())
{
optinfo &info = begin_next_optinfo (loc);
info.handle_dump_file_kind (dump_kind);
info.add_gimple_expr (gs, spc, dump_flags | extra_dump_flags);
}
}
@ -539,14 +589,22 @@ dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
DUMP_KIND is enabled. */
void
dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
tree t)
dump_context::dump_generic_expr (dump_flags_t dump_kind,
dump_flags_t extra_dump_flags,
tree t)
{
if (dump_file && (dump_kind & pflags))
print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
if (alt_dump_file && (dump_kind & alt_flags))
print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
info.add_tree (t, dump_flags | extra_dump_flags);
}
}
@ -554,8 +612,10 @@ dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
location. */
void
dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, tree t)
dump_context::dump_generic_expr_loc (dump_flags_t dump_kind,
const dump_location_t &loc,
dump_flags_t extra_dump_flags,
tree t)
{
location_t srcloc = loc.get_location_t ();
if (dump_file && (dump_kind & pflags))
@ -569,53 +629,83 @@ dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_loc (dump_kind, alt_dump_file, srcloc);
print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
}
if (optinfo_enabled_p ())
{
optinfo &info = begin_next_optinfo (loc);
info.handle_dump_file_kind (dump_kind);
info.add_tree (t, dump_flags | extra_dump_flags);
}
}
/* Output a formatted message using FORMAT on appropriate dump streams. */
void
dump_printf (dump_flags_t dump_kind, const char *format, ...)
dump_context::dump_printf_va (dump_flags_t dump_kind, const char *format,
va_list ap)
{
if (dump_file && (dump_kind & pflags))
{
va_list ap;
va_start (ap, format);
vfprintf (dump_file, format, ap);
va_end (ap);
va_list aq;
va_copy (aq, ap);
vfprintf (dump_file, format, aq);
va_end (aq);
}
if (alt_dump_file && (dump_kind & alt_flags))
{
va_list ap;
va_start (ap, format);
vfprintf (alt_dump_file, format, ap);
va_end (ap);
va_list aq;
va_copy (aq, ap);
vfprintf (alt_dump_file, format, aq);
va_end (aq);
}
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
va_list aq;
va_copy (aq, ap);
info.add_printf_va (format, aq);
va_end (aq);
}
}
/* Similar to dump_printf, except source location is also printed. */
/* Similar to dump_printf, except source location is also printed, and
dump location captured. */
void
dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
const char *format, ...)
dump_context::dump_printf_loc_va (dump_flags_t dump_kind,
const dump_location_t &loc,
const char *format, va_list ap)
{
location_t srcloc = loc.get_location_t ();
if (dump_file && (dump_kind & pflags))
{
va_list ap;
dump_loc (dump_kind, dump_file, srcloc);
va_start (ap, format);
vfprintf (dump_file, format, ap);
va_end (ap);
va_list aq;
va_copy (aq, ap);
vfprintf (dump_file, format, aq);
va_end (aq);
}
if (alt_dump_file && (dump_kind & alt_flags))
{
va_list ap;
dump_loc (dump_kind, alt_dump_file, srcloc);
va_start (ap, format);
vfprintf (alt_dump_file, format, ap);
va_end (ap);
va_list aq;
va_copy (aq, ap);
vfprintf (alt_dump_file, format, aq);
va_end (aq);
}
if (optinfo_enabled_p ())
{
optinfo &info = begin_next_optinfo (loc);
info.handle_dump_file_kind (dump_kind);
va_list aq;
va_copy (aq, ap);
info.add_printf_va (format, aq);
va_end (aq);
}
}
@ -623,7 +713,7 @@ dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
template<unsigned int N, typename C>
void
dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
dump_context::dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
{
STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
@ -632,6 +722,224 @@ dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
if (alt_dump_file && (dump_kind & alt_flags))
print_dec (value, alt_dump_file, sgn);
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
info.add_poly_int<N,C> (value);
}
}
/* Output the name of NODE on appropriate dump streams. */
void
dump_context::dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
{
if (dump_file && (dump_kind & pflags))
fprintf (dump_file, "%s", node->dump_name ());
if (alt_dump_file && (dump_kind & alt_flags))
fprintf (alt_dump_file, "%s", node->dump_name ());
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo ();
info.handle_dump_file_kind (dump_kind);
info.add_symtab_node (node);
}
}
/* Get the current dump scope-nesting depth.
For use by -fopt-info (for showing nesting via indentation). */
unsigned int
dump_context::get_scope_depth () const
{
return m_scope_depth;
}
/* Push a nested dump scope.
Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
destination, if any.
Emit a "scope" optinfo if optinfos are enabled.
Increment the scope depth. */
void
dump_context::begin_scope (const char *name, const dump_location_t &loc)
{
/* Specialcase, to avoid going through dump_printf_loc,
so that we can create a optinfo of kind OPTINFO_KIND_SCOPE. */
if (dump_file)
{
dump_loc (MSG_NOTE, dump_file, loc.get_location_t ());
fprintf (dump_file, "=== %s ===\n", name);
}
if (alt_dump_file)
{
dump_loc (MSG_NOTE, alt_dump_file, loc.get_location_t ());
fprintf (alt_dump_file, "=== %s ===\n", name);
}
if (optinfo_enabled_p ())
{
end_any_optinfo ();
optinfo info (loc, OPTINFO_KIND_SCOPE, current_pass);
info.add_printf ("=== %s ===", name);
info.emit ();
}
m_scope_depth++;
}
/* Pop a nested dump scope. */
void
dump_context::end_scope ()
{
end_any_optinfo ();
m_scope_depth--;
}
/* Return the optinfo currently being accumulated, creating one if
necessary. */
optinfo &
dump_context::ensure_pending_optinfo ()
{
if (!m_pending)
return begin_next_optinfo (dump_location_t (dump_user_location_t ()));
return *m_pending;
}
/* Start a new optinfo and return it, ending any optinfo that was already
accumulated. */
optinfo &
dump_context::begin_next_optinfo (const dump_location_t &loc)
{
end_any_optinfo ();
gcc_assert (m_pending == NULL);
m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
return *m_pending;
}
/* End any optinfo that has been accumulated within this context; emitting
it to any destinations as appropriate - though none have currently been
implemented. */
void
dump_context::end_any_optinfo ()
{
if (m_pending)
m_pending->emit ();
delete m_pending;
m_pending = NULL;
}
/* The current singleton dump_context, and its default. */
dump_context *dump_context::s_current = &dump_context::s_default;
dump_context dump_context::s_default;
/* Implementation of dump_* API calls, calling into dump_context
member functions. */
/* Dump gimple statement GS with SPC indentation spaces and
EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled. */
void
dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
dump_context::get ().dump_gimple_stmt (dump_kind, extra_dump_flags, gs, spc);
}
/* Similar to dump_gimple_stmt, except additionally print source location. */
void
dump_gimple_stmt_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, gimple *gs, int spc)
{
dump_context::get ().dump_gimple_stmt_loc (dump_kind, loc, extra_dump_flags,
gs, spc);
}
/* Dump gimple statement GS with SPC indentation spaces and
EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.
Do not terminate with a newline or semicolon. */
void
dump_gimple_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
gimple *gs, int spc)
{
dump_context::get ().dump_gimple_expr (dump_kind, extra_dump_flags, gs, spc);
}
/* Similar to dump_gimple_expr, except additionally print source location. */
void
dump_gimple_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, gimple *gs, int spc)
{
dump_context::get ().dump_gimple_expr_loc (dump_kind, loc, extra_dump_flags,
gs, spc);
}
/* Dump expression tree T using EXTRA_DUMP_FLAGS on dump streams if
DUMP_KIND is enabled. */
void
dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
tree t)
{
dump_context::get ().dump_generic_expr (dump_kind, extra_dump_flags, t);
}
/* Similar to dump_generic_expr, except additionally print the source
location. */
void
dump_generic_expr_loc (dump_flags_t dump_kind, const dump_location_t &loc,
dump_flags_t extra_dump_flags, tree t)
{
dump_context::get ().dump_generic_expr_loc (dump_kind, loc, extra_dump_flags,
t);
}
/* Output a formatted message using FORMAT on appropriate dump streams. */
void
dump_printf (dump_flags_t dump_kind, const char *format, ...)
{
va_list ap;
va_start (ap, format);
dump_context::get ().dump_printf_va (dump_kind, format, ap);
va_end (ap);
}
/* Similar to dump_printf, except source location is also printed, and
dump location captured. */
void
dump_printf_loc (dump_flags_t dump_kind, const dump_location_t &loc,
const char *format, ...)
{
va_list ap;
va_start (ap, format);
dump_context::get ().dump_printf_loc_va (dump_kind, loc, format, ap);
va_end (ap);
}
/* Output VALUE in decimal to appropriate dump streams. */
template<unsigned int N, typename C>
void
dump_dec (dump_flags_t dump_kind, const poly_int<N, C> &value)
{
dump_context::get ().dump_dec (dump_kind, value);
}
template void dump_dec (dump_flags_t, const poly_uint16 &);
@ -662,29 +970,42 @@ dump_hex (dump_flags_t dump_kind, const poly_wide_int &value)
print_hex (value, alt_dump_file);
}
/* The current dump scope-nesting depth. */
/* Emit and delete the currently pending optinfo, if there is one,
without the caller needing to know about class dump_context. */
static int dump_scope_depth;
void
dumpfile_ensure_any_optinfo_are_flushed ()
{
dump_context::get().end_any_optinfo ();
}
/* Output the name of NODE on appropriate dump streams. */
void
dump_symtab_node (dump_flags_t dump_kind, symtab_node *node)
{
dump_context::get ().dump_symtab_node (dump_kind, node);
}
/* Get the current dump scope-nesting depth.
For use by dump_*_loc (for showing nesting via indentation). */
For use by -fopt-info (for showing nesting via indentation). */
unsigned int
get_dump_scope_depth ()
{
return dump_scope_depth;
return dump_context::get ().get_scope_depth ();
}
/* Push a nested dump scope.
Print "=== NAME ===\n" to the dumpfile, if any, and to the -fopt-info
destination, if any.
Emit a "scope" opinfo if optinfos are enabled.
Increment the scope depth. */
void
dump_begin_scope (const char *name, const dump_location_t &loc)
{
dump_printf_loc (MSG_NOTE, loc, "=== %s ===\n", name);
dump_scope_depth++;
dump_context::get ().begin_scope (name, loc);
}
/* Pop a nested dump scope. */
@ -692,7 +1013,7 @@ dump_begin_scope (const char *name, const dump_location_t &loc)
void
dump_end_scope ()
{
dump_scope_depth--;
dump_context::get ().end_scope ();
}
/* Start a dump for PHASE. Store user-supplied dump flags in
@ -1249,6 +1570,24 @@ enable_rtl_dump_file (void)
#if CHECKING_P
/* temp_dump_context's ctor. Temporarily override the dump_context
(to forcibly enable optinfo-generation). */
temp_dump_context::temp_dump_context (bool forcibly_enable_optinfo)
: m_context (),
m_saved (&dump_context ().get ())
{
dump_context::s_current = &m_context;
m_context.m_forcibly_enable_optinfo = forcibly_enable_optinfo;
}
/* temp_dump_context's dtor. Restore the saved dump_context. */
temp_dump_context::~temp_dump_context ()
{
dump_context::s_current = m_saved;
}
namespace selftest {
/* Verify that the dump_location_t constructors capture the source location
@ -1285,12 +1624,188 @@ test_impl_location ()
#endif
}
/* Verify that ITEM has the expected values. */
static void
verify_item (const location &loc,
const optinfo_item *item,
enum optinfo_item_kind expected_kind,
location_t expected_location,
const char *expected_text)
{
ASSERT_EQ_AT (loc, item->get_kind (), expected_kind);
ASSERT_EQ_AT (loc, item->get_location (), expected_location);
ASSERT_STREQ_AT (loc, item->get_text (), expected_text);
}
/* Verify that ITEM is a text item, with EXPECTED_TEXT. */
#define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
UNKNOWN_LOCATION, (EXPECTED_TEXT)); \
SELFTEST_END_STMT
/* Verify that ITEM is a tree item, with the expected values. */
#define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
(EXPECTED_LOCATION), (EXPECTED_TEXT)); \
SELFTEST_END_STMT
/* Verify that ITEM is a gimple item, with the expected values. */
#define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
(EXPECTED_LOCATION), (EXPECTED_TEXT)); \
SELFTEST_END_STMT
/* Verify that calls to the dump_* API are captured and consolidated into
optimization records. */
static void
test_capture_of_dump_calls (const line_table_case &case_)
{
/* Generate a location_t for testing. */
line_table_test ltt (case_);
linemap_add (line_table, LC_ENTER, false, "test.txt", 0);
linemap_line_start (line_table, 5, 100);
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
location_t where = linemap_position_for_column (line_table, 10);
dump_location_t loc = dump_location_t::from_location_t (where);
/* Test of dump_printf. */
{
temp_dump_context tmp (true);
dump_printf (MSG_NOTE, "int: %i str: %s", 42, "foo");
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
}
/* Tree, via dump_generic_expr. */
{
temp_dump_context tmp (true);
dump_printf_loc (MSG_NOTE, loc, "test of tree: ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, integer_zero_node);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->get_location_t (), where);
ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
}
/* Tree, via dump_generic_expr_loc. */
{
temp_dump_context tmp (true);
dump_generic_expr_loc (MSG_NOTE, loc, TDF_SLIM, integer_one_node);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->get_location_t (), where);
ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
}
/* Gimple. */
{
greturn *stmt = gimple_build_return (NULL);
gimple_set_location (stmt, where);
/* dump_gimple_stmt_loc. */
{
temp_dump_context tmp (true);
dump_gimple_stmt_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
}
/* dump_gimple_stmt. */
{
temp_dump_context tmp (true);
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 2);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_GIMPLE (info->get_item (0), where, "return;\n");
}
/* dump_gimple_expr_loc. */
{
temp_dump_context tmp (true);
dump_gimple_expr_loc (MSG_NOTE, loc, TDF_SLIM, stmt, 2);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
}
/* dump_gimple_expr. */
{
temp_dump_context tmp (true);
dump_gimple_expr (MSG_NOTE, TDF_SLIM, stmt, 2);
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_GIMPLE (info->get_item (0), where, "return;");
}
}
/* poly_int. */
{
temp_dump_context tmp (true);
dump_dec (MSG_NOTE, poly_int64 (42));
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_TEXT (info->get_item (0), "42");
}
/* Verify that MSG_* affects optinfo->get_kind (); we tested MSG_NOTE
above. */
{
/* MSG_OPTIMIZED_LOCATIONS. */
{
temp_dump_context tmp (true);
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
OPTINFO_KIND_SUCCESS);
}
/* MSG_MISSED_OPTIMIZATION. */
{
temp_dump_context tmp (true);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
OPTINFO_KIND_FAILURE);
}
}
}
/* Run all of the selftests within this file. */
void
dumpfile_c_tests ()
{
test_impl_location ();
for_each_line_table_case (test_capture_of_dump_calls);
}
} // namespace selftest

View File

@ -420,35 +420,6 @@ extern FILE *dump_begin (int, dump_flags_t *, int part=-1);
extern void dump_end (int, FILE *);
extern int opt_info_switch_p (const char *);
extern const char *dump_flag_name (int);
extern void dump_printf (dump_flags_t, const char *, ...) ATTRIBUTE_PRINTF_2;
extern void dump_printf_loc (dump_flags_t, const dump_location_t &,
const char *, ...) ATTRIBUTE_PRINTF_3;
extern void dump_function (int phase, tree fn);
extern void dump_basic_block (dump_flags_t, basic_block, int);
extern void dump_generic_expr_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, tree);
extern void dump_generic_expr (dump_flags_t, dump_flags_t, tree);
extern void dump_gimple_stmt_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, gimple *, int);
extern void dump_gimple_stmt (dump_flags_t, dump_flags_t, gimple *, int);
extern void dump_gimple_expr_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, gimple *, int);
extern void dump_gimple_expr (dump_flags_t, dump_flags_t, gimple *, int);
extern void print_combine_total_stats (void);
extern bool enable_rtl_dump_file (void);
template<unsigned int N, typename C>
void dump_dec (dump_flags_t, const poly_int<N, C> &);
extern void dump_dec (dump_flags_t, const poly_wide_int &, signop);
extern void dump_hex (dump_flags_t, const poly_wide_int &);
/* In tree-dump.c */
extern void dump_node (const_tree, dump_flags_t, FILE *);
/* In combine.c */
extern void dump_combine_total_stats (FILE *);
/* In cfghooks.c */
extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
/* Global variables used to communicate with passes. */
extern FILE *dump_file;
@ -466,6 +437,54 @@ dump_enabled_p (void)
return dumps_are_enabled;
}
/* The following API calls (which *don't* take a "FILE *")
write the output to zero or more locations:
(a) the active dump_file, if any
(b) the -fopt-info destination, if any
(c) to the "optinfo" destinations, if any:
dump_* (MSG_*) --> dumpfile.c --+--> (a) dump_file
|
+--> (b) alt_dump_file
|
`--> (c) optinfo
`---> optinfo destinations
For optinfos, the dump_*_loc mark the beginning of an optinfo
instance: all subsequent dump_* calls are consolidated into
that optinfo, until the next dump_*_loc call (or a change in
dump scope, or a call to dumpfile_ensure_any_optinfo_are_flushed).
A group of dump_* calls should be guarded by:
if (dump_enabled_p ())
to minimize the work done for the common case where dumps
are disabled. */
extern void dump_printf (dump_flags_t, const char *, ...) ATTRIBUTE_PRINTF_2;
extern void dump_printf_loc (dump_flags_t, const dump_location_t &,
const char *, ...) ATTRIBUTE_PRINTF_3;
extern void dump_function (int phase, tree fn);
extern void dump_basic_block (dump_flags_t, basic_block, int);
extern void dump_generic_expr_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, tree);
extern void dump_generic_expr (dump_flags_t, dump_flags_t, tree);
extern void dump_gimple_stmt_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, gimple *, int);
extern void dump_gimple_stmt (dump_flags_t, dump_flags_t, gimple *, int);
extern void dump_gimple_expr_loc (dump_flags_t, const dump_location_t &,
dump_flags_t, gimple *, int);
extern void dump_gimple_expr (dump_flags_t, dump_flags_t, gimple *, int);
extern void dump_symtab_node (dump_flags_t, symtab_node *);
template<unsigned int N, typename C>
void dump_dec (dump_flags_t, const poly_int<N, C> &);
extern void dump_dec (dump_flags_t, const poly_wide_int &, signop);
extern void dump_hex (dump_flags_t, const poly_wide_int &);
extern void dumpfile_ensure_any_optinfo_are_flushed ();
/* Managing nested scopes, so that dumps can express the call chain
leading to a dump message. */
@ -505,8 +524,23 @@ class auto_dump_scope
#define AUTO_DUMP_SCOPE(NAME, LOC) \
auto_dump_scope scope (NAME, LOC)
extern void dump_function (int phase, tree fn);
extern void print_combine_total_stats (void);
extern bool enable_rtl_dump_file (void);
/* In tree-dump.c */
extern void dump_node (const_tree, dump_flags_t, FILE *);
/* In combine.c */
extern void dump_combine_total_stats (FILE *);
/* In cfghooks.c */
extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
namespace gcc {
/* A class for managing all of the various dump files used by the
optimization passes. */
class dump_manager
{
public:

236
gcc/optinfo.cc Normal file
View File

@ -0,0 +1,236 @@
/* Optimization information.
Copyright (C) 2018 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "optinfo.h"
#include "dump-context.h"
#include "pretty-print.h"
#include "gimple-pretty-print.h"
#include "cgraph.h"
#include "selftest.h"
/* optinfo_item's ctor. */
optinfo_item::optinfo_item (enum optinfo_item_kind kind, location_t location,
char *text, bool owned)
: m_kind (kind), m_location (location), m_text (text), m_owned (owned)
{
}
/* optinfo_item's dtor. */
optinfo_item::~optinfo_item ()
{
if (m_owned)
free (m_text);
}
/* Get a string from KIND. */
const char *
optinfo_kind_to_string (enum optinfo_kind kind)
{
switch (kind)
{
default:
gcc_unreachable ();
case OPTINFO_KIND_SUCCESS:
return "success";
case OPTINFO_KIND_FAILURE:
return "failure";
case OPTINFO_KIND_NOTE:
return "note";
case OPTINFO_KIND_SCOPE:
return "scope";
}
}
/* optinfo's dtor. */
optinfo::~optinfo ()
{
/* Cleanup. */
unsigned i;
optinfo_item *item;
FOR_EACH_VEC_ELT (m_items, i, item)
delete item;
}
/* Emit the optinfo to all of the active destinations. */
void
optinfo::emit ()
{
/* currently this is a no-op. */
}
/* Update the optinfo's kind based on DUMP_KIND. */
void
optinfo::handle_dump_file_kind (dump_flags_t dump_kind)
{
if (dump_kind & MSG_OPTIMIZED_LOCATIONS)
m_kind = OPTINFO_KIND_SUCCESS;
else if (dump_kind & MSG_MISSED_OPTIMIZATION)
m_kind = OPTINFO_KIND_FAILURE;
else if (dump_kind & MSG_NOTE)
m_kind = OPTINFO_KIND_NOTE;
}
/* Append a string literal to this optinfo. */
void
optinfo::add_string (const char *str)
{
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
const_cast <char *> (str), false);
m_items.safe_push (item);
}
/* Append printf-formatted text to this optinfo. */
void
optinfo::add_printf (const char *format, ...)
{
va_list ap;
va_start (ap, format);
add_printf_va (format, ap);
va_end (ap);
}
/* Append printf-formatted text to this optinfo. */
void
optinfo::add_printf_va (const char *format, va_list ap)
{
char *formatted_text = xvasprintf (format, ap);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
formatted_text, true);
m_items.safe_push (item);
}
/* Append a gimple statement to this optinfo, equivalent to
print_gimple_stmt. */
void
optinfo::add_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
{
pretty_printer pp;
pp_needs_newline (&pp) = true;
pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
pp_newline (&pp);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
xstrdup (pp_formatted_text (&pp)), true);
m_items.safe_push (item);
}
/* Append a gimple statement to this optinfo, equivalent to
print_gimple_expr. */
void
optinfo::add_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
{
dump_flags |= TDF_RHS_ONLY;
pretty_printer pp;
pp_needs_newline (&pp) = true;
pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_GIMPLE, gimple_location (stmt),
xstrdup (pp_formatted_text (&pp)), true);
m_items.safe_push (item);
}
/* Append a tree node to this optinfo, equivalent to print_generic_expr. */
void
optinfo::add_tree (tree node, dump_flags_t dump_flags)
{
pretty_printer pp;
pp_needs_newline (&pp) = true;
pp_translate_identifiers (&pp) = false;
dump_generic_node (&pp, node, 0, dump_flags, false);
location_t loc = UNKNOWN_LOCATION;
if (EXPR_HAS_LOCATION (node))
loc = EXPR_LOCATION (node);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_TREE, loc,
xstrdup (pp_formatted_text (&pp)), true);
m_items.safe_push (item);
}
/* Append a symbol table node to this optinfo. */
void
optinfo::add_symtab_node (symtab_node *node)
{
location_t loc = DECL_SOURCE_LOCATION (node->decl);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
xstrdup (node->dump_name ()), true);
m_items.safe_push (item);
}
/* Append the decimal represenation of a wide_int_ref to this
optinfo. */
void
optinfo::add_dec (const wide_int_ref &wi, signop sgn)
{
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
print_dec (wi, buf, sgn);
optinfo_item *item
= new optinfo_item (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
xstrdup (buf), true);
m_items.safe_push (item);
}
/* 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 ()
{
/* Currently no destinations are implemented, just a hook for
selftests. */
return dump_context::get ().forcibly_enable_optinfo_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 false;
}

203
gcc/optinfo.h Normal file
View File

@ -0,0 +1,203 @@
/* Optimization information.
Copyright (C) 2018 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_OPTINFO_H
#define GCC_OPTINFO_H
/* An "optinfo" is a bundle of information describing part of an
optimization, which can be emitted to zero or more of several
destinations, such as:
* as a "remark" through the diagnostics subsystem
* saved to a file as an "optimization record"
Currently no such destinations are implemented.
They are generated in response to calls to the "dump_*" API in
dumpfile.h; repeated calls to the "dump_*" API are consolidated
into a pending optinfo instance, with a "dump_*_loc" starting a new
optinfo instance.
The data sent to the dump calls are captured within the pending optinfo
instance as a sequence of optinfo_items. For example, given:
if (dump_enabled_p ())
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: live stmt not supported: ");
dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
}
the "dump_printf_loc" call begins a new optinfo containing two items:
(1) a text item containing "not vectorized: live stmt not supported: "
(2) a gimple item for "stmt"
Dump destinations are thus able to access rich metadata about the
items when the optinfo is emitted to them, rather than just having plain
text. For example, when saving the above optinfo to a file as an
"optimization record", the record could capture the source location of
"stmt" above, rather than just its textual form.
The currently pending optinfo is emitted and deleted:
* each time a "dump_*_loc" call occurs (which starts the next optinfo), or
* when the dump files are changed (at the end of a pass)
Dumping to an optinfo instance is non-trivial (due to building optinfo_item
instances), so all usage should be guarded by
if (optinfo_enabled_p ())
which is off by default. */
/* Forward decls. */
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). */
extern bool optinfo_wants_inlining_info_p ();
/* The various kinds of optinfo. */
enum optinfo_kind
{
OPTINFO_KIND_SUCCESS,
OPTINFO_KIND_FAILURE,
OPTINFO_KIND_NOTE,
OPTINFO_KIND_SCOPE
};
extern const char *optinfo_kind_to_string (enum optinfo_kind kind);
/* A bundle of information describing part of an optimization. */
class optinfo
{
friend class dump_context;
public:
optinfo (const dump_location_t &loc,
enum optinfo_kind kind,
opt_pass *pass)
: m_loc (loc), m_kind (kind), m_pass (pass), m_items ()
{}
~optinfo ();
const dump_user_location_t &
get_user_location () const { return m_loc.get_user_location (); }
const dump_impl_location_t &
get_impl_location () const { return m_loc.get_impl_location (); }
enum optinfo_kind get_kind () const { return m_kind; }
opt_pass *get_pass () const { return m_pass; }
unsigned int num_items () const { return m_items.length (); }
const optinfo_item *get_item (unsigned int i) const { return m_items[i]; }
location_t get_location_t () const { return m_loc.get_location_t (); }
profile_count get_count () const { return m_loc.get_count (); }
private:
void emit ();
/* Pre-canned ways of manipulating the optinfo, for use by friend class
dump_context. */
void handle_dump_file_kind (dump_flags_t);
void add_string (const char *str);
void add_printf (const char *format, ...) ATTRIBUTE_PRINTF_2;
void add_printf_va (const char *format, va_list ap) ATTRIBUTE_PRINTF (2, 0);
void add_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags);
void add_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags);
void add_tree (tree node, dump_flags_t dump_flags);
void add_symtab_node (symtab_node *node);
void add_dec (const wide_int_ref &wi, signop sgn);
template<unsigned int N, typename C>
void add_poly_int (const poly_int<N, C> &value)
{
/* Compare with dump_dec (MSG_NOTE, ). */
STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
signop sgn = poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED;
if (value.is_constant ())
add_dec (value.coeffs[0], sgn);
else
{
add_string ("[");
for (unsigned int i = 0; i < N; ++i)
{
add_dec (value.coeffs[i], sgn);
add_string (i == N - 1 ? "]" : ",");
}
}
}
private:
dump_location_t m_loc;
enum optinfo_kind m_kind;
opt_pass *m_pass;
auto_vec <optinfo_item *> m_items;
};
/* An enum for discriminating between different kinds of optinfo_item. */
enum optinfo_item_kind
{
OPTINFO_ITEM_KIND_TEXT,
OPTINFO_ITEM_KIND_TREE,
OPTINFO_ITEM_KIND_GIMPLE,
OPTINFO_ITEM_KIND_SYMTAB_NODE
};
/* An item within an optinfo. */
class optinfo_item
{
public:
optinfo_item (enum optinfo_item_kind kind, location_t location,
char *text, bool owned);
~optinfo_item ();
enum optinfo_item_kind get_kind () const { return m_kind; }
location_t get_location () const { return m_location; }
const char *get_text () const { return m_text; }
private:
/* Metadata (e.g. for optimization records). */
enum optinfo_item_kind m_kind;
location_t m_location;
/* The textual form of the item. */
char *m_text;
bool m_owned;
};
#endif /* #ifndef GCC_OPTINFO_H */