Hi, PR 35545 has trivial testcase of feedback directed devirtualization: int main() { int i; A* ap = 0;
for (i = 0; i < 10000; i++) { if (i%7==0) ap = new A(); else ap = new B(); ap->foo(); .... Here we should devirtualize since B's foo is dominating target and we correctly do so. We however do more, we trace the code into: for (i = 0; i < 10000; i++) { if (i%7==0) { ap = new A(); ap->foo(); } else { ap = new B(); ap->foo(); } that should allow us to devirtualize completely. Instead of doing that we get stuck on stupid <bb 5>: ap_8 = operator new (16); ap_8->i = 0; ap_8->_vptr.A = &MEM[(void *)&_ZTV1A + 16B]; _19 = foo; PROF_26 = [obj_type_ref] OBJ_TYPE_REF(_19;(struct A)ap_8->0); if (PROF_26 == foo) goto <bb 8>; else goto <bb 7>; <bb 6>: ap_13 = operator new (16); MEM[(struct B *)ap_13].D.2237.i = 0; MEM[(struct B *)ap_13].b = 0; MEM[(struct B *)ap_13].D.2237._vptr.A = &MEM[(void *)&_ZTV1B + 16B]; _1 = foo; PROF_30 = [obj_type_ref] OBJ_TYPE_REF(_1;(struct A)ap_13->0); if (PROF_30 == foo) goto <bb 8>; else goto <bb 7>; There are several reasons for it 1) most of our passes do not expect OBJ_TYPE_REF in arguments and cowardly consider it volatile 2) tracer happens too late and there is no VRP pass to cleanup afterwards 3) folding machinery expect OBJ_TYPE_REF to be only in argument. After some consideration I decided to not update gimple_ic to remove OBJ_TYPE_REF, since this is a perfect example where OBJ_TYPE_REF may be useful after inlining: in a more complex cases a type based devirt may kick in and save a day even late after unrolling/tracing and other code specialization. This is first trivial patch to make VRP behaving correctly. Bootstrapped/regtested x86_64-linux OK? * tree-vrp.c (extract_range_from_unary_expr_1): Add OBJ_TYPE_REF Index: tree-vrp.c =================================================================== --- tree-vrp.c (revision 206040) +++ tree-vrp.c (working copy) @@ -3202,9 +3202,9 @@ extract_range_from_unary_expr_1 (value_r } /* Handle operations that we express in terms of others. */ - if (code == PAREN_EXPR) + if (code == PAREN_EXPR || code == OBJ_TYPE_REF) { - /* PAREN_EXPR is a simple copy. */ + /* PAREN_EXPR and OBJ_TYPE_REF are simple copies. */ copy_value_range (vr, &vr0); return; }