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. */
......
...@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-phinodes.h" #include "tree-phinodes.h"
#include "tree-into-ssa.h" #include "tree-into-ssa.h"
#include "bitmap.h" #include "bitmap.h"
#include "params.h"
/* GIMPLE parser state. */ /* GIMPLE parser state. */
...@@ -81,20 +82,23 @@ struct gimple_parser ...@@ -81,20 +82,23 @@ struct gimple_parser
int src; int src;
int dest; int dest;
int flags; int flags;
profile_probability probability;
}; };
auto_vec<gimple_parser_edge> edges; auto_vec<gimple_parser_edge> edges;
basic_block current_bb; basic_block current_bb;
void push_edge (int, int, int); void push_edge (int, int, int, profile_probability);
}; };
void void
gimple_parser::push_edge (int src, int dest, int flags) gimple_parser::push_edge (int src, int dest, int flags,
profile_probability prob)
{ {
gimple_parser_edge e; gimple_parser_edge e;
e.src = src; e.src = src;
e.dest = dest; e.dest = dest;
e.flags = flags; e.flags = flags;
e.probability = prob;
edges.safe_push (e); edges.safe_push (e);
} }
...@@ -120,7 +124,7 @@ static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *); ...@@ -120,7 +124,7 @@ static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
/* See if VAL is an identifier matching __BB<num> and return <num> /* See if VAL is an identifier matching __BB<num> and return <num>
in *INDEX. Return true if so. */ in *INDEX. */
static bool static bool
c_parser_gimple_parse_bb_spec (tree val, int *index) c_parser_gimple_parse_bb_spec (tree val, int *index)
...@@ -134,11 +138,77 @@ c_parser_gimple_parse_bb_spec (tree val, int *index) ...@@ -134,11 +138,77 @@ c_parser_gimple_parse_bb_spec (tree val, int *index)
return *index > 0; return *index > 0;
} }
/* See if VAL is an identifier matching __BB<num> and return <num>
in *INDEX. Return true if so and parse also FREQUENCY of
the edge. */
static bool
c_parser_gimple_parse_bb_spec_edge_probability (tree val,
gimple_parser &parser,
int *index,
profile_probability *probablity)
{
bool return_p = c_parser_gimple_parse_bb_spec (val, index);
if (return_p)
{
*probablity = profile_probability::uninitialized ();
/* Parse frequency if provided. */
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
tree f;
c_parser_consume_token (parser);
if (!c_parser_next_token_is (parser, CPP_NAME))
{
c_parser_error (parser, "expected frequency quality");
return false;
}
profile_quality quality;
const char *v
= IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (!parse_profile_quality (v, &quality))
{
c_parser_error (parser, "unknown profile quality");
return false;
}
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return false;
if (!c_parser_next_token_is (parser, CPP_NUMBER)
|| (TREE_CODE (f = c_parser_peek_token (parser)->value)
!= INTEGER_CST))
{
c_parser_error (parser, "expected frequency value");
return false;
}
unsigned int value = TREE_INT_CST_LOW (f);
*probablity = profile_probability (value, quality);
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
return false;
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
return false;
}
return true;
}
return false;
}
/* Parse the body of a function declaration marked with "__GIMPLE". */ /* Parse the body of a function declaration marked with "__GIMPLE". */
void void
c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
enum c_declspec_il cdil) enum c_declspec_il cdil,
profile_count entry_bb_count)
{ {
gimple_parser parser (cparser); gimple_parser parser (cparser);
gimple_seq seq = NULL; gimple_seq seq = NULL;
...@@ -209,9 +279,12 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, ...@@ -209,9 +279,12 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
add_local_decl (cfun, var); add_local_decl (cfun, var);
/* We have a CFG. Build the edges. */ /* We have a CFG. Build the edges. */
for (unsigned i = 0; i < parser.edges.length (); ++i) for (unsigned i = 0; i < parser.edges.length (); ++i)
make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src), {
BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest), edge e = make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
parser.edges[i].flags); BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
parser.edges[i].flags);
e->probability = parser.edges[i].probability;
}
/* Add edges for case labels. */ /* Add edges for case labels. */
basic_block bb; basic_block bb;
FOR_EACH_BB_FN (bb, cfun) FOR_EACH_BB_FN (bb, cfun)
...@@ -274,6 +347,13 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, ...@@ -274,6 +347,13 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
fix_loop_structure (NULL); fix_loop_structure (NULL);
} }
if (cfun->curr_properties & PROP_cfg)
{
ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = entry_bb_count;
gcov_type t = PARAM_VALUE (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD);
set_hot_bb_threshold (t);
update_max_bb_count ();
}
dump_function (TDI_gimple, current_function_decl); dump_function (TDI_gimple, current_function_decl);
} }
...@@ -337,11 +417,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -337,11 +417,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME)) if (c_parser_next_token_is (parser, CPP_NAME))
{ {
c_parser_gimple_goto_stmt (parser, loc, tree label = c_parser_peek_token (parser)->value;
c_parser_peek_token
(parser)->value,
seq);
c_parser_consume_token (parser); c_parser_consume_token (parser);
c_parser_gimple_goto_stmt (parser, loc, label, seq);
if (! c_parser_require (parser, CPP_SEMICOLON, if (! c_parser_require (parser, CPP_SEMICOLON,
"expected %<;%>")) "expected %<;%>"))
return return_p; return return_p;
...@@ -355,7 +433,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -355,7 +433,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
"expected %<;%>")) "expected %<;%>"))
return return_p; return return_p;
if (cfun->curr_properties & PROP_cfg) if (cfun->curr_properties & PROP_cfg)
parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0); parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0,
profile_probability::uninitialized ());
break; break;
default: default:
goto expr_stmt; goto expr_stmt;
...@@ -397,6 +476,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -397,6 +476,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
return return_p; return return_p;
} }
int is_loop_header_of = -1; int is_loop_header_of = -1;
profile_count bb_count = profile_count::uninitialized ();
c_parser_consume_token (parser); c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_COMMA)) while (c_parser_next_token_is (parser, CPP_COMMA))
{ {
...@@ -430,10 +510,39 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -430,10 +510,39 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
"expected %<)%>")) "expected %<)%>"))
return return_p; return return_p;
} }
/* Parse profile: quality(value) */
else else
{ {
c_parser_error (parser, "unknown block specifier"); tree q;
return return_p; profile_quality quality;
tree v = c_parser_peek_token (parser)->value;
if (!parse_profile_quality (IDENTIFIER_POINTER (v),
&quality))
{
c_parser_error (parser, "unknown block specifier");
return false;
}
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN,
"expected %<(%>"))
return false;
if (!c_parser_next_token_is (parser, CPP_NUMBER)
|| (TREE_CODE (q = c_parser_peek_token (parser)->value)
!= INTEGER_CST))
{
c_parser_error (parser, "expected count value");
return false;
}
bb_count
= profile_count::from_gcov_type (TREE_INT_CST_LOW (q),
quality);
c_parser_consume_token (parser);
if (! c_parser_require (parser, CPP_CLOSE_PAREN,
"expected %<)%>"))
return return_p;
} }
} }
if (! c_parser_require (parser, CPP_CLOSE_PAREN, if (! c_parser_require (parser, CPP_CLOSE_PAREN,
...@@ -470,7 +579,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -470,7 +579,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
last_basic_block_for_fn (cfun) = index + 1; last_basic_block_for_fn (cfun) = index + 1;
n_basic_blocks_for_fn (cfun)++; n_basic_blocks_for_fn (cfun)++;
if (!parser.current_bb) if (!parser.current_bb)
parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU); parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU,
profile_probability::always ());
/* We leave the proper setting to fixup. */ /* We leave the proper setting to fixup. */
struct loop *loop_father = loops_for_fn (cfun)->tree_root; struct loop *loop_father = loops_for_fn (cfun)->tree_root;
...@@ -498,6 +608,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) ...@@ -498,6 +608,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
loop_father = get_loop (cfun, is_loop_header_of); loop_father = get_loop (cfun, is_loop_header_of);
} }
bb->loop_father = loop_father; bb->loop_father = loop_father;
bb->count = bb_count;
/* Stmts now go to the new block. */ /* Stmts now go to the new block. */
parser.current_bb = bb; parser.current_bb = bb;
...@@ -1609,8 +1720,10 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs) ...@@ -1609,8 +1720,10 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
return; return;
c_parser_consume_token (parser); c_parser_consume_token (parser);
specs->entry_bb_count = profile_count::uninitialized ();
while (c_parser_next_token_is (parser, CPP_NAME)) while (c_parser_next_token_is (parser, CPP_NAME))
{ {
profile_quality quality;
const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
c_parser_consume_token (parser); c_parser_consume_token (parser);
if (! strcmp (op, "startwith")) if (! strcmp (op, "startwith"))
...@@ -1629,6 +1742,26 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs) ...@@ -1629,6 +1742,26 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>")) if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>"))
return; return;
} }
else if (parse_profile_quality (op, &quality))
{
tree q;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return;
if (!c_parser_next_token_is (parser, CPP_NUMBER)
|| (TREE_CODE (q = c_parser_peek_token (parser)->value)
!= INTEGER_CST))
{
c_parser_error (parser, "expected count value");
return;
}
specs->entry_bb_count
= profile_count::from_gcov_type (TREE_INT_CST_LOW (q), quality);
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
return;
}
else if (specs->declspec_il != cdil_gimple) else if (specs->declspec_il != cdil_gimple)
/* Allow only one IL specifier and none on RTL. */ /* Allow only one IL specifier and none on RTL. */
; ;
...@@ -1757,10 +1890,12 @@ c_parser_gimple_goto_stmt (gimple_parser &parser, ...@@ -1757,10 +1890,12 @@ c_parser_gimple_goto_stmt (gimple_parser &parser,
if (cfun->curr_properties & PROP_cfg) if (cfun->curr_properties & PROP_cfg)
{ {
int dest_index; int dest_index;
if (c_parser_gimple_parse_bb_spec (label, &dest_index)) profile_probability prob;
if (c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
&dest_index, &prob))
{ {
parser.push_edge (parser.current_bb->index, dest_index, parser.push_edge (parser.current_bb->index, dest_index,
EDGE_FALLTHRU); EDGE_FALLTHRU, prob);
return; return;
} }
} }
...@@ -1811,10 +1946,12 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq) ...@@ -1811,10 +1946,12 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
label = c_parser_peek_token (parser)->value; label = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser); c_parser_consume_token (parser);
int dest_index; int dest_index;
profile_probability prob;
if ((cfun->curr_properties & PROP_cfg) if ((cfun->curr_properties & PROP_cfg)
&& c_parser_gimple_parse_bb_spec (label, &dest_index)) && c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
&dest_index, &prob))
parser.push_edge (parser.current_bb->index, dest_index, parser.push_edge (parser.current_bb->index, dest_index,
EDGE_TRUE_VALUE); EDGE_TRUE_VALUE, prob);
else else
t_label = lookup_label_for_goto (loc, label); t_label = lookup_label_for_goto (loc, label);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
...@@ -1844,14 +1981,16 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq) ...@@ -1844,14 +1981,16 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
return; return;
} }
label = c_parser_peek_token (parser)->value; label = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
int dest_index; int dest_index;
profile_probability prob;
if ((cfun->curr_properties & PROP_cfg) if ((cfun->curr_properties & PROP_cfg)
&& c_parser_gimple_parse_bb_spec (label, &dest_index)) && c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
&dest_index, &prob))
parser.push_edge (parser.current_bb->index, dest_index, parser.push_edge (parser.current_bb->index, dest_index,
EDGE_FALSE_VALUE); EDGE_FALSE_VALUE, prob);
else else
f_label = lookup_label_for_goto (loc, label); f_label = lookup_label_for_goto (loc, label);
c_parser_consume_token (parser);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
return; return;
} }
......
...@@ -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