This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/43411] New: Missed inline optimization opportunity with indirect calls
- From: "jonty_lawson at yahoo dot co dot uk" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 17 Mar 2010 21:54:51 -0000
- Subject: [Bug tree-optimization/43411] New: Missed inline optimization opportunity with indirect calls
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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