http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47316
--- Comment #5 from Jan Hubicka <hubicka at gcc dot gnu.org> --- The testcase provided now generates: void foo(A*) (struct A * a) { int (*__vtbl_ptr_type) () * _3; int (*__vtbl_ptr_type) () _4; int i.0_6; int i.1_7; void * PROF_9; int i.2_11; int i.3_12; <bb 2>: _3 = a_2(D)->_vptr.A; _4 = *_3; PROF_9 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct A)a_2(D)->0); if (PROF_9 == f) goto <bb 3>; else goto <bb 4>; <bb 3>: i.2_11 ={v} i; i.3_12 = i.2_11 + -1; i ={v} i.3_12; goto <bb 5>; <bb 4>: OBJ_TYPE_REF(_4;(struct A)a_2(D)->0) (a_2(D)); <bb 5>: i.0_6 ={v} i; i.1_7 = i.0_6 + -1; i ={v} i.1_7; return; } where PROF_9 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct A)a_2(D)->0); if (PROF_9 == f) goto <bb 3>; else goto <bb 4>; looking at it, I am not sure if we want to keep OBJ_TYPE_REF here. It is generally ignored except for the call statements themselves. So either we want to drop it or extend type devirtualization in the folding machinery to work for non-calls, too.