Hi, as discused in the PR log there seems to be ordering issue in update_indirect_edges_after_inlining that first updates info in call edge to correspond the situation after inlining and then it tries to devirtualize that is trying to look up the info prior inlining.
Bootstrapped/regtested x86_64-linux Martin, does it look sane? Can you also, please, look into why ipa-cp is not handling both calls? Honza PR tree-optimization/55823 * g++.dg/ipa/devirt-10.C: New testcase. * ipa-prop.c (update_indirect_edges_after_inlining): Fix ordering issue. Index: testsuite/g++.dg/ipa/devirt-10.C =================================================================== *** testsuite/g++.dg/ipa/devirt-10.C (revision 0) --- testsuite/g++.dg/ipa/devirt-10.C (revision 0) *************** *** 0 **** --- 1,34 ---- + /* { dg-do compile } */ + /* { dg-options "-O3 -fdump-ipa-inline -fdump-ipa-cp" } */ + class wxPaintEvent { }; + struct wxDCBase + { + wxDCBase (); + virtual int GetLayoutDirection() const{} + virtual void SetLayoutDirection(int){} + }; + struct wxWindowDC : public wxDCBase {}; + struct wxBufferedDC : public wxDCBase + { + void Init(wxDCBase*dc) { + InitCommon(dc); + } + void InitCommon(wxDCBase*dc) { + if (dc) + SetLayoutDirection(dc->GetLayoutDirection()); + } + }; + struct wxBufferedPaintDC : public wxBufferedDC { + wxBufferedPaintDC() { + Init(&m_paintdc); + } + wxWindowDC m_paintdc; + }; + void OnPaint(wxPaintEvent & event) { + wxBufferedPaintDC dc; + } + /* IPA-CP should really discover both cases, but for time being the second is handled by inliner. */ + /* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "inline" } } */ + /* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "cp" } } */ + /* { dg-final { cleanup-ipa-dump "inline" } } */ + /* { dg-final { cleanup-ipa-dump "cp" } } */ Index: ipa-prop.c =================================================================== *** ipa-prop.c (revision 194918) --- ipa-prop.c (working copy) *************** update_indirect_edges_after_inlining (st *** 2264,2303 **** param_index = ici->param_index; jfunc = ipa_get_ith_jump_func (top, param_index); - if (jfunc->type == IPA_JF_PASS_THROUGH - && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) - { - if (ici->agg_contents - && !ipa_get_jf_pass_through_agg_preserved (jfunc)) - ici->param_index = -1; - else - ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc); - } - else if (jfunc->type == IPA_JF_ANCESTOR) - { - if (ici->agg_contents - && !ipa_get_jf_ancestor_agg_preserved (jfunc)) - ici->param_index = -1; - else - { - ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc); - ici->offset += ipa_get_jf_ancestor_offset (jfunc); - } - } - else - /* Either we can find a destination for this edge now or never. */ - ici->param_index = -1; if (!flag_indirect_inlining) ! continue; ! ! if (ici->polymorphic) new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc, new_root_info); else new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc, new_root_info); - if (new_direct_edge) { new_direct_edge->indirect_inlining_edge = 1; --- 2264,2278 ---- param_index = ici->param_index; jfunc = ipa_get_ith_jump_func (top, param_index); if (!flag_indirect_inlining) ! new_direct_edge = NULL; ! else if (ici->polymorphic) new_direct_edge = try_make_edge_direct_virtual_call (ie, jfunc, new_root_info); else new_direct_edge = try_make_edge_direct_simple_call (ie, jfunc, new_root_info); if (new_direct_edge) { new_direct_edge->indirect_inlining_edge = 1; *************** update_indirect_edges_after_inlining (st *** 2312,2317 **** --- 2287,2315 ---- res = true; } } + else if (jfunc->type == IPA_JF_PASS_THROUGH + && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) + { + if (ici->agg_contents + && !ipa_get_jf_pass_through_agg_preserved (jfunc)) + ici->param_index = -1; + else + ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc); + } + else if (jfunc->type == IPA_JF_ANCESTOR) + { + if (ici->agg_contents + && !ipa_get_jf_ancestor_agg_preserved (jfunc)) + ici->param_index = -1; + else + { + ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc); + ici->offset += ipa_get_jf_ancestor_offset (jfunc); + } + } + else + /* Either we can find a destination for this edge now or never. */ + ici->param_index = -1; } return res;