Commit d276406a by Martin Liska Committed by Martin Liska

Support profile (BB counts and edge probabilities) in GIMPLE FE.

2019-05-09  Martin Liska  <mliska@suse.cz>

	* tree-cfg.c (dump_function_to_file): Dump entry BB count.
	* gimple-pretty-print.c (dump_gimple_bb_header):
	Dump BB count.
	(pp_cfg_jump): Dump edge probability.
	* profile-count.c (profile_quality_as_string): Simplify
	with a static array.
	(parse_profile_quality): New function.
	(profile_count::dump): Simplify with a static array.
	(profile_count::from_gcov_type): Add new argument.
	* profile-count.h (parse_profile_quality): Likewise.
	* predict.h (set_hot_bb_threshold): New.
	* params.def (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD):
	New param.
	* predict.c (get_hot_bb_threshold): Set from the new param.
	(set_hot_bb_threshold): New.
2019-05-09  Martin Liska  <mliska@suse.cz>

	* gimple-parser.c (struct gimple_parser): Add probability.
	for gimple_parser_edge.
	(gimple_parser::push_edge): Add new argument probability.
	(c_parser_gimple_parse_bb_spec): Parse also probability
	if present.
	(c_parser_parse_gimple_body): Set edge probability.
	(c_parser_gimple_compound_statement): Consume token
	before calling c_parser_gimple_goto_stmt.
	Parse BB counts.
	(c_parser_gimple_statement): Pass new argument.
	(c_parser_gimple_goto_stmt): Likewise.
	(c_parser_gimple_if_stmt): Likewise.
	(c_parser_gimple_or_rtl_pass_list): Parse hot_bb_threshold.
	* c-parser.c (c_parser_declaration_or_fndef): Pass
	hot_bb_threshold argument.
	* c-tree.h (struct c_declspecs): Add hot_bb_threshold
	field.
	(c_parser_gimple_parse_bb_spec_edge_probability): New.
2019-05-09  Martin Liska  <mliska@suse.cz>

	* gcc.dg/gimplefe-37.c: New test.
	* gcc.dg/gimplefe-33.c: Likewise.

