http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59831
--- Comment #4 from Jan Hubicka <hubicka at gcc dot gnu.org> --- Created attachment 31996 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=31996&action=edit Proposed fix OK, here we have A& C::operator[](int) (struct C * const this, int p1) { int (*__vtbl_ptr_type) () * _3; int (*__vtbl_ptr_type) () _4; struct A & _8; <bb 2>: _3 = this_2(D)->_vptr.C; _4 = *_3; OBJ_TYPE_REF(_4;(struct C)this_2(D)->0) (this_2(D)); _8 = B::operator[] (this_2(D), p1_6(D)); return _8; } that is devirtualizable in the context of: void sort(C&, C&) (struct C & p1, struct C & p2) { <bb 2>: <bb 3>: C::operator[] (p2_3(D), 0); C::operator[] (p1_5(D), 0); C::operator[] (p2_3(D), 0); <bb 4>: goto <bb 3>; } used exclusively from: void sort(C&, C&) (struct C & p1, struct C & p2) { <bb 2>: <bb 3>: C::operator[] (p2_3(D), 0); C::operator[] (p1_5(D), 0); C::operator[] (p2_3(D), 0); <bb 4>: goto <bb 3>; } ipa-cp does: Evaluating opportunities for void sort(C&, C&)/10. - Creating a specialized node of void sort(C&, C&)/10 for all known contexts. replacing param #1 p2 with const &b Accounting size:2.00, time:0.00 on new predicate:(not inlined) the new node is void sort.constprop(C&)/30. Aggregate replacements: 0[0]=&MEM[(void *)&_ZTV1C + 16B] Evaluating opportunities for void sort(C&, C&)/10. Marking node as dead: void sort(C&, C&)/10. Evaluating opportunities for A& C::operator[](int)/1. - considering value &b for param #0 this (caller_count: 3) good_cloning_opportunity_p (time: 1, size: 17, freq_sum: 201000) -> evaluation: 11823, threshold: 500 Creating a specialized node of A& C::operator[](int)/1. adding an extra known scalar value 0 for param #1 p1 replacing param #0 this with const &b replacing param #1 p1 with const 0 Accounting size:1.00, time:1.00 on predicate:(true) Accounting size:3.00, time:2.00 on new predicate:(not inlined) Accounting size:0.50, time:0.50 on new predicate:(op0[ref offset: 0] changed) && (not inlined) Accounting size:0.50, time:0.50 on new predicate:(op0[ref offset: 0] changed) the new node is A& C::operator[].constprop()/31. Evaluating opportunities for A& C::operator[](int)/1. Evaluating opportunities for virtual int C::m_fn1()/0. - considering value &b for param #0 this (caller_count: 1) good_cloning_opportunity_p (time: 2, size: 3, freq_sum: 800) -> evaluation: 533, threshold: 500 Creating a specialized node of virtual int C::m_fn1()/0. replacing param #0 this with const &b Accounting size:3.00, time:2.00 on new predicate:(not inlined) the new node is int C::m_fn1.constprop()/32. Evaluating opportunities for virtual int C::m_fn1()/0. For some reason it gets right the aggregate value, but misses the devirtualization. devirtualization_time_bonus properly anticipates the devirtualization to happen. The problem is that later we replace BINFO by a constant. This is going throug gimple_extract_binfo_from_cst that is known to be buggy. This patch removes it and uses equivalent functionality of ipa-devirt.