diff options
author | Martin Liska <mliska@suse.cz> | 2019-05-09 15:03:28 +0200 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2019-05-09 13:03:28 +0000 |
commit | d276406ac1e7fc7f9c380325c994cf477b3d6fb8 (patch) | |
tree | aaacbcded0429a0522a06ff2c662c5f3910bcaf4 /gcc/c/gimple-parser.c | |
parent | 555dbc42b2dfed0c9e70e9e53fcd569f82aeae02 (diff) | |
download | gcc-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.c | 183 |
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; } |