Bug 33358 - Slow calls through simple member function pointers
Summary: Slow calls through simple member function pointers
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.1
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-09-08 20:06 UTC by Dushan Leska
Modified: 2007-09-10 04:06 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dushan Leska 2007-09-08 20:06:40 UTC
Hi,

By simple MFPs I mean those that point to a class with single or no inheritance and the class is fully defined at the time of the call. For example:

class SomeClass {};

typedef void (SomeClass::*MemberFunc)();

void callMemberFunc(SomeClass *object, MemberFunc func)
{
   (object->*func)();
} 

g++ seems to generate the same code whether SomeClass is a complete type or not. In the above example, VS 2005 can significantly optimise the call when SomeClass is defined:

00424D40  mov         ecx,dword ptr [esp+4]
00424D44  jmp         dword ptr [esp+8] 

g++ 4.2.1 generates the following:

	.file	"test.cpp"
	.text
	.align 2
	.p2align 4,,15
.globl __Z12callDelegateRN12fastdelegate12FastDelegateIFvvEEE
	.def	__Z12callDelegateRN12fastdelegate12FastDelegateIFvvEEE;	.scl	2;	.type	32;	.endef
__Z12callDelegateRN12fastdelegate12FastDelegateIFvvEEE:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ebx
	movl	8(%ebp), %eax
	movl	4(%eax), %ecx
	movl	(%eax), %ebx
	movl	8(%eax), %edx
	testb	$1, %cl
	je	L7
	leal	(%ebx,%edx), %edx
	movl	(%edx), %eax
	movl	-1(%eax,%ecx), %ecx
	movl	%edx, 8(%ebp)
	popl	%ebx
	popl	%ebp
	jmp	*%ecx
	.p2align 4,,7
L7:
	leal	(%ebx,%edx), %edx
	movl	%edx, 8(%ebp)
	popl	%ebx
	popl	%ebp
	jmp	*%ecx

I've reproduced this on 4.2.1 and 3.4.2 on x86 (MinGW) and 4.1.1, 4.1.0, 4.0.1 and 3.4.4 on arm/thumb.

Would it be possible for gcc to optimise such calls?
Comment 1 Richard Biener 2007-09-08 20:40:26 UTC
VS seems to dispatch to some other function.  Dependend on whether the method
is virtual or not the code path has to be more complicated.  Of course this is
also dependent on the actual ABI.  That is,

L7:
        leal    (%ebx,%edx), %edx
        movl    %edx, 8(%ebp)
        popl    %ebx
        popl    %ebp
        jmp     *%ecx

is the equivalent to the direct jump, and the rest involves loading the
vtable pointer.

        leal    (%ebx,%edx), %edx
        movl    (%edx), %eax
        movl    -1(%eax,%ecx), %ecx
        movl    %edx, 8(%ebp)
        popl    %ebx
        popl    %ebp
        jmp     *%ecx

and of course the check if this is a virtual method or not.
Comment 2 Dushan Leska 2007-09-09 06:47:40 UTC
(In reply to comment #1)
> VS seems to dispatch to some other function.

Yep - if the function is virtual, VS generates a stub that does the vtable lookup.  However for non virtual function the call is direct - which is much faster than what gcc does.

Note that if I replace the first line of my example with 'class SomeClass;' - gcc and VS generate comparable code. However when the class is defined at the point of the call and does not use multiple/virtual inheritance, VS generates significantly faster calls (at least for non-virtual functions).

Is this optimisation not possible in gcc?
Comment 3 Andrew Pinski 2007-09-09 10:37:12 UTC
Subject: Re:  Slow calls through simple member function pointers

On 9 Sep 2007 06:47:40 -0000, dleska at gmail dot com
<gcc-bugzilla@gcc.gnu.org> wrote:
> Is this optimisation not possible in gcc?

Only because the ABI that GCC follows (the IA64 C++ ABI) says
otherwise so we have to follow that.

If you want this optimization, you will need the whole program as even
if there is no inheritence in the current source, there can be in
other places.

-- Pinski