Another inline question

A

asterisc

Hi there,

Before getting a binary, there is the following sequence of steps:
- preprocessing
- compilation
- assembly
- linking

Is there any rule at which level should the inline work?
I mean, where should we see the effect of the inline keyword ?

I have the following fairly simple piece of code:

//test.cpp
#include <iostream>

inline void increment( int& i )
{
++i;
}

#define INCREMENT(i) (++i)

int main()
{
int i = 0;
increment( i );
std::cout << i << endl;
INCREMENT(i);
std::cout << i << endl;
}

The #define is replaced in the preprocessing step.

As far as I could check, the effect of the inline is only at the
assembling step, where we won't have a call to the increment()
function. (if we apply an optimization)
The preprocessed source looks exactly the same as the .cpp file, only
the #define was expanded.

Is that the normal behavior?

Another question, how is inline working with a virtual member
function? (if we call that function thru a base pointer which point to
a derived object)

Thanks in advance
 
V

Victor Bazarov

asterisc said:
Hi there,

Before getting a binary, there is the following sequence of steps:
- preprocessing
- compilation
- assembly
- linking

While 'preprocessing' is clearly separated into its own step in the
language Standard, the other ones are not really defined so well.
Especially the assembly portion - nowadays most compilers produce
native code in an object file form. Linking is still a step in
most cases.
Is there any rule at which level should the inline work?

No rule.
I mean, where should we see the effect of the inline keyword ?

During compilation 'inline' acts as a suggestion for the compiler
to substitute the call with the body. During linking 'inline' gives
an instruction to only consider a single definition of the function.
IOW, different meanings at different stages.
I have the following fairly simple piece of code:

//test.cpp
#include <iostream>

inline void increment( int& i )
{
++i;
}

#define INCREMENT(i) (++i)

int main()
{
int i = 0;
increment( i );
std::cout << i << endl;
INCREMENT(i);
std::cout << i << endl;
}

The #define is replaced in the preprocessing step.
Right.

As far as I could check, the effect of the inline is only at the
assembling step, where we won't have a call to the increment()
function. (if we apply an optimization)
The preprocessed source looks exactly the same as the .cpp file, only
the #define was expanded.

Is that the normal behavior?

Probably. I've not seen separate assembling step for quite a while,
so I'll just take your word for it.
Another question, how is inline working with a virtual member
function? (if we call that function thru a base pointer which point to
a derived object)

It doesn't. If the function is not known until run-time, like in
the case with a virtual function, it cannot be inlined, can it?

V
 
A

asterisc

While 'preprocessing' is clearly separated into its own step in the
language Standard, the other ones are not really defined so well.
Especially the assembly portion - nowadays most compilers produce
native code in an object file form. Linking is still a step in
most cases.


No rule.


During compilation 'inline' acts as a suggestion for the compiler
to substitute the call with the body. During linking 'inline' gives
an instruction to only consider a single definition of the function.
IOW, different meanings at different stages.










Probably. I've not seen separate assembling step for quite a while,
so I'll just take your word for it.


It doesn't. If the function is not known until run-time, like in
the case with a virtual function, it cannot be inlined, can it?

V

That was my thoughts as well about mixing inline with virtual.

At the assembly step (in gcc, the output with -S option), for the -O0
(no optimization) I have the "extra" call for the inline function.
With -O2 option, that's replace with the body of the function, but
only in the assembling step. After preprocessing (-E option), the
sources looks the same for both -O0 and -O2, and the same with the
original .cpp file.

Thank you for your answer!
 
P

Paavo Helde

If the compiler can determine the actual run-time type of the object it can
replace a virtual call by a non-virtual and then inline it as well. In
practice this probably can happen only if the member function is called
directly on an object and not on a pointer or reference, so it would be an
untypical usage for a polymorphic class. In principle this kind of
optimizations could be done also by a full-program optimization, but
because of existence of dynamic load libraries this is next of impossible
on mainstream platforms.

Paavo
 
J

Juha Nieminen

asterisc said:
Is there any rule at which level should the inline work?
I mean, where should we see the effect of the inline keyword ?

Actually, rather ironically, in most modern compilers the keyword
'inline' has practically nothing to do with function inlining. This is
because if the implementation of a function is available at the place
where the function is called, most optimizing compilers will inline it
anyways (if they calculate that there would be a benefit in doing so),
completely regardless of whether it has the keyword 'inline' or not.
(And also the other way around: Even if the function has the keyword
'inline', that does in no way guarantee that it will actually be inlined.)

However, 'inline' is not a no-op keyword (like for example 'register'
is). It has a role, but this role has nothing to do with inlining. This
role has to do with linking.

When a function has been declared to be 'inline', and the function
actually doesn't get inlined, the compiler will instruct the linker to
merge all the instances of that function in all the compilation units it
appears in. In other words, even if the implementation of that function
is compiled into several object files, at linking stage all these
instantiations of that function will be merged into one so that in the
final executable there will be only one instance of that function.

Without the keyword 'inline' what you get in this case is a linker
error. (The linker finds more than one implementation of the same
function, they have not been marked by the compiler to actually be the
same function, and thus the compiler will issue an error because it
can't know which one of those implementations it should use.)
 
J

James Kanze

asterisc wrote:

[...]
It doesn't. If the function is not known until run-time, like
in the case with a virtual function, it cannot be inlined, can
it?

Declaring a function inline has no effect on its semantics. I
often use inline virtual functions, and the compiler inlines
them. (The most obvious example is the virtual destructor of an
abstract base class. Which, of course, will never be called
other than from the destructor of the derived class, where it
will be inlined.)

I have also heard of one compiler which will inline depending on
profiler output. If the profiler reveals that 99% of the calls
are in fact to the same function, and the calls are critical to
the total run-time of the program, it will generate the
equivalent on an if of the type, and inline the frequent case.
(This can be very effective if the if can be hoisted out of a
loop, and the inlining reveals additional optimization
possibilities.) Of course, in this case, the compiler will
inline the function whether it was declared inline or not.

(With regards to the part of your posting I cut: note that the
distinction between compilation and linking isn't always that
clear either. Most compilers today have options for profiler
based optimizing, and a lot support intermodule optimizing,
which means that final code generation---including the choice of
whether to inline or not---doesn't occur until after linking.)
 

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

Similar Threads

Inline functions 33
Proposed Standard Change: inline this 8
gcc inline memcpy 7
inline functions 15
First time question 1
how to inline member function is a separate file 6
inline question 25
Cannot find my infinite loop 1

Members online

No members online now.

Forum statistics

Threads
473,772
Messages
2,569,588
Members
45,100
Latest member
MelodeeFaj
Top