Hi Martin, > Honza, is it OK for trunk? Tamar, can you please double check it fixes > your problem with perlbench? >
Thanks for working on this! Yes it does seem to fix the regression as well. Cheers, Tamar > Thanks, > > Martin > > > ipa-cp: Avoid wrongly gathering self-recursive edges (PR 93707) > > 2020-02-18 Martin Jambor <mjam...@suse.cz> > Feng Xue <f...@os.amperecomputing.com> > > PR ipa/93707 > * ipa-cp.c (same_node_or_its_all_contexts_clone_p): Replaced with > new function calls_same_node_or_its_all_contexts_clone_p. > (cgraph_edge_brings_value_p): Use it. Fix comment. > (cgraph_edge_brings_value_p): Likewise. > > testsuite/ > * gcc.dg/ipa/pr93707.c: New test. > --- > gcc/ChangeLog | 9 +++++++++ > gcc/ipa-cp.c | 29 ++++++++++++++--------------- > gcc/testsuite/ChangeLog | 6 ++++++ > gcc/testsuite/gcc.dg/ipa/pr93707.c | 29 > +++++++++++++++++++++++++++++ > 4 files changed, 58 insertions(+), 15 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/ipa/pr93707.c > > diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c > index 4f5b72e6994..4609375bf8d 100644 > --- a/gcc/ipa-cp.c > +++ b/gcc/ipa-cp.c > @@ -4033,15 +4033,23 @@ edge_clone_summary_t::duplicate > (cgraph_edge *src_edge, cgraph_edge *dst_edge, > src_data->next_clone = dst_edge; > } > > -/* Return true is NODE is DEST or its clone for all contexts. */ > +/* Return true is CS calls DEST or its clone for all contexts, except for > + self-recursive nodes in which it has to be DEST itself. */ > > static bool > -same_node_or_its_all_contexts_clone_p (cgraph_node *node, > cgraph_node *dest) > +calls_same_node_or_its_all_contexts_clone_p (cgraph_edge *cs, > cgraph_node *dest) > { > - if (node == dest) > + enum availability availability; > + cgraph_node *callee = cs->callee->function_symbol (&availability); > + > + if (availability <= AVAIL_INTERPOSABLE) > + return false; > + if (callee == dest) > return true; > + if (cs->caller == callee) > + return false; > > - class ipa_node_params *info = IPA_NODE_REF (node); > + class ipa_node_params *info = IPA_NODE_REF (callee); > return info->is_all_contexts_clone && info->ipcp_orig_node == dest; > } > > @@ -4053,11 +4061,8 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, > ipcp_value_source<tree> *src, > cgraph_node *dest, ipcp_value<tree> *dest_val) > { > class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); > - enum availability availability; > - cgraph_node *real_dest = cs->callee->function_symbol (&availability); > > - if (availability <= AVAIL_INTERPOSABLE > - || !same_node_or_its_all_contexts_clone_p (real_dest, dest) > + if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest) > || caller_info->node_dead) > return false; > > @@ -4076,9 +4081,6 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, > ipcp_value_source<tree> *src, > } > else > { > - /* At the moment we do not propagate over arithmetic jump functions in > - SCCs, so it is safe to detect self-feeding recursive calls in this > - way. */ > if (src->val == dest_val) > return true; > > @@ -4113,11 +4115,8 @@ cgraph_edge_brings_value_p (cgraph_edge *cs, > ipcp_value<ipa_polymorphic_call_context> *) > { > class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); > - enum availability avail; > - cgraph_node *real_dest = cs->callee->function_symbol (&avail); > > - if (avail <= AVAIL_INTERPOSABLE > - || !same_node_or_its_all_contexts_clone_p (real_dest, dest) > + if (!calls_same_node_or_its_all_contexts_clone_p (cs, dest) > || caller_info->node_dead) > return false; > if (!src->val) > diff --git a/gcc/testsuite/gcc.dg/ipa/pr93707.c > b/gcc/testsuite/gcc.dg/ipa/pr93707.c > new file mode 100644 > index 00000000000..e200a3a432b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/ipa/pr93707.c > @@ -0,0 +1,29 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O3 --param ipa-cp-eval-threshold=1" } */ > + > +int foo(); > +int data[100]; > + > +__attribute__((noinline)) static int recur_fn (int i, int j, int depth) > +{ > + if (depth > 10) > + return 1; > + > + data[i + j]++; > + > + if (depth & 3) > + recur_fn (i, 1, depth + 1); > + else > + recur_fn (i, j & 1, depth + 1); > + > + foo(); > + > + return i + j; > +} > + > +int caller (int v, int depth) > +{ > + recur_fn (1, v, depth); > + > + return 0; > +} > -- > 2.25.0