C++ inlining of virtual calls does not occur in many instances when it should be easy to determine that it is safe.
The problem occurs when there is an object that is referred to via a pointer or reference. Normally a virtual call through a pointer cannot be inlined because it is not known what its actual type is at compile time. However, sometimes the pointer is assigned to an object of known type, and in this case the compiler could determine the correct version of the method to call, and so inline it. This is a somewhat unlikely state of affairs in normal code, but it becomes important when some inlining has already taken place. Often the inlined method will refer to a parameter via a reference, but this may refer to a type known precisely at the call site. After inlining this information could be profitably used to allow further inlining. Small getter/setter methods would benefit enormously from this. As far as I can make out, the microsoft C++ compiler seems to do this optimization. For example, consider the complete source file: class P { public: virtual int val() { return 123; } }; class Psub : public P { }; extern int sink1, sink2; void test() { Psub p; P &pRef = p; sink1 = p.val(); sink2 = pRef.val(); } inline int v(P &p) { return p.val(); } void testInlineP() { P p; sink1 = v(p); } void testInlinePsub() { Psub p; sink1 = v(p); } With -O3 specified this generates the following code (with a very little cleanup for clarity): __Z4testv: pushl %ebp movl $123, %edx movl %esp, %ebp leal -24(%ebp), %eax subl $40, %esp movl %eax, (%esp) movl $__ZTV4Psub+8, -24(%ebp) movl %edx, _sink1 call *__ZTV4Psub+8 movl %eax, _sink2 leave ret __Z11testInlinePv: pushl %ebp movl %esp, %ebp leal -24(%ebp), %eax subl $40, %esp movl %eax, (%esp) movl $__ZTV1P+8, -24(%ebp) call *__ZTV1P+8 movl %eax, _sink1 leave ret __Z14testInlinePsubv: pushl %ebp movl %esp, %ebp leal -24(%ebp), %eax subl $40, %esp movl %eax, (%esp) movl $__ZTV4Psub+8, -24(%ebp) call *__ZTV4Psub+8 movl %eax, _sink1 leave ret Only the line "sink1 = p.val();" in test has been inlined to "movl $123, %edx / movl %edx, _sink1". The other calls have not been inlined, even though they can safely be replaced by the same instruction pair. The above code was generated with version 3.4.5 mingw, but I have checked that the same thing happens with version 4.3.3 under Ubuntu. I haven't checked that it happens with targets other than i386, but it seems likely that it would. This bug report seems likely to be a more general case of bug report 41012 and probably replaces it. -- Summary: Missed inline optimization opportunity with indirect calls Product: gcc Version: 4.3.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jonty_lawson at yahoo dot co dot uk http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43411