mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-21 19:35:28 -05:00
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 <mjambor@suse.cz> 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 <mjambor@suse.cz> PR ipa/122856 * g++.dg/ipa/pr122856.C: New test.
This commit is contained in:
committed by
Martin Jambor
parent
8d8725bedd
commit
e47f44074a
@@ -5259,9 +5259,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)
|
||||
@@ -5270,6 +5270,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
|
||||
@@ -5361,6 +5380,8 @@ find_scalar_values_for_callers_subset (vec<tree> &known_csts,
|
||||
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);
|
||||
@@ -5515,7 +5536,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);
|
||||
|
||||
26
gcc/testsuite/g++.dg/ipa/pr122856.C
Normal file
26
gcc/testsuite/g++.dg/ipa/pr122856.C
Normal file
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user