How do I inline a function from another translation unit?
Asked Answered
M

1

6

Consider the two translation units below. My goal is to inline the function add both in file1.c and main.c.

file1.c:

extern inline int add(int x, int y)
{
 return x + y;
}

void g(void)
{
  add(1, 1);     // this will probably be inlined
}

main.c:

extern int add(int, int);

void f(void)
{
  add(2, 4);    // this doesn't appear to be inlined
}

int main(void)
{
  f();
  return 0;
}

The generated assembly indicates that add(2, 4) is not inlined. Why? Or is it the rule that, for a function to be inlined in a translation unit, it must be declared inline in the translation unit and therefore its definition must be seen?

Metabolism answered 9/2, 2020 at 5:44 Comment(3)
You can put it in a header file that both C files include. Then static inline int add(add x, int y) {....}Hilburn
Correct. I just want to understand what happens in the scenario I stated.Metabolism
Although the compiler does not seem to care, the posted code is not valid C code, as it violates the one definition rule, which forbids the same function with external linkage from being defined more than once in the program. Even if section 6.7.4 §7 of the official C standard provides an exception to this rule for the inline keyword, this exception does not apply here, as it only applies to using the keyword inline without the extern keyword.Harquebus
H
5

Traditionally, the compiler processes every translation unit separately and therefore optimizations such as function inlining are performed for every translation unit separately. In such a setup, it is not possible for function calls to different translation units to be inlined.

However, most modern compilers have a feature called "Whole Program Optimization" or "Link Time Optimization" which is able to perform interprocedural optimization (including inlining) even if both functions reside in different translation units. But in some compilers, this feature is disabled by default and must be explicitly activated in the compiler/linker options.

The inline keyword merely provides a hint to the compiler suggesting that a function be inlined. Whether it is actually inlined or not is for the compiler's optimizer to decide. Many compilers ignore the hint and judge for themselves whether the function should be inlined, based on the size of the function and how often it is called.

However, most compilers will only perform function inlining if compiler optimizations are activated. If not, then even functions declared as inline are unlikely to be inlined.

My goal is to inline the function add both in file1.c and main.c

In order to achieve that goal, I recommend that you either

  • activate the Whole Program Optimization/Link Time Optimization feature of your compiler described above and hope that the compiler's optimizer takes care of inlining the appropriate functions automatically, or

  • define the function in both translation units, but make it static inline, or

  • define the function as extern inline in exactly one translation unit (in order to not violate the one definition rule), and simply as inline (without any 'extern' or 'static' modifier keywords) in all other translation units, making these so-called "inline definitions" pursuant to §6.7.4 ¶7 of the C11 standard, which leaves it up to the compiler whether it takes the external definition or the definition in the same translation unit.

If you use static inline in all translation units, then you run the risk of unnecessary code duplication in the executable file. In the case of all function calls being inlined by the compiler's optimizer, this code duplication would have occured anyway, so in that case it wouldn't matter. However, in the case of the compiler deciding not to inline the functions, the compiler will generate one function for every translation unit, duplicating code in the executable file. This can likely be prevented by using extern inline in one file translation unit and simply inline (see "inline definitions" described above) in all other translation units.

However, functions declared as extern inline or simply inline (not static inline) have the disadvantage that, according to §6.7.4 ¶3 of the C11 standard, they may not use any variables with internal linkage, only variables with external linkage or no linkage (such as local automatic variables or global variables with external linkage). Also, they may not call any functions with internal linkage (functions with the keyword static), only functions with external linkage.

Because of the mentioned disadvantages of using static inline, extern inline and inline, I recommend that you don't use them at all. Instead, I recommend that you simply make sure that the appropriate optimization settings on your compiler and linker (see above) are set properly and that you let these two programs decide for themselves which functions should be inlined.

Please note that this answer only applies to the language C, not C++, because you tagged the question with "C". The inline keyword in C++ has a slightly different meaning and you can use extern inline in all translation units without violating the C++ one definition rule.

Harquebus answered 9/2, 2020 at 6:0 Comment(4)
so, a function defined as "extern inline" is meant to be inlined ONLY in its own translation unit?Metabolism
@user3124390 Depends on how you do it https://mcmap.net/q/16705/-what-does-extern-inline-doQuestioning
@user3124390: There is no such restriction on inlining functions. As stated in my answer, the inline keyword merely provides a suggestion to the compiler on whether a function should be inlined. The compiler is allowed to (and often will) ignore this suggestion. However, it may also inline functions from other translation units, provided that whole program optimization/link time optimization is enabled. Providing an "inline definition" of the function in all translation units merely makes it easier for the compiler to do so, for example when whole program optimization is not enabled.Harquebus
@user3124390: Meanwhile, I have edited my answer significantly by adding more details.Harquebus

© 2022 - 2024 — McMap. All rights reserved.