https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64812
Jan Hubicka <hubicka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rguenther at suse dot de --- Comment #12 from Jan Hubicka <hubicka at gcc dot gnu.org> --- Markus, the devirtualization seems valid to me. You are supposed to link with the implementaiton of the class. It is possible to overwrite this by manually setting the visibility. We however end up with funny code in optimized dump: <bb 2>: _3 = this_2(D)->D.2399.D.2325._vptr.B; _4 = *_3; PROF_6 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_6 == acquire) goto <bb 3>; else goto <bb 18>; <bb 3>: PROF_10 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_10 == acquire) goto <bb 4>; else goto <bb 17>; <bb 4>: PROF_14 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_14 == acquire) goto <bb 5>; else goto <bb 16>; <bb 5>: PROF_18 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_18 == acquire) goto <bb 6>; else goto <bb 15>; <bb 6>: PROF_22 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_22 == acquire) goto <bb 7>; else goto <bb 14>; <bb 7>: PROF_26 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_26 == acquire) goto <bb 8>; else goto <bb 13>; <bb 8>: PROF_30 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_30 == acquire) goto <bb 9>; else goto <bb 12>; <bb 9>: PROF_34 = [obj_type_ref] OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0); if (PROF_34 == acquire) goto <bb 10>; else goto <bb 11>; <bb 10>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 11>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 12>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 13>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 14>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 15>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 16>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 17>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] goto <bb 19>; <bb 18>: OBJ_TYPE_REF(_4;(struct WindowListenerMultiplexer)this_2(D)->0) (this_2(D)); [tail call] <bb 19>: return; } this is result of recursive inlining over the devirtualized call that sort of seem legit even though it is bit of overkill. RTL optimizers simplify this to: _ZN25WindowListenerMultiplexer7acquireEv: .LFB1: .cfi_startproc movq (%rdi), %rax jmp *(%rax) .cfi_endproc .LFE1: RIchi, I think PRE is supposed to optimize this?