This patch makes the previous one less conservative by looking whether
there are known ipa-modref loads from areas covered by the IPA-CP
aggregate constant entry in question.  Because ipa-modref relies on
alias information which IPA-CP does not have (yet), the test is much
more crude and only reports overlapping accesses with known offsets
and max_size.

I was not able to put together a testcase which would fail without
this patch however.  It basically needs to be a combination of
testcases for PR 92497 (so that IPA-CP transformation phase is not
enough), PR 111157 (to get a load) and PR 103669 (to get a
clobber/kill) in a way that ipa-modref can still track things.
Therefore I am not sure if we actually want this patch.

gcc/ChangeLog:

2023-10-04  Martin Jambor  <mjam...@suse.cz>

        * ipa-modref.cc (ipcp_argagg_and_access_must_overlap_p): New function.
        (ipcp_argagg_and_modref_tree_must_overlap_p): Likewise.
        (update_signature): Use ipcp_argagg_and_modref_tree_must_overlap_p.

Combined third step
---
 gcc/ipa-modref.cc | 65 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index a8fcf159259..d2bfca3445d 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -4090,6 +4090,64 @@ ipcp_argagg_and_kill_overlap_p (const ipa_argagg_value 
&v,
   return false;
 }
 
+/* Return true if V overlaps with ACCESS_NODE.  When in doubt, return
+   false.  */
+
+static bool
+ipcp_argagg_and_access_must_overlap_p (const ipa_argagg_value &v,
+                                      const modref_access_node &access_node)
+{
+  if (access_node.parm_index == MODREF_GLOBAL_MEMORY_PARM
+      || access_node.parm_index == MODREF_UNKNOWN_PARM
+      || access_node.parm_index == MODREF_GLOBAL_MEMORY_PARM)
+      return false;
+
+  if (access_node.parm_index == v.index)
+    {
+      if (!access_node.parm_offset_known)
+       return false;
+
+      poly_int64 repl_size;
+      bool ok = poly_int_tree_p (TYPE_SIZE (TREE_TYPE (v.value)),
+                                &repl_size);
+      gcc_assert (ok);
+      poly_int64 repl_offset (v.unit_offset);
+      repl_offset <<= LOG2_BITS_PER_UNIT;
+      poly_int64 combined_offset
+       = (access_node.parm_offset << LOG2_BITS_PER_UNIT) + access_node.offset;
+      if (ranges_maybe_overlap_p (repl_offset, repl_size,
+                                 combined_offset, access_node.max_size))
+       return true;
+    }
+  return false;
+}
+
+/* Return true if MT contains an access that certainly overlaps with V even
+   when we cannot evaluate alias references.  When in doubt, return false.  */
+
+template <typename base>
+static bool
+ipcp_argagg_and_modref_tree_must_overlap_p (const ipa_argagg_value &v,
+                                           const modref_tree<base> &mt)
+{
+  for (auto base_node : mt.bases)
+    {
+      if (base_node->every_ref)
+       return false;
+      for (auto ref_node : base_node->refs)
+       {
+         if (ref_node->every_access)
+           return false;
+         for (auto access_node : ref_node->accesses)
+           {
+             if (ipcp_argagg_and_access_must_overlap_p (v, access_node))
+               return true;
+           }
+       }
+    }
+  return false;
+}
+
 /* If signature changed, update the summary.  */
 
 static void
@@ -4111,14 +4169,17 @@ update_signature (struct cgraph_node *node)
          continue;
        if (r)
          for (const modref_access_node &kill : r->kills)
-           if (ipcp_argagg_and_kill_overlap_p (v, kill))
+           if (ipcp_argagg_and_kill_overlap_p (v, kill)
+               && !ipcp_argagg_and_modref_tree_must_overlap_p (v, *r->loads))
              {
                v.killed = true;
                break;
              }
        if (!v.killed && r_lto)
          for (const modref_access_node &kill : r_lto->kills)
-           if (ipcp_argagg_and_kill_overlap_p (v, kill))
+           if (ipcp_argagg_and_kill_overlap_p (v, kill)
+               && !ipcp_argagg_and_modref_tree_must_overlap_p (v,
+                                                               *r_lto->loads))
              {
                v.killed = 1;
                break;
-- 
2.42.0

Reply via email to