Hi. The patch adds support for profile for GIMPLE FE. That can be useful in the future.
Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed after stage1 opens? Thanks, Martin gcc/ChangeLog: 2019-04-05 Martin Liska <mli...@suse.cz> * gimple-pretty-print.c (dump_gimple_bb_header): Dump BB count. (pp_cfg_jump): Dump edge probability. * profile-count.h (get_raw_value): New function. (from_raw_value): Likewise. gcc/c/ChangeLog: 2019-04-05 Martin Liska <mli...@suse.cz> * gimple-parser.c (struct gimple_parser): Add frequency for gimple_parser_edge. (gimple_parser::push_edge): Add new argument frequency. (c_parser_gimple_parse_bb_spec): Parse also frequency 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. gcc/testsuite/ChangeLog: 2019-04-05 Martin Liska <mli...@suse.cz> * gcc.dg/gimplefe-37.c: New test. --- gcc/c/gimple-parser.c | 116 +++++++++++++++++++++++------ gcc/gimple-pretty-print.c | 8 ++ gcc/profile-count.h | 15 ++++ gcc/testsuite/gcc.dg/gimplefe-37.c | 27 +++++++ 4 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/gimplefe-37.c
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index fff34606dae..082f84de3ac 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -81,20 +81,22 @@ struct gimple_parser int src; int dest; int flags; + int frequency; }; auto_vec<gimple_parser_edge> edges; basic_block current_bb; - void push_edge (int, int, int); + void push_edge (int, int, int, int); }; void -gimple_parser::push_edge (int src, int dest, int flags) +gimple_parser::push_edge (int src, int dest, int flags, int frequency) { gimple_parser_edge e; e.src = src; e.dest = dest; e.flags = flags; + e.frequency = frequency; edges.safe_push (e); } @@ -120,10 +122,12 @@ 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. Return true if so and parse also FREQUENCY of + the edge. */ static bool -c_parser_gimple_parse_bb_spec (tree val, int *index) +c_parser_gimple_parse_bb_spec (tree val, gimple_parser &parser, + int *index, int *frequency) { if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0) return false; @@ -131,7 +135,33 @@ c_parser_gimple_parse_bb_spec (tree val, int *index) if (!ISDIGIT (*p)) return false; *index = atoi (IDENTIFIER_POINTER (val) + 4); - return *index > 0; + + if (*index > 0) + { + *frequency = -1; + /* 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_NUMBER) + || (TREE_CODE (f = c_parser_peek_token (parser)->value) + != INTEGER_CST)) + { + c_parser_error (parser, "expected frequency value"); + return false; + } + + *frequency = TREE_INT_CST_LOW (f); + c_parser_consume_token (parser); + 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". */ @@ -209,9 +239,14 @@ 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); + if (parser.edges[i].frequency != -1) + e->probability + = profile_probability::from_raw_value (parser.edges[i].frequency); + } /* Add edges for case labels. */ basic_block bb; FOR_EACH_BB_FN (bb, cfun) @@ -274,6 +309,8 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, fix_loop_structure (NULL); } + if (cfun->curr_properties & PROP_cfg) + update_max_bb_count (); dump_function (TDI_gimple, current_function_decl); } @@ -337,11 +374,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 +390,7 @@ 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, -1); break; default: goto expr_stmt; @@ -397,6 +432,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) return return_p; } int is_loop_header_of = -1; + int bb_count = -1; c_parser_consume_token (parser); while (c_parser_next_token_is (parser, CPP_COMMA)) { @@ -430,6 +466,30 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) "expected %<)%>")) return return_p; } + /* count (NUM) */ + else if (!strcmp (IDENTIFIER_POINTER + (c_parser_peek_token (parser)->value), + "count")) + { + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_OPEN_PAREN, + "expected %<(%>")) + return return_p; + tree count; + if (! c_parser_next_token_is (parser, CPP_NUMBER) + || TREE_CODE (count + = c_parser_peek_token (parser)->value) + != INTEGER_CST) + { + c_parser_error (parser, "expected count value"); + return return_p; + } + c_parser_consume_token (parser); + bb_count = TREE_INT_CST_LOW (count); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, + "expected %<)%>")) + return return_p; + } else { c_parser_error (parser, "unknown block specifier"); @@ -470,7 +530,7 @@ 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, -1); /* We leave the proper setting to fixup. */ struct loop *loop_father = loops_for_fn (cfun)->tree_root; @@ -499,6 +559,10 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) } bb->loop_father = loop_father; + if (bb_count != -1) + bb->count + = profile_count::from_gcov_type (bb_count).guessed_local (); + /* Stmts now go to the new block. */ parser.current_bb = bb; break; @@ -688,7 +752,9 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq) if (c_parser_next_token_is (parser, CPP_COLON)) c_parser_consume_token (parser); int src_index = -1; - if (!c_parser_gimple_parse_bb_spec (arg, &src_index)) + int frequency; + if (!c_parser_gimple_parse_bb_spec (arg, parser, &src_index, + &frequency)) c_parser_error (parser, "invalid source block specification"); vargs.safe_push (size_int (src_index)); } @@ -1757,10 +1823,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)) + int frequency; + if (c_parser_gimple_parse_bb_spec (label, parser, &dest_index, + &frequency)) { parser.push_edge (parser.current_bb->index, dest_index, - EDGE_FALLTHRU); + EDGE_FALLTHRU, frequency); return; } } @@ -1811,10 +1879,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; + int frequency; if ((cfun->curr_properties & PROP_cfg) - && c_parser_gimple_parse_bb_spec (label, &dest_index)) + && c_parser_gimple_parse_bb_spec (label, parser, &dest_index, + &frequency)) parser.push_edge (parser.current_bb->index, dest_index, - EDGE_TRUE_VALUE); + EDGE_TRUE_VALUE, frequency); else t_label = lookup_label_for_goto (loc, label); if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) @@ -1844,14 +1914,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; + int frequency; if ((cfun->curr_properties & PROP_cfg) - && c_parser_gimple_parse_bb_spec (label, &dest_index)) + && c_parser_gimple_parse_bb_spec (label, parser, &dest_index, + &frequency)) parser.push_edge (parser.current_bb->index, dest_index, - EDGE_FALSE_VALUE); + EDGE_FALSE_VALUE, frequency); else f_label = lookup_label_for_goto (loc, label); - c_parser_consume_token (parser); if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) return; } diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 69bae0d10d0..b5fca58aa07 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -2704,6 +2704,8 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, fprintf (outf, "%*s__BB(%d", indent, "", bb->index); if (bb->loop_father->header == bb) fprintf (outf, ",loop_header(%d)", bb->loop_father->num); + if (bb->count.initialized_p ()) + fprintf (outf, ",count(%" PRId64 ")", bb->count.to_gcov_type ()); fprintf (outf, "):\n"); } else @@ -2760,6 +2762,12 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t flags) { pp_string (buffer, "goto __BB"); pp_decimal_int (buffer, e->dest->index); + if (e->probability.initialized_p ()) + { + pp_string (buffer, "("); + pp_decimal_int (buffer, e->probability.get_raw_value ()); + pp_string (buffer, ")"); + } pp_semicolon (buffer); } else diff --git a/gcc/profile-count.h b/gcc/profile-count.h index d6de61f0a61..8d978e14e00 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -564,6 +564,21 @@ public: /* Print THIS to stderr. */ void debug () const; + /* Get m_val for GIMPLE FE. */ + uint32_t get_raw_value () const + { + return m_val; + } + + /* Build guessed profiled based on VALUE (in GIMPLE FE). */ + static profile_probability from_raw_value (uint32_t value) + { + profile_probability ret; + ret.m_val = value; + ret.m_quality = profile_guessed; + return ret; + } + /* Return true if THIS is known to differ significantly from OTHER. */ bool differs_from_p (profile_probability other) const; /* Return if difference is greater than 50%. */ diff --git a/gcc/testsuite/gcc.dg/gimplefe-37.c b/gcc/testsuite/gcc.dg/gimplefe-37.c new file mode 100644 index 00000000000..2872eb03051 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gimplefe-37.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fgimple -fdump-tree-optimized" } */ + +int __GIMPLE (ssa,startwith("slsr")) +main (int argc) +{ + int _1; + + __BB(2,count(3)): + if (argc_2(D) == 2) + goto __BB3(44739243); + else + goto __BB4(89478485); + + __BB(3,count(1)): + goto __BB4(134217728); + + __BB(4,count(3)): + _1 = __PHI (__BB2: 0, __BB3: 12); + return _1; +} + + +/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local count: 3" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local 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" } } */