From-SVN: r271034
parent 555dbc42
2019-05-09 Martin Liska <mliska@suse.cz>
* tree-cfg.c (dump_function_to_file): Dump entry BB count.
* gimple-pretty-print.c (dump_gimple_bb_header):
Dump BB count.
(pp_cfg_jump): Dump edge probability.
* profile-count.c (profile_quality_as_string): Simplify
with a static array.
(parse_profile_quality): New function.
(profile_count::dump): Simplify with a static array.
(profile_count::from_gcov_type): Add new argument.
* profile-count.h (parse_profile_quality): Likewise.
* predict.h (set_hot_bb_threshold): New.
* params.def (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD):
New param.
* predict.c (get_hot_bb_threshold): Set from the new param.
(set_hot_bb_threshold): New.
2019-05-09 Richard Biener <rguenther@suse.de> 2019-05-09 Richard Biener <rguenther@suse.de>
PR tree-optimization/90395 PR tree-optimization/90395
......
2019-05-09 Martin Liska <mliska@suse.cz>
* gimple-parser.c (struct gimple_parser): Add probability.
for gimple_parser_edge.
(gimple_parser::push_edge): Add new argument probability.
(c_parser_gimple_parse_bb_spec): Parse also probability
if present.
(c_parser_parse_gimple_body): Set edge probability.
(c_parser_gimple_compound_statement): Consume token
before calling c_parser_gimple_goto_stmt.
Parse BB counts.
(c_parser_gimple_statement): Pass new argument.
(c_parser_gimple_goto_stmt): Likewise.
(c_parser_gimple_if_stmt): Likewise.
(c_parser_gimple_or_rtl_pass_list): Parse hot_bb_threshold.
* c-parser.c (c_parser_declaration_or_fndef): Pass
hot_bb_threshold argument.
* c-tree.h (struct c_declspecs): Add hot_bb_threshold
field.
(c_parser_gimple_parse_bb_spec_edge_probability): New.
2019-04-26 Jakub Jelinek <jakub@redhat.com> 2019-04-26 Jakub Jelinek <jakub@redhat.com>
PR debug/90197 PR debug/90197
......
...@@ -2347,7 +2347,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, ...@@ -2347,7 +2347,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool saved = in_late_binary_op; bool saved = in_late_binary_op;
in_late_binary_op = true; in_late_binary_op = true;
c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass, c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
specs->declspec_il); specs->declspec_il,
specs->entry_bb_count);
in_late_binary_op = saved; in_late_binary_op = saved;
} }
else else
......
...@@ -317,6 +317,8 @@ struct c_declspecs { ...@@ -317,6 +317,8 @@ struct c_declspecs {
tree attrs; tree attrs;
/* The pass to start compiling a __GIMPLE or __RTL function with. */ /* The pass to start compiling a __GIMPLE or __RTL function with. */
char *gimple_or_rtl_pass; char *gimple_or_rtl_pass;
/* ENTRY BB count. */
profile_count entry_bb_count;
/* The base-2 log of the greatest alignment required by an _Alignas /* The base-2 log of the greatest alignment required by an _Alignas
specifier, in bytes, or -1 if no such specifiers with nonzero specifier, in bytes, or -1 if no such specifiers with nonzero
alignment. */ alignment. */
......
...@@ -22,7 +22,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -22,7 +22,8 @@ along with GCC; see the file COPYING3. If not see
/* Gimple parsing functions. */ /* Gimple parsing functions. */
extern void c_parser_parse_gimple_body (c_parser *, char *, extern void c_parser_parse_gimple_body (c_parser *, char *,
enum c_declspec_il); enum c_declspec_il,
profile_count);
extern void c_parser_gimple_or_rtl_pass_list (c_parser *, c_declspecs *); extern void c_parser_gimple_or_rtl_pass_list (c_parser *, c_declspecs *);
#endif #endif
...@@ -2704,6 +2704,10 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, ...@@ -2704,6 +2704,10 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent,
fprintf (outf, "%*s__BB(%d", indent, "", bb->index); fprintf (outf, "%*s__BB(%d", indent, "", bb->index);
if (bb->loop_father->header == bb) if (bb->loop_father->header == bb)
fprintf (outf, ",loop_header(%d)", bb->loop_father->num); fprintf (outf, ",loop_header(%d)", bb->loop_father->num);
if (bb->count.initialized_p ())
fprintf (outf, ",%s(%d)",
profile_quality_as_string (bb->count.quality ()),
bb->count.value ());
fprintf (outf, "):\n"); fprintf (outf, "):\n");
} }
else else
...@@ -2760,6 +2764,15 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t flags) ...@@ -2760,6 +2764,15 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t flags)
{ {
pp_string (buffer, "goto __BB"); pp_string (buffer, "goto __BB");
pp_decimal_int (buffer, e->dest->index); pp_decimal_int (buffer, e->dest->index);
if (e->probability.initialized_p ())
{
pp_string (buffer, "(");
pp_string (buffer,
profile_quality_as_string (e->probability.quality ()));
pp_string (buffer, "(");
pp_decimal_int (buffer, e->probability.value ());
pp_string (buffer, "))");
}
pp_semicolon (buffer); pp_semicolon (buffer);
} }
else else
......
...@@ -1419,6 +1419,12 @@ DEFPARAM(PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS, ...@@ -1419,6 +1419,12 @@ DEFPARAM(PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS,
" loops.", " loops.",
100, 0, 0) 100, 0, 0)
DEFPARAM(PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD,
"gimple-fe-computed-hot-bb-threshold",
"The number of executions of a basic block which is considered hot."
" The parameters is used only in GIMPLE FE.",
0, 0, 0)
/* /*
Local variables: Local variables:
......
...@@ -132,8 +132,8 @@ get_hot_bb_threshold () ...@@ -132,8 +132,8 @@ get_hot_bb_threshold ()
{ {
if (min_count == -1) if (min_count == -1)
{ {
min_count gcov_type t = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION); set_hot_bb_threshold (t);
if (dump_file) if (dump_file)
fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n", fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n",
min_count); min_count);
......
...@@ -33,34 +33,57 @@ along with GCC; see the file COPYING3. If not see ...@@ -33,34 +33,57 @@ along with GCC; see the file COPYING3. If not see
#include "wide-int.h" #include "wide-int.h"
#include "sreal.h" #include "sreal.h"
/* Names from profile_quality enum values. */
const char *profile_quality_names[] =
{
"uninitialized",
"guessed_local",
"guessed_global0",
"guessed_global0adjusted",
"guessed",
"afdo",
"adjusted",
"precise"
};
/* Get a string describing QUALITY. */ /* Get a string describing QUALITY. */
const char * const char *
profile_quality_as_string (enum profile_quality quality) profile_quality_as_string (enum profile_quality quality)
{ {
switch (quality) return profile_quality_names[quality];
{ }
default:
gcc_unreachable (); /* Parse VALUE as profile quality and return true when a valid QUALITY. */
case profile_uninitialized:
return "uninitialized"; bool
case profile_guessed_local: parse_profile_quality (const char *value, profile_quality *quality)
return "guessed_local"; {
case profile_guessed_global0: for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
return "guessed_global0"; if (strcmp (profile_quality_names[i], value) == 0)
case profile_guessed_global0adjusted: {
return "guessed_global0adjusted"; *quality = (profile_quality)i;
case profile_guessed: return true;
return "guessed"; }
case profile_afdo:
return "afdo"; return false;
case profile_adjusted:
return "adjusted";
case profile_precise:
return "precise";
}
} }
/* Display names from profile_quality enum values. */
const char *profile_quality_display_names[] =
{
NULL,
"estimated locally",
"estimated locally, globally 0",
"estimated locally, globally 0 adjusted",
"adjusted",
"auto FDO",
"guessed",
"precise"
};
/* Dump THIS to F. */ /* Dump THIS to F. */
void void
...@@ -69,23 +92,8 @@ profile_count::dump (FILE *f) const ...@@ -69,23 +92,8 @@ profile_count::dump (FILE *f) const
if (!initialized_p ()) if (!initialized_p ())
fprintf (f, "uninitialized"); fprintf (f, "uninitialized");
else else
{ fprintf (f, "%" PRId64 " (%s)", m_val,
fprintf (f, "%" PRId64, m_val); profile_quality_display_names[m_quality]);
if (m_quality == profile_guessed_local)
fprintf (f, " (estimated locally)");
else if (m_quality == profile_guessed_global0)
fprintf (f, " (estimated locally, globally 0)");
else if (m_quality == profile_guessed_global0adjusted)
fprintf (f, " (estimated locally, globally 0 adjusted)");
else if (m_quality == profile_adjusted)
fprintf (f, " (adjusted)");
else if (m_quality == profile_afdo)
fprintf (f, " (auto FDO)");
else if (m_quality == profile_guessed)
fprintf (f, " (guessed)");
else if (m_quality == profile_precise)
fprintf (f, " (precise)");
}
} }
/* Dump THIS to stderr. */ /* Dump THIS to stderr. */
...@@ -362,7 +370,7 @@ profile_count::combine_with_ipa_count (profile_count ipa) ...@@ -362,7 +370,7 @@ profile_count::combine_with_ipa_count (profile_count ipa)
Conversions back and forth are used to read the coverage and get it Conversions back and forth are used to read the coverage and get it
into internal representation. */ into internal representation. */
profile_count profile_count
profile_count::from_gcov_type (gcov_type v) profile_count::from_gcov_type (gcov_type v, profile_quality quality)
{ {
profile_count ret; profile_count ret;
gcc_checking_assert (v >= 0); gcc_checking_assert (v >= 0);
...@@ -371,7 +379,7 @@ profile_count::from_gcov_type (gcov_type v) ...@@ -371,7 +379,7 @@ profile_count::from_gcov_type (gcov_type v)
"Capping gcov count %" PRId64 " to max_count %" PRId64 "\n", "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
(int64_t) v, (int64_t) max_count); (int64_t) v, (int64_t) max_count);
ret.m_val = MIN (v, (gcov_type)max_count); ret.m_val = MIN (v, (gcov_type)max_count);
ret.m_quality = profile_precise; ret.m_quality = quality;
return ret; return ret;
} }
......
...@@ -60,6 +60,8 @@ enum profile_quality { ...@@ -60,6 +60,8 @@ enum profile_quality {
}; };
extern const char *profile_quality_as_string (enum profile_quality); extern const char *profile_quality_as_string (enum profile_quality);
extern bool parse_profile_quality (const char *value,
profile_quality *quality);
/* The base value for branch probability notes and edge probabilities. */ /* The base value for branch probability notes and edge probabilities. */
#define REG_BR_PROB_BASE 10000 #define REG_BR_PROB_BASE 10000
...@@ -149,6 +151,13 @@ class GTY((user)) profile_probability ...@@ -149,6 +151,13 @@ class GTY((user)) profile_probability
friend class profile_count; friend class profile_count;
public: public:
profile_probability (): m_val (uninitialized_probability),
m_quality (profile_guessed)
{}
profile_probability (uint32_t val, profile_quality quality):
m_val (val), m_quality (quality)
{}
/* Named probabilities. */ /* Named probabilities. */
static profile_probability never () static profile_probability never ()
...@@ -558,6 +567,12 @@ public: ...@@ -558,6 +567,12 @@ public:
return initialized_p () && other.initialized_p () && m_val >= other.m_val; return initialized_p () && other.initialized_p () && m_val >= other.m_val;
} }
/* Get the value of the count. */
uint32_t value () const { return m_val; }
/* Get the quality of the count. */
enum profile_quality quality () const { return m_quality; }
/* Output THIS to F. */ /* Output THIS to F. */
void dump (FILE *f) const; void dump (FILE *f) const;
...@@ -675,7 +690,6 @@ private: ...@@ -675,7 +690,6 @@ private:
return ipa_p () == other.ipa_p (); return ipa_p () == other.ipa_p ();
} }
public: public:
/* Used for counters which are expected to be never executed. */ /* Used for counters which are expected to be never executed. */
static profile_count zero () static profile_count zero ()
{ {
...@@ -737,6 +751,9 @@ public: ...@@ -737,6 +751,9 @@ public:
return m_quality == profile_precise; return m_quality == profile_precise;
} }
/* Get the value of the count. */
uint32_t value () const { return m_val; }
/* Get the quality of the count. */ /* Get the quality of the count. */
enum profile_quality quality () const { return m_quality; } enum profile_quality quality () const { return m_quality; }
...@@ -1136,7 +1153,8 @@ public: ...@@ -1136,7 +1153,8 @@ public:
/* The profiling runtime uses gcov_type, which is usually 64bit integer. /* The profiling runtime uses gcov_type, which is usually 64bit integer.
Conversions back and forth are used to read the coverage and get it Conversions back and forth are used to read the coverage and get it
into internal representation. */ into internal representation. */
static profile_count from_gcov_type (gcov_type v); static profile_count from_gcov_type (gcov_type v,
profile_quality quality = profile_precise);
/* LTO streaming support. */ /* LTO streaming support. */
static profile_count stream_in (struct lto_input_block *); static profile_count stream_in (struct lto_input_block *);
......
2019-05-09 Martin Liska <mliska@suse.cz>
* gcc.dg/gimplefe-37.c: New test.
* gcc.dg/gimplefe-33.c: Likewise.
2019-05-09 Paolo Carlini <paolo.carlini@oracle.com> 2019-05-09 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/90382 PR c++/90382
......
/* { dg-do compile } */
/* { dg-options "-O2 -fgimple -fdump-tree-optimized --param=gimple-fe-computed-hot-bb-threshold=10 " } */
int __GIMPLE (ssa,startwith("slsr"),precise(3))
main (int argc)
{
int _1;
__BB(2,precise(3)):
if (argc_2(D) == 2)
goto __BB3(precise(44739243));
else
goto __BB4(precise(89478485));
__BB(3,precise(1)):
goto __BB4(precise(134217728));
__BB(4,precise(3)):
_1 = __PHI (__BB2: 0, __BB3: 12);
return _1;
}
/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[count: 3" 2 "optimized" } } */
/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[count: 2" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[33\\\.33%\\\]" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[66\\\.67%\\\]" 1 "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fgimple -fdump-tree-slsr" } */
int __GIMPLE (ssa,startwith("slsr"),guessed_local(1073741824))
main (int argc)
{
int _1;
__BB(2,guessed_local(1073741824)):
if (argc_2(D) == 2)
goto __BB3(guessed(16777216));
else
goto __BB4(guessed(117440512));
__BB(3,guessed_local(134217728)):
goto __BB4(precise(134217728));
__BB(4,guessed_local(1073741824)):
_1 = __PHI (__BB2: 0, __BB3: 12);
return _1;
}
/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local count: 1073741824" 2 "slsr" } } */
/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local count: 134217728" 1 "slsr" } } */
/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[12\\\.50%\\\]" 1 "slsr" } } */
/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[87\\\.50%\\\]" 1 "slsr" } } */
...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3. If not see
#include "selftest.h" #include "selftest.h"
#include "opts.h" #include "opts.h"
#include "asan.h" #include "asan.h"
#include "profile.h"
/* This file contains functions for building the Control Flow Graph (CFG) /* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */ for a function tree. */
...@@ -7872,13 +7873,32 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags) ...@@ -7872,13 +7873,32 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
current_function_decl = fndecl; current_function_decl = fndecl;
if (flags & TDF_GIMPLE) if (flags & TDF_GIMPLE)
{ {
static bool hotness_bb_param_printed = false;
if (profile_info != NULL
&& !hotness_bb_param_printed)
{
hotness_bb_param_printed = true;
fprintf (file,
"/* --param=gimple-fe-computed-hot-bb-threshold=%" PRId64
" */\n", get_hot_bb_threshold ());
}
print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)), print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)),
dump_flags | TDF_SLIM); dump_flags | TDF_SLIM);
fprintf (file, " __GIMPLE (%s)\n%s (", fprintf (file, " __GIMPLE (%s",
(fun->curr_properties & PROP_ssa) ? "ssa" (fun->curr_properties & PROP_ssa) ? "ssa"
: (fun->curr_properties & PROP_cfg) ? "cfg" : (fun->curr_properties & PROP_cfg) ? "cfg"
: "", : "");
function_name (fun));
if (cfun->cfg)
{
basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
if (bb->count.initialized_p ())
fprintf (file, ",%s(%d)",
profile_quality_as_string (bb->count.quality ()),
bb->count.value ());
fprintf (file, ")\n%s (", function_name (fun));
}
} }
else else
fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : ""); fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment