force inline function in other translation unit - c

This part of the gcc manual is pretty obscure and i can't understand the usage of the forceinline attribute after repeated attempts.
I'm defining an object and certain functions to manipulate that object. Few of those functions can use atomic instructions and i want the compiler to inline those functions. However i do not want to write those functions in the header file and declare them with "static inline" like in the linux kernel.
Is there a way to force gcc to inline functions from another translation unit ?

you can use the always_inline attribute, for example:
void foo () __attribute__((always_inline));
From the docs
always_inline
Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the
function even if no optimization level was specified.
Note1: There's no need to use inline if you use the always_inline attribute
Note2: If the function could not be inlined you will get a warning, if for example the definition is not available when compiling, however, at a higher optimization gcc can still inline it into the caller, there's a specific switch for that too:
-funit-at-a-time
From the docs:
Optimization levels -O2 and above, in particular, enable
unit-at-a-time mode, which allows the compiler to consider information
gained from later functions in the file when compiling a function.
Compiling multiple files at once to a single output file in
unit-at-a-time mode allows the compiler to use information gained from
all of the files when compiling each of them.
Note3:
It is not necessary to have an explicit prototype so you can use the attribute on the function defintion:
__attribute__((always_inline)) void foo() {
//some code
}
Also see this discussion, it answers some of your questions.

Related

Does it provide any benefits to simultaneously use __attribute__ ((pure)) and static inline?

I am optimizing a c program and I would like to know if it does make any sense to use __attribute__ ((pure)) and static inline both in the same function declaration?
All three attributes are orthogonal to each other:
static says that function is not used outside of compilation unit so it won't be exported and won't pollute external namespace
inline increases the chance that function is inlined
pure tells compiler that function does not have side effects so if inlining fails compiler will still be able to optimize code around function call more aggressively
So none of them is a substitute to another and they should be used simultaneously.

How to change optimization of all caller function when an inline function is called?

I have a Makefile project to compile bunch of C files. All the files in the project are compiled with optimization level zero but certain functions require optimization level 2 (O2). All those functions which require optimization level 2 are always using a static inline function from a header file.
My requirement is whenever a function uses this inline function from header file, should change its optimization level from O0 to O2 automatically. Is there any provision in GCC which accomplish this requirement?
I have tried changing optimization level of each function which uses the inline function by adding GCC attribute, __attribute__((optimize("O2"))) and it works well. But this inline function is used in more than 200 locations in my project and I have to change the optimization of the function using above strategy in more than 200 locations which is not looking good solution for me
include "foo.h"
void abc ()
{
....
}
void __attribute__((optimize("O2"))) foo()
{
...
"uses inline function from foo.h"
}
abc compiles with optimization 0 from GCC command line.
Need foo() to compile with optimization O2 without GCC attribute option.
I also tried adding GCC attribute to the actual inline function but it does not affect foo's optimization.

"inline" directive doesn't work (Pure C) [duplicate]

I defined my function in .c (without header declaration) as here:
inline int func(int i) {
return i+1;
}
Then in the same file below I use it:
...
i = func(i);
And during the linking I got "undefined reference to 'func'". Why?
The inline model in C99 is a bit different than most people think, and in particular different from the one used by C++
inline is only a hint such that the compiler doesn't complain about doubly defined symbols. It doesn't guarantee that a function is inlined, nor actually that a symbol is generated, if it is needed. To force the generation of a symbol you'd have to add a sort of instantiation after the inline definition:
int func(int i);
Usually you'd have the inline definition in a header file, that is then included in several .c files (compilation units). And you'd only have the above line in exactly one of the compilation units. You probably only see the problem that you have because you are not using optimization for your compiler run.
So, your use case of having the inline in the .c file doesn't make much sense, better just use static for that, even an additional inline doesn't buy you much.
C99 inline semantics are often misunderstood. The inline specifier serves two purposes:
First, as a compiler hint in case of static inline and extern inline declarations. Semantics remain unchanged if you remove the specifier.
Second, in case of raw inline (ie without static or extern) to provide an inline definition as an alternative to an external one, which has to be present in a different translation unit. Not providing the external one is undefined behaviour, which will normally manifest as linking failure.
This is particularly useful if you want to put a function into a shared library, but also make the function body available for optimization (eg inlining or specialization). Assuming a sufficiently smart compiler, this allows you to recover many of the benefits of C++ templates without having to jump through preprocessor hoops.
Note that it's a bit more messy than I described here as having another file scope non-inline external declaration will trigger the first case as described in Jens' answer, even if the definition itself is inline instead of extern inline. This is by design so you can have have a single inline definition in a header file, which you can include into the source file that provides the external one by adding a single line for the external declaration.
This is because of the way GCC handle inline function. GCC performs inline substitution as the part of optimization.
To remove this error use static before inline. Using static keyword force the compiler to inline this function, which makes the program compile successfully.
static inline int func(int i) {
return i+1;
}
...
i = func(i);

