aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/gimple-parser.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2019-05-09 15:03:28 +0200
committerMartin Liska <marxin@gcc.gnu.org>2019-05-09 13:03:28 +0000
commitd276406ac1e7fc7f9c380325c994cf477b3d6fb8 (patch)
treeaaacbcded0429a0522a06ff2c662c5f3910bcaf4 /gcc/c/gimple-parser.c
parent555dbc42b2dfed0c9e70e9e53fcd569f82aeae02 (diff)
downloadgcc-d276406ac1e7fc7f9c380325c994cf477b3d6fb8.zip
gcc-d276406ac1e7fc7f9c380325c994cf477b3d6fb8.tar.gz
gcc-d276406ac1e7fc7f9c380325c994cf477b3d6fb8.tar.bz2
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
Diffstat (limited to 'gcc/c/gimple-parser.c')
-rw-r--r--gcc/c/gimple-parser.c183
1 files changed, 161 insertions, 22 deletions
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index fff3460..ede5a92 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-phinodes.h"
#include "tree-into-ssa.h"
#include "bitmap.h"
+#include "params.h"
/* GIMPLE parser state. */
@@ -81,20 +82,23 @@ struct gimple_parser
int src;
int dest;
int flags;
+ profile_probability probability;
};
auto_vec<gimple_parser_edge> edges;
basic_block current_bb;
- void push_edge (int, int, int);
+ void push_edge (int, int, int, profile_probability);
};
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;
e.src = src;
e.dest = dest;
e.flags = flags;
+ e.probability = prob;
edges.safe_push (e);
}
@@ -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>
- in *INDEX. Return true if so. */
+ in *INDEX. */
static bool
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;
}
+/* 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". */
void
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_seq seq = NULL;
@@ -209,9 +279,12 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
add_local_decl (cfun, var);
/* We have a CFG. Build the edges. */
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),
- parser.edges[i].flags);
+ {
+ edge e = make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
+ BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
+ parser.edges[i].flags);
+ e->probability = parser.edges[i].probability;
+ }
/* Add edges for case labels. */
basic_block bb;
FOR_EACH_BB_FN (bb, cfun)
@@ -274,6 +347,13 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
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);
}
@@ -337,11 +417,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_NAME))
{
- c_parser_gimple_goto_stmt (parser, loc,
- c_parser_peek_token
- (parser)->value,
- seq);
+ tree label = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
+ c_parser_gimple_goto_stmt (parser, loc, label, seq);
if (! c_parser_require (parser, CPP_SEMICOLON,
"expected %<;%>"))
return return_p;
@@ -355,7 +433,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
"expected %<;%>"))
return return_p;
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;
default:
goto expr_stmt;
@@ -397,6 +476,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
return return_p;
}
int is_loop_header_of = -1;
+ profile_count bb_count = profile_count::uninitialized ();
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_COMMA))
{
@@ -430,10 +510,39 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
"expected %<)%>"))
return return_p;
}
+ /* Parse profile: quality(value) */
else
{
- c_parser_error (parser, "unknown block specifier");
- return return_p;
+ tree q;
+ 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,
@@ -470,7 +579,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
last_basic_block_for_fn (cfun) = index + 1;
n_basic_blocks_for_fn (cfun)++;
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. */
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)
loop_father = get_loop (cfun, is_loop_header_of);
}
bb->loop_father = loop_father;
+ bb->count = bb_count;
/* Stmts now go to the new block. */
parser.current_bb = bb;
@@ -1609,8 +1720,10 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
return;
c_parser_consume_token (parser);
+ specs->entry_bb_count = profile_count::uninitialized ();
while (c_parser_next_token_is (parser, CPP_NAME))
{
+ profile_quality quality;
const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
c_parser_consume_token (parser);
if (! strcmp (op, "startwith"))
@@ -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 %<(%>"))
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)
/* Allow only one IL specifier and none on RTL. */
;
@@ -1757,10 +1890,12 @@ c_parser_gimple_goto_stmt (gimple_parser &parser,
if (cfun->curr_properties & PROP_cfg)
{
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,
- EDGE_FALLTHRU);
+ EDGE_FALLTHRU, prob);
return;
}
}
@@ -1811,10 +1946,12 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
label = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
int dest_index;
+ profile_probability prob;
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,
- EDGE_TRUE_VALUE);
+ EDGE_TRUE_VALUE, prob);
else
t_label = lookup_label_for_goto (loc, label);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
@@ -1844,14 +1981,16 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
return;
}
label = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
int dest_index;
+ profile_probability prob;
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,
- EDGE_FALSE_VALUE);
+ EDGE_FALSE_VALUE, prob);
else
f_label = lookup_label_for_goto (loc, label);
- c_parser_consume_token (parser);
if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
return;
}