From: Feng Xue OS <fxue@os.amperecomputing.com>
To: Martin Jambor <mjambor@suse.cz>,
Tamar Christina <Tamar.Christina@arm.com>,
Jan Hubicka <hubicka@ucw.cz>,
"gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Cc: nd <nd@arm.com>
Subject: Re: [PATCH] Fix bug in recursiveness check for function to be cloned (ipa/pr93707)
Date: Sat, 22 Feb 2020 03:32:00 -0000 [thread overview]
Message-ID: <BYAPR01MB486919C39A40BCCC67D10ED3F7EE0@BYAPR01MB4869.prod.exchangelabs.com> (raw)
In-Reply-To: <ri61rqnu7qj.fsf@suse.cz>
It is a good solution.
Thanks,
Feng
________________________________________
From: Martin Jambor <mjambor@suse.cz>
Sent: Saturday, February 22, 2020 2:15 AM
To: Feng Xue OS; Tamar Christina; Jan Hubicka; gcc-patches@gcc.gnu.org
Cc: nd
Subject: Re: [PATCH] Fix bug in recursiveness check for function to be cloned (ipa/pr93707)
Hi,
On Thu, Feb 20 2020, Feng Xue OS wrote:
> This is a simpel and nice fix, but could suppress some CP opportunities for
> self-recursive call. Using the test case as example, the first should be a
> for-all-context clone, and the call "recur_fn (i, 1, depth + 1)" is replaced with
> a newly created recursive node. Thus, in the next round of CP iteration, the
> way to do CP for the 2nd arugment "1" is blocked, because its coming edge
> can not pass check by cgraph_edge_brings_value_p().
>
> +__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;
> +}
>
>
>>However, I believe that his approach mostly papers over a bug that
>>happens earlier, specifically that cgraph_edge_brings_value_p returned
>>true for the self-recursive edge from all-context clone to itself, even
>>though when evaluating the second argument. We assume that all context
>>clones get at least as many constants as any other potential clone, but
>>that does not work for self-recursive edges with pass-through parameters
>>that that just pass along the received constant.
>
> The following check on value in cgraph_edge_brings_value_p could ensure
> whether the value can arrive the dest node or not. If the value is a constant
> without source, as above example "1", this is allowed. Otherwise, code snippet
> enclosed by "if (caller_info->ipcp_orig_node)" could capture for-all-context clone.
there has not been any "following check" in your email but I believe I
understand what you mean, and I added such check to my patch so that the
edge carrying the non-pass through jump function was accepted by the
cgraph_edge_brings_value_p predicate.
However, that lead to the same assert in
find_more_scalar_values_for_callers_subset because on that edge it tried
to compute the depth + 1 value before it had any value to calculate it
from.
So after staring at the problem for another while I realized that the
users self_recursive_pass_through_p and
self_recursive_agg_pass_through_p would be OK if it returned false for
self-recursive calls from/to a node which is already a clone - clones
have their known constant values set at the point of their creation -
and that doing so avoids this problem. So that is what the patch below
does. I have still kept the cgraph_edge_brings_value_p hunks too, so
that edges are collected reliably.
Bootstrapped and tested on an x86_64-linux, LTO bootstrap underway.
What do you think?
Martin
2020-02-21 Martin Jambor <mjambor@suse.cz>
Feng Xue <fxue@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.
(cgraph_edge_brings_value_p): Likewise.
(self_recursive_pass_through_p): Return false if caller is a clone.
(self_recursive_agg_pass_through_p): Likewise.
testsuite/
* gcc.dg/ipa/pr93707.c: New test.
---
gcc/ChangeLog | 11 +++++++++
gcc/ipa-cp.c | 38 +++++++++++++++++-------------
gcc/testsuite/ChangeLog | 6 +++++
gcc/testsuite/gcc.dg/ipa/pr93707.c | 31 ++++++++++++++++++++++++
4 files changed, 69 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/ipa/pr93707.c
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7c481407de9..a965cae4f07 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2020-02-21 Martin Jambor <mjambor@suse.cz>
+ Feng Xue <fxue@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.
+ (cgraph_edge_brings_value_p): Likewise.
+ (self_recursive_pass_through_p): Return false if caller is a clone.
+ (self_recursive_agg_pass_through_p): Likewise.
+
2020-02-17 Richard Biener <rguenther@suse.de>
PR c/86134
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 4f5b72e6994..aa228df1204 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -4033,15 +4033,24 @@ 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,
+ bool allow_recursion_to_clone)
{
- 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 (!allow_recursion_to_clone && 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 +4062,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, !src->val)
|| caller_info->node_dead)
return false;
@@ -4076,9 +4082,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 +4116,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, true)
|| caller_info->node_dead)
return false;
if (!src->val)
@@ -4630,7 +4630,9 @@ self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i,
&& availability > AVAIL_INTERPOSABLE
&& jfunc->type == IPA_JF_PASS_THROUGH
&& (!simple || ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
- && ipa_get_jf_pass_through_formal_id (jfunc) == i)
+ && ipa_get_jf_pass_through_formal_id (jfunc) == i
+ && IPA_NODE_REF (cs->caller)
+ && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
return true;
return false;
}
@@ -4651,7 +4653,9 @@ self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
&& jfunc->offset == jfunc->value.load_agg.offset
&& (!simple || jfunc->value.pass_through.operation == NOP_EXPR)
&& jfunc->value.pass_through.formal_id == i
- && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type))
+ && useless_type_conversion_p (jfunc->value.load_agg.type, jfunc->type)
+ && IPA_NODE_REF (cs->caller)
+ && !IPA_NODE_REF (cs->caller)->ipcp_orig_node)
return true;
return false;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b326529ac75..e8c9f197e42 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-18 Martin Jambor <mjambor@suse.cz>
+ Feng Xue <fxue@os.amperecomputing.com>
+
+ PR ipa/93707
+ * gcc.dg/ipa/pr93707.c: New test.
+
2020-02-17 Richard Biener <rguenther@suse.de>
PR c/86134
diff --git a/gcc/testsuite/gcc.dg/ipa/pr93707.c b/gcc/testsuite/gcc.dg/ipa/pr93707.c
new file mode 100644
index 00000000000..685fae45020
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr93707.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 --param ipa-cp-eval-threshold=1 -fdump-ipa-cp" } */
+
+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;
+}
+
+/* { dg-final { scan-ipa-dump-times "Clone of recur_fn/" 2 "cp" } } */
--
2.25.0
next prev parent reply other threads:[~2020-02-22 3:32 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-25 13:52 [PATCH] Generalized value pass-through for self-recursive function (ipa/pr93203) Feng Xue OS
2020-01-25 16:17 ` [PATCH V2] " Feng Xue OS
2020-02-03 1:57 ` Ping* " Feng Xue OS
2020-02-05 17:27 ` Martin Jambor
2020-02-10 3:28 ` Feng Xue OS
2020-02-11 10:05 ` Tamar Christina
2020-02-11 13:10 ` Feng Xue OS
2020-02-11 14:31 ` Tamar Christina
2020-02-13 5:39 ` [PATCH] Fix bug in recursiveness check for function to be cloned (ipa/pr93707) Feng Xue OS
2020-02-17 8:44 ` Tamar Christina
2020-02-18 15:16 ` Ping: " Feng Xue OS
2020-02-19 16:28 ` Martin Jambor
2020-02-20 3:36 ` Feng Xue OS
2020-02-21 18:16 ` Martin Jambor
2020-02-22 3:32 ` Feng Xue OS [this message]
2020-02-24 15:41 ` Martin Jambor
2020-02-20 12:57 ` Tamar Christina
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=BYAPR01MB486919C39A40BCCC67D10ED3F7EE0@BYAPR01MB4869.prod.exchangelabs.com \
--to=fxue@os.amperecomputing.com \
--cc=Tamar.Christina@arm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=hubicka@ucw.cz \
--cc=mjambor@suse.cz \
--cc=nd@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).