Should an inline function be defined before it is called?

The C language allows source files to be read in a single pass without looking ahead; at any point the compiler only has to consider declarations, prototypes, macro definitions etc. that have appeared before its current position in the file.
Does this mean that for a function call to be inlined, a compiler might require the function to be defined before the call? For example:
int foo(void);
int bar(void) { return foo(); }
inline int foo(void) { return 42; }
Is the call to foo more likely to be inlined if the inline definition is moved in front of the definition of bar?
Should I arrange inline definitions in my code so that they appear before the calls that should best be inlined? Or can I just assume that any optimizing compiler that is advanced enough to do inlining at all will be able to find the definition even if it appears after the call (which seems to be the case with gcc)?
EDIT: I noticed that in the Pelles C with the /Ob1 option indeed requires the definition to visible before a call can be inlined. The Compiler also offers an /Ob2 option which removes this limitation (and also allows the compiler to inline functions without an inline specifier, similar to what gcc does), but the documentation states that using this second option may require much more memory.
It shouldn't make any difference in practice. Because, its compiler's choice to inline a function or not even if it's explicitly told to inline. Compiler may also inline a function even if it's defined using inline keyword.
First, I ran your code with with gcc 4.6.3 without any optimizations:
$ gcc -fdump-ipa-inline test.c
From the generated assembly both foo and bar are not inlined even though foo is inlined.
When I changed put the definition of inline foo at the top, the compiler still didn't inline both.
Next I did the same with -O3:
$ gcc -fdump-ipa-inline -O3 test.c
Now both the functions are inlined. Even though only one has the inline declaration.
Basically the compiler can inline a function as it sees fit.

C inline functions and "undefined external" error

