Hi,

ipa_polymorphic_call_context::equal_to happily ignores the speculative
part of the context if it is inconsistent with the known part.  While
this is OK for uses outside of IPA-CP, for this pass it cannot be done
because it happily drops the non-speculative part when jump functions
are not known to "preserve types."  This can then mean that two
contexts from which we can derive diferent "final" ones are
representeed as one in the IPA-CP lattice and then later IPA-CP is
confused when the (speculative) one that it has created a clone for is
not actually available from any caller.

I was only able to trigger this issue with all the patches pending
review applied and when I relaxed the IPA-CP parameters so much that
they created a clone for every opportunity , no matter how
non-profitable, and then tried to build 510.parest_r.  But still it is
a bug regardless of the patches and I believe the equal_to predicate
should not be used in this way.

Bootstrapped and tested on x86_64-linux, OK for master?

Thanks,

Martin


gcc/ChangeLog:

2025-12-05  Martin Jambor  <[email protected]>

        * cgraph.h (ipa_polymorphic_call_context::equal_to): Add parametr
        strict_speculation.
        * ipa-polymorphic-call.cc (ipa_polymorphic_call_context::equal_to):
        Likewise.
        * ipa-cp.cc (values_equal_for_ipcp_p): Pass true to strict_speculation
        of ipa_polymorphic_call_context::equal_to.
---
 gcc/cgraph.h                |  7 +++++--
 gcc/ipa-cp.cc               |  2 +-
 gcc/ipa-polymorphic-call.cc | 22 ++++++++++++++--------
 3 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 91b5de40cef..bca26ddfad1 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1684,8 +1684,11 @@ public:
 
   /* Return TRUE if context is fully useless.  */
   bool useless_p () const;
-  /* Return TRUE if this context conveys the same information as X.  */
-  bool equal_to (const ipa_polymorphic_call_context &x) const;
+  /* Return TRUE if this context conveys the same information as X.  If
+     STRICT_SPECULATION is true, compare the speculative part even when it is
+     inconsistent.  */
+  bool equal_to (const ipa_polymorphic_call_context &x,
+                bool strict_speculation = false) const;
 
   /* Dump human readable context to F.  If NEWLINE is true, it will be
      terminated by a newline.  */
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 65784761360..5bcca5f2dfa 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -2026,7 +2026,7 @@ static bool
 values_equal_for_ipcp_p (ipa_polymorphic_call_context x,
                         ipa_polymorphic_call_context y)
 {
-  return x.equal_to (y);
+  return x.equal_to (y, true);
 }
 
 
diff --git a/gcc/ipa-polymorphic-call.cc b/gcc/ipa-polymorphic-call.cc
index 09316de0e6b..7b7036f0f71 100644
--- a/gcc/ipa-polymorphic-call.cc
+++ b/gcc/ipa-polymorphic-call.cc
@@ -2368,11 +2368,13 @@ 
ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
     maybe_in_construction = true;
 }
 
-/* Return TRUE if this context conveys the same information as OTHER.  */
+/* Return TRUE if this context conveys the same information as X.  If
+   STRICT_SPECULATION is true, compare the speculative part even when it is
+   inconsistent.  */
 
 bool
 ipa_polymorphic_call_context::equal_to
-    (const ipa_polymorphic_call_context &x) const
+(const ipa_polymorphic_call_context &x, bool strict_speculation) const
 {
   if (useless_p ())
     return x.useless_p ();
@@ -2397,8 +2399,11 @@ ipa_polymorphic_call_context::equal_to
 
 
   if (speculative_outer_type
-      && speculation_consistent_p (speculative_outer_type, speculative_offset,
-                                  speculative_maybe_derived_type, NULL_TREE))
+      && (strict_speculation
+         || speculation_consistent_p (speculative_outer_type,
+                                      speculative_offset,
+                                      speculative_maybe_derived_type,
+                                      NULL_TREE)))
     {
       if (!x.speculative_outer_type)
        return false;
@@ -2412,10 +2417,11 @@ ipa_polymorphic_call_context::equal_to
        return false;
     }
   else if (x.speculative_outer_type
-          && x.speculation_consistent_p (x.speculative_outer_type,
-                                         x.speculative_offset,
-                                         x.speculative_maybe_derived_type,
-                                         NULL))
+          && (strict_speculation
+              || x.speculation_consistent_p (x.speculative_outer_type,
+                                             x.speculative_offset,
+                                             x.speculative_maybe_derived_type,
+                                             NULL)))
     return false;
 
   return true;
-- 
2.51.1

Reply via email to