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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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" } } */