On 12/17/13 11:00, Jan Hubicka wrote:
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
s/Add/Handle. Please add the PR marker as well. OK with that trivial nit. jeff