https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63671
--- Comment #5 from Jan Hubicka <hubicka at gcc dot gnu.org> --- There is also code size differnce. I tried to track it down and with -fno-devirtualize I need to disable all places devirtualization happens: Index: gimple-fold.c =================================================================== --- gimple-fold.c (revision 217304) +++ gimple-fold.c (working copy) @@ -331,7 +331,7 @@ fold_gimple_assign (gimple_stmt_iterator tree val = OBJ_TYPE_REF_EXPR (rhs); if (is_gimple_min_invariant (val)) return val; - else if (flag_devirtualize && virtual_method_call_p (rhs)) + else if (flag_devirtualize && virtual_method_call_p (rhs) && 0) { bool final; vec <cgraph_node *>targets @@ -2633,7 +2633,7 @@ gimple_fold_call (gimple_stmt_iterator * gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee)); changed = true; } - else if (flag_devirtualize && !inplace && virtual_method_call_p (callee)) + else if (flag_devirtualize && !inplace && virtual_method_call_p (callee) && 0) { bool final; vec <cgraph_node *>targets Index: ipa.c =================================================================== --- ipa.c (revision 217304) +++ ipa.c (working copy) @@ -198,7 +198,7 @@ walk_polymorphic_call_targets (hash_set< final or anonymous (so we know all its derivation) and there is only one possible virtual call target, make the edge direct. */ - if (final) + if (final && 0) { if (targets.length () <= 1 && dbg_cnt (devirt)) { Index: tree-ssa-pre.c =================================================================== --- tree-ssa-pre.c (revision 217304) +++ tree-ssa-pre.c (working copy) @@ -4320,7 +4320,7 @@ eliminate_dom_walker::before_dom_childre { tree fn = gimple_call_fn (stmt); if (fn - && flag_devirtualize + && flag_devirtualize && 0 && virtual_method_call_p (fn)) { tree otr_type = obj_type_ref_class (fn); So apparently it is not the unit growth nor reachability code. It is simply presence of direct calls instead of polymorphic calls that seems to make inliner to do bad decisions...