Hi, in my commit r16-6149-g14ee9a2b41bafa I have added an early exit to update_indirect_edges_after_inlining which was however wrong, as demonstrated by the PR123229 testcase. This patch reverts that change, restoring the previous behavior in this regard.
In the testcase, the edge being inlined is a call to a thunk, which do not have jump functions associated with them. This means that with the early exit we neither reset the parameter index associated with the indirect edge nor update the edges and the usage flags associated with them In the testcase, this meant that the param_used_by_indirect_call flag was not updated, which in turn meant that the inlining edge cost cache did not copy necessary information into the context which led to the fact that two contexts which were not the same were considered the same, and the checking code that evaluations in the cache should match a re-evaluation triggered. But unfortunately this bug can probably have all sorts of weird and unexpected consequences. The testcase also shows that inlined thunks are a barrier to devirtualization which is something I will try to address next stage1. I'm currently bootstrapping&testing and O3-lto-bootstrapping this on x86_64-linux. I plan to commit it if they pass because it is essentially a revert of my own change, even if only of a small bit of the patch. Martin gcc/ChangeLog: 2026-02-27 Martin Jambor <[email protected]> PR ipa/123229 * ipa-prop.cc (update_indirect_edges_after_inlining): Reset parameter index associated with an indirect edge if the inlined edge does not have any jump functions. gcc/testsuite/ChangeLog: 2026-02-27 Martin Jambor <[email protected]> PR ipa/123229 * g++.dg/ipa/pr123229.C: New test. --- gcc/ipa-prop.cc | 5 ++-- gcc/testsuite/g++.dg/ipa/pr123229.C | 36 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/pr123229.C diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 12e936ba29b..385912c3790 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -4539,8 +4539,6 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, ipa_check_create_edge_args (); class ipa_edge_args *top = ipa_edge_args_sum->get (cs); - if (!top) - return res; cgraph_node *new_root = cs->caller->inlined_to ? cs->caller->inlined_to : cs->caller; ipa_node_params *new_root_info = ipa_node_params_sum->get (new_root); @@ -4552,7 +4550,8 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, { next_ie = ie->next_callee; - if (ie->indirect_info->param_index < 0 + if (!top + || ie->indirect_info->param_index < 0 || ie->indirect_info->param_index >= ipa_get_cs_argument_count (top)) { ie->indirect_info->param_index = -1; diff --git a/gcc/testsuite/g++.dg/ipa/pr123229.C b/gcc/testsuite/g++.dg/ipa/pr123229.C new file mode 100644 index 00000000000..7c4931871d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr123229.C @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-exceptions" } */ + +class a { + virtual int c(); +}; +struct e { + virtual e *d(unsigned) const; + void m_fn3() { d(0); } +} *f, *g; +struct h : a, e { + e *d(unsigned) const { return i(); } + virtual h *i() const; +}; +struct j { + virtual void k(e *); +}; +void l(j &m) { + m.k(g); + while (1) { + m.k(f); + f->m_fn3(); + } +} +struct n : j { + void k(e *m) { + if (o) + m->m_fn3(); + } + bool o; +}; +void p() { + n b; + l(b); +} + -- 2.52.0
