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

Reply via email to