Function Pointers and Inlining

M

Mat Booth

If I call an inline member function through a member function pointer,
will that function be inlined?

I imagine it wouldn't because the function that's pointed to isn't known
until run-time, is that correct?

Cheers.
 
D

David White

Mat Booth said:
If I call an inline member function through a member function pointer,
will that function be inlined?

I imagine it wouldn't because the function that's pointed to isn't known
until run-time, is that correct?

It might be that in some cases the compiler is smart enough to know the
identity of the function whose address must be in the pointer, or that it
can do away with the pointer altogether and just inline the function. In
other cases it couldn't possibly know what the pointer contains and would
have to indirectly call a non-inlined instance of the function.

I tried this on VC++ 6.0, optimized for speed:

int N;

inline void f()
{
++N; // do some work or no code is generated
}

int main()
{
f();
void (*pf)() = &f;
(*pf)();
}

The generated code was:

inc dword ptr [N]
jmp f
f:
inc dword ptr [N]
ret

I don't know why it bothered with the redundant jump, but the compiler
clearly saw that no call was needed. In principle, a pointer to an inlined
class member function is no different, though this compiler wasn't smart
enough to generate such small code when I tried the member-function
equivalent. It ignored the pointer and called the non-inlined function
directly.

DW
 
J

James Aguilar

Mat Booth said:
If I call an inline member function through a member function pointer,
will that function be inlined?

I imagine it wouldn't because the function that's pointed to isn't known
until run-time, is that correct?

Any function which has its address taken during the course of the program
will never be inlined.

- JFA1
 
H

Howard

James Aguilar said:
Any function which has its address taken during the course of the program
will never be inlined.

- JFA1

Never? I don't think that's correct. If I recall, the implementation is
free to inline those calls which it is able to inline. But it must also
provide a non-inline version which can be called normally. It's not an
all-or-nothing thing, but is handled on a case-by-case basis. At least,
that's my understanding.

-Howard
 
J

James Aguilar

Howard said:
Never? I don't think that's correct. If I recall, the implementation is free
to inline those calls which it is able to inline. But it must also provide a
non-inline version which can be called normally. It's not an all-or-nothing
thing, but is handled on a case-by-case basis. At least, that's my
understanding.

I've been wrong before, but I think I read something about how if you take the
address of a particular function, that function won't be inlined elsewhere. A
test shows . . .

--- CODE ---
inline
void inlineTest(int &i) {
i += 5;
}

int main()
{
int i = 2;
void (*testPtr)(int &) = &inlineTest;
testPtr(i);

inlineTest(i);
return 0;
}

--- CODE ---

This compiled with -S and on g++ gives this assembly code:

--- CODE ---
movl $2, -4(%ebp)
movl $__Z10inlineTestRi, -8(%ebp)
leal -4(%ebp), %eax
movl %eax, (%esp)
movl -8(%ebp), %eax
call *%eax
leal -4(%ebp), %eax
movl %eax, (%esp)
call __Z10inlineTestRi ;LINK 1
movl $0, %eax
--- CODE ---

I think that if it worked as you say, LINK 1 would be addl $5, %eax or something
like that. On the other hand, when I get the assembly compiling with -O2, crazy
stuff happens and I can't read it.

- JFA1
 
V

Victor Bazarov

James said:
Never? I don't think that's correct. If I recall, the implementation is free
to inline those calls which it is able to inline. But it must also provide a
non-inline version which can be called normally. It's not an all-or-nothing
thing, but is handled on a case-by-case basis. At least, that's my
understanding.


I've been wrong before, but I think I read something about how if you take the
address of a particular function, that function won't be inlined elsewhere. A
test shows . . .

--- CODE --- [...]
--- CODE ---

I think that if it worked as you say, LINK 1 would be addl $5, %eax or something
like that. On the other hand, when I get the assembly compiling with -O2, crazy
stuff happens and I can't read it.

You're arguing different points here. Howard says what the Standard says.
You are demonstrating what you've observed with the compilers you have.
Both are correct but they don't contradict each other.

The Standard does not mandate either behaviour. It should be reasonably
apparent that if somebody takes the address of a function, the body has to
exist somewhere otherwise what would the address point to? However, the
act of putting a copy of the function body with all necessary adjustments
into the code instead of a call to that function (known as "inlining") is
totally up to the compiler. It doesn't have to do it even if you use the
'inline' keyword.

Between two extremes: inlining all [static] calls to that function and
also providing a body elsewhere if the address is taken *and* not inlining
the function at all, is where the behaviour of a compliant compiler lies.
You should see by now that there is nothing to argue about.

V
 
R

Rolf Magnus

James said:
I've been wrong before, but I think I read something about how if you take
the address of a particular function, that function won't be inlined
elsewhere.

It's rather the other way round. If you take a pointer, a non-inline version
of the function must be created. However, that doesn't mean that the
function cannot be inlined anymore.
A test shows . . .

--- CODE ---
inline
void inlineTest(int &i) {
i += 5;
}

int main()
{
int i = 2;
void (*testPtr)(int &) = &inlineTest;
testPtr(i);

inlineTest(i);
return 0;
}

--- CODE ---

This compiled with -S and on g++ gives this assembly code:

--- CODE ---
movl $2, -4(%ebp)
movl $__Z10inlineTestRi, -8(%ebp)
leal -4(%ebp), %eax
movl %eax, (%esp)
movl -8(%ebp), %eax
call *%eax
leal -4(%ebp), %eax
movl %eax, (%esp)
call __Z10inlineTestRi ;LINK 1
movl $0, %eax
--- CODE ---

I think that if it worked as you say, LINK 1 would be addl $5, %eax or
something like that.

And where's the produced code that proves that the function gets inlined if
you remove the pointer?
On the other hand, when I get the assembly compiling with -O2, crazy stuff
happens and I can't read it.

Yes. One thing it does with -O2 is enable inlining.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top