I'm trying to replace some macro subroutines with inline functions, so the compiler can optimize them, so the debugger can step into them, etc. If I define them as normal functions it works:
void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
but if I define them as inline:
inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
it says "Error: Undefined external". What does that mean? Taking a stab in the dark, I tried
static inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
and no more errors. The function definition and call to the function are in the same .c file.
Can someone explain why one works and the other doesn't?
(Second related question: Where do I put inline functions if I want to use them in more than one .c file?)
First, the compiler does not always inline functions marked as inline; eg if you turn all optimizations off it will probably not inline them.
When you define an inline function
inline void do_something(void)
{
blah
}
and use that function, even in the same file, the call to that function is resolved by the linker not the compiler, because it is implicitely "extern". But this definition alone does not provide an external definition of the function.
If you include a declaration without inline
void do_something(void);
in a C file which can see the inline definition, the compiler will provide an external definition of the function, and the error should go away.
The reason static inline works is that it makes the function visible only within that compilatioin unit, and so allows the compiler to resolve the call to the function (and optimize it) and emit the code for the function within that compilation unit. The linker then doesn't have to resolve it, so there is no need for an external definition.
The best place to put inline function is in a header file, and declare them static inline. This removes any need for an external definition, so it resolves the linker problem. However, this causes the compiler to emit the code for the function in every compilation unit that uses it, so could result in code bloat. But since the function is inline, it is probably small anyway, so this usually isn't a problem.
The other option is to define it as extern inline in the header, and in one C file provide and extern declaration without the inline modifier.
The gcc manual explains it thus:
By declaring a function inline, you can direct GCC to make calls to
that function faster. One way GCC can achieve this is to integrate
that function's code into the code for its callers. This makes
execution faster by eliminating the function-call overhead; in
addition, if any of the actual argument values are constant, their
known values may permit simplifications at compile time so that not
all of the inline function's code needs to be included. The effect on
code size is less predictable; object code may be larger or smaller
with function inlining, depending on the particular case. You can
also direct GCC to try to integrate all "simple enough" functions into
their callers with the option -finline-functions.
GCC implements three different semantics of declaring a function
inline. One is available with -std=gnu89 or -fgnu89-inline or
when gnu_inline attribute is present on all inline declarations,
another when -std=c99, -std=c1x, -std=gnu99 or -std=gnu1x
(without -fgnu89-inline), and the third is used when compiling C++.
To declare a function inline, use the inline keyword in its
declaration, like this:
static inline int
inc (int *a)
{
return (*a)++;
}
If you are writing a header file to be included in ISO C90 programs,
write __inline__ instead of inline.
The three types of inlining behave similarly in two important cases:
when the inline keyword is used on a static function, like the
example above, and when a function is first declared without using the
inline keyword and then is defined with inline, like this:
extern int inc (int *a);
inline int
inc (int *a)
{
return (*a)++;
}
In both of these common cases, the program behaves the same as if you
had not used the inline keyword, except for its speed.
When a function is both inline and static, if all calls to the
function are integrated into the caller, and the function's address is
never used, then the function's own assembler code is never
referenced. In this case, GCC does not actually output assembler code
for the function, unless you specify the option
-fkeep-inline-functions. Some calls cannot be integrated for various
reasons (in particular, calls that precede the function's definition
cannot be integrated, and neither can recursive calls within the
definition). If there is a nonintegrated call, then the function is
compiled to assembler code as usual. The function must also be
compiled as usual if the program refers to its address, because that
can't be inlined.
Note that certain usages in a function definition can make it
unsuitable for inline substitution. Among these usages are: use of
varargs, use of alloca, use of variable sized data types , use of computed goto,
use of nonlocal goto, and nested functions.
Using -Winline will warn when a function marked inline could not
be substituted, and will give the reason for the failure.
As required by ISO C++, GCC considers member functions defined within
the body of a class to be marked inline even if they are not
explicitly declared with the inline keyword. You can override this
with -fno-default-inline.
GCC does not inline any functions when not optimizing unless you
specify the always_inline attribute for the function, like this:
/* Prototype. */
inline void foo (const char) __attribute__((always_inline));
The remainder of this section is specific to GNU C90 inlining.
When an inline function is not static, then the compiler must
assume that there may be calls from other source files; since a global
symbol can be defined only once in any program, the function must not
be defined in the other source files, so the calls therein cannot be
integrated. Therefore, a non-static inline function is always
compiled on its own in the usual fashion.
If you specify both inline and extern in the function definition,
then the definition is used only for inlining. In no case is the
function compiled on its own, not even if you refer to its address
explicitly. Such an address becomes an external reference, as if you
had only declared the function, and had not defined it.
This combination of inline and extern has almost the effect of a
macro. The way to use it is to put a function definition in a header
file with these keywords, and put another copy of the definition
(lacking inline and extern) in a library file. The definition in
the header file will cause most calls to the function to be inlined.
If any uses of the function remain, they will refer to the single copy
in the library.
For inline functions to work with C99 (they only came there into the language) you'd have to give the definition in a header file
inline void do_something(void)
{
blah
}
and in one compilation unit (aka .c) you place some sort of "instantiation"
void do_something(void);
without the inline.
You have to put them in a header file if you want to use them from multiple files.
And for the linker error: the default declaration of a function implies that it's "extern", but since it's inlined, the linker can find the compiler-generated symbol stub, hence the error.

Resources