https://gcc.gnu.org/g:ddccaad7202fdacc6c82b31d2cde889f0ce17e09

commit r15-10879-gddccaad7202fdacc6c82b31d2cde889f0ce17e09
Author: Martin Jambor <[email protected]>
Date:   Fri Feb 20 14:34:27 2026 +0100

    ipa-cp: Also look at self-recursive ancestor jump functions (PR122856)
    
    PR 122856 shows that when looking at self recursive calls with
    self-feeding jump functions, we did consider pass-through functions
    but not ancestor functions with zero offsets.  This then leads to the
    fact that constants which were collected from IPA-CP lattices were not
    among those collected from available edges, triggering a verification
    assert.
    
    This patch fixes that by also detecting self-feeding ancestor jump
    functions.
    
    gcc/ChangeLog:
    
    2026-02-06  Martin Jambor  <[email protected]>
    
            PR ipa/122856
            * ipa-cp.cc (self_recursive_pass_through_p): Test jump function 
type first.
            (self_recursive_ancestor_p): New function.
            (find_scalar_values_for_callers_subset): Test also for 
self-recursive
            ancestor jump functions.
            (push_agg_values_for_index_from_edge): Likewise.
    
    gcc/testsuite/ChangeLog:
    
    2026-02-06  Martin Jambor  <[email protected]>
    
            PR ipa/122856
            * g++.dg/ipa/pr122856.C: New test.
    
    (cherry picked from commit e47f44074a5fe9b51cbe75269363a42e90d6a580)

Diff:
---
 gcc/ipa-cp.cc                       | 28 +++++++++++++++++++++++++---
 gcc/testsuite/g++.dg/ipa/pr122856.C | 26 ++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 782a39791840..7702b5860b98 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -5318,9 +5318,9 @@ self_recursive_pass_through_p (cgraph_edge *cs, 
ipa_jump_func *jfunc, int i,
                               bool simple = true)
 {
   enum availability availability;
-  if (cs->caller == cs->callee->function_symbol (&availability)
+  if (jfunc->type == IPA_JF_PASS_THROUGH
+      && cs->caller == cs->callee->function_symbol (&availability)
       && 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_node_params_sum->get (cs->caller)
@@ -5329,6 +5329,25 @@ self_recursive_pass_through_p (cgraph_edge *cs, 
ipa_jump_func *jfunc, int i,
   return false;
 }
 
+/* Return true if JFUNC, which describes the i-th parameter of call CS, is an
+   ancestor function with zero offset to itself when the cgraph_node involved
+   is not an IPA-CP clone.  */
+
+static bool
+self_recursive_ancestor_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i)
+{
+  enum availability availability;
+  if (jfunc->type == IPA_JF_ANCESTOR
+      && cs->caller == cs->callee->function_symbol (&availability)
+      && availability > AVAIL_INTERPOSABLE
+      && ipa_get_jf_ancestor_offset (jfunc) == 0
+      && ipa_get_jf_ancestor_formal_id (jfunc) == i
+      && ipa_node_params_sum->get (cs->caller)
+      && !ipa_node_params_sum->get (cs->caller)->ipcp_orig_node)
+    return true;
+  return false;
+}
+
 /* Return true if JFUNC, which describes a part of an aggregate represented or
    pointed to by the i-th parameter of call CS, is a pass-through function to
    itself when the cgraph_node involved is not an IPA-CP clone..  When
@@ -5415,6 +5434,8 @@ find_more_scalar_values_for_callers_subset (struct 
cgraph_node *node,
                                op_type);
              t = ipacp_value_safe_for_type (type, t);
            }
+         else if (self_recursive_ancestor_p (cs, jump_func, i))
+           continue;
          else
            t = ipa_value_from_jfunc (ipa_node_params_sum->get (cs->caller),
                                      jump_func, type);
@@ -5580,7 +5601,8 @@ push_agg_values_for_index_from_edge (struct cgraph_edge 
*cs, int index,
              && !src_plats->aggs_bottom
              && (agg_jf_preserved || !src_plats->aggs_by_ref))
            {
-             if (interim && self_recursive_pass_through_p (cs, jfunc, index))
+             if (interim && (self_recursive_pass_through_p (cs, jfunc, index)
+                             || self_recursive_ancestor_p (cs, jfunc, index)))
                {
                  interim->push_adjusted_values (src_idx, index, unit_delta,
                                                 res);
diff --git a/gcc/testsuite/g++.dg/ipa/pr122856.C 
b/gcc/testsuite/g++.dg/ipa/pr122856.C
new file mode 100644
index 000000000000..b634e6280095
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr122856.C
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=gnu++11" } */
+
+template <typename T>
+class Base {
+public:
+    virtual int get();
+    virtual ~Base() = default;
+};
+
+template <typename T>
+class Derived : public Base<T> {
+public:
+    int get() override { return Base<T>::get(); }
+};
+
+template <typename T>
+int Base<T>::get() {
+
+    return static_cast<Derived<int>*>(this)->get();
+}
+
+int main() {
+    Derived<int> d;
+    return d.get();
+}

Reply via email to