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
