Inline expansion, or “inlining”, is a kind of optimization that replaces a function call site with the body of the called function. In the compiler, inline function expansion typically favors relatively small user functions over functions that are relatively large. Function inlining can improve execution time by removing the runtime overhead of function calls, however, function inlining can increase code size, code complexity, and compile times.
There are several ways to enable/disable inlining during compilation. Inlining is enabled with the default optimization setting for the Intel compiler.
Here is a simple example showing how it works:
subroutine test_inlining integer k k =10 print *, k end subroutine test_inlining program Console1 call test_inlining print *, 'Hello World' end program Console1
Compile this code using default optimization options (put S option to get the ASM code):
Linux & Mac OS: ifort -S test.f90
Windows: ifort /S test.f90
In this case the default level of optimization is enabled and inlining of the function TEST_INLINING is performed. Checking the assembly listing produced from the above example, you will see that there is no call of the test_inlining subroutine in the generated ASM code (test.s) - the body of this small subroutine was inlined. Here is the example of the assembly listing produced on Windows:
mov DWORD PTR [8+esp], 0 ;8.6 lea edx, DWORD PTR [8+esp] ;8.6 lea eax, DWORD PTR [80+esp] ;8.6 mov DWORD PTR [80+esp], 10 ;8.6 push 32 ;8.6 push eax ;8.6 push OFFSET FLAT: STRLITPACK_0.0.1 ;8.6 push -2088435968 ;8.6 push -1 ;8.6 push edx ;8.6 call _for_write_seq_lis ;8.6
Set the code optimization level to disable inlining:
Linux & Mac OS: ifort –O0 -S test.f90
Windows: ifort /Od /S test.f90
Examining the assembly language listing produced by the above example, you will see that there is the explicit call of test_inlining subroutine:
call _TEST_INLINING ;8.6
It is also possible to control the inlining of the specific subroutines using directives. Adding a simple directive before the subroutine will avoid the inlining:
!DEC$ ATTRIBUTES NOINLINE :: test_inlining subroutine test_inlining integer k ...
The explicit call of test_inlining subroutine could be found in the ASM code again. The NOINLINE option disables inlining of a function.
There is also the INLINE option which could be used to specify that a function or subroutine can be inlined. However, the inlining can be ignored in this case by the compiler if inline heuristics determine it may have a negative impact on performance or will cause too much of an increase in code size.
The FORCEINLINE option could be used to specify that a function or subroutine must be inlined unless it will cause errors.
There is also a way to control the inline expansion using -inline-level (Linux) or /Ob (Windows) option. It specifies the level of inline function expansion. Depending on the value specified, the option can disable or enable inlining.
-inline-level=0 option disables inlining of user-defined functions (note that statement functions are always inlined) on Linux, /Ob0 is the corresponding option on Windows.