Hello. In order to have valid profile, we should add counts of an edge only when it's really redirected and hasn't been redirected in previous invocation of the function.
Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. Ready to be installed? Martin gcc/ChangeLog: 2017-08-31 Martin Liska <mli...@suse.cz> PR tree-optimization/82059 * gimple-ssa-isolate-paths.c (isolate_path): Add profile and frequency only when an edge is redirected. gcc/testsuite/ChangeLog: 2017-08-31 Martin Liska <mli...@suse.cz> PR tree-optimization/82059 * gcc.dg/tree-ssa/pr82059.c: New test. --- gcc/gimple-ssa-isolate-paths.c | 9 ++++++--- gcc/testsuite/gcc.dg/tree-ssa/pr82059.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr82059.c
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index fbc41057463..807e0032410 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -160,14 +160,17 @@ isolate_path (basic_block bb, basic_block duplicate, for (ei = ei_start (duplicate->succs); (e2 = ei_safe_edge (ei)); ) remove_edge (e2); } - bb->frequency += EDGE_FREQUENCY (e); - bb->count += e->count; /* Complete the isolation step by redirecting E to reach DUPLICATE. */ e2 = redirect_edge_and_branch (e, duplicate); if (e2) - flush_pending_stmts (e2); + { + flush_pending_stmts (e2); + /* Update profile only when redirection is really processed. */ + bb->frequency += EDGE_FREQUENCY (e); + bb->count += e->count; + } /* There may be more than one statement in DUPLICATE which exhibits undefined behavior. Ultimately we want the first such statement in diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr82059.c b/gcc/testsuite/gcc.dg/tree-ssa/pr82059.c new file mode 100644 index 00000000000..0285b03cc04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr82059.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/82059 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-isolate-paths" } */ + +struct a +{ + char b; + struct a *c; +} d (), f; +void *e; +long g; +void +h () +{ + struct a *i = 0; + if (g) + i = e; + if (!i) + d (); + i->c = &f; + i->b = *(char *) h; +}