# Inline Expansion of Functions

Inline function expansion does not require that the applications meet the criteria for whole program analysis normally required by IPO; so this optimization is one of the most important optimizations done in Interprocedural Optimization (IPO). For function calls that the compiler believes are frequently executed, the compiler often decides to replace the instructions of the call with code for the function itself.

In the compiler, inline function expansion is performed on relatively small user functions more often than on functions that are relatively large. This optimization improves application performance by performing the following:

- Removing the need to set up parameters for a function call

- Eliminating the function call branch

- Propagating constants

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. In general, when you instruct the compiler to perform function inlining, the compiler can examine the source code in a much larger context, and the compiler can find more opportunities to apply optimizations.

Specifying the [Q]ip compiler option, single-file IPO, causes the compiler to perform inline function expansion for calls to procedures defined within the current source file; in contrast, specifying the [Q]ipo compiler option, multi-file IPO, causes the compiler to perform inline function expansion for calls to procedures defined in other files.

### CAUTION

Using the [Q]ip and[Q]ipo (Windows*) options can, in some cases, significantly increase compile time and code size.

The compiler does a certain amount of inlining at the default level. Although such inlining is similar to what is done when you use the [Q]ip option, the amount of inlining done is generally less than when you use the option.

## Selecting Routines for Inlining

The compiler attempts to select the routines whose inline expansions provide the greatest benefit to program performance. The selection is done using default heuristics. The inlining heuristics used by the compiler differ based on whether or not you use options for Profile-Guided Optimizations (PGO): [Q]prof-use compiler option.

When you use PGO with [Q]ip or[Q]ipo, the compiler uses the following guidelines for applying heuristics:

- The default heuristic focuses on the most frequently executed call sites, based on the profile information gathered for the program.

- The default heuristic always inlines very small functions that meet the minimum inline criteria.

Using IPO with PGO

Combining IPO and PGO typically produces better results than using IPO alone. PGO produces dynamic profiling information that can usually provide better optimization opportunities than the static profiling information used in IPO.

The compiler uses characteristics of the source code to estimate which function calls are executed most frequently. It applies these estimates to the PGO-based guidelines described above. The estimation of frequency, based on static characteristics of the source, is not always accurate.

## Compiler Directed Inline Expansion of Functions

Without directions from the user, the compiler attempts to estimate what functions should be inlined to optimize application performance.

The following options are useful in situations where an application can benefit from user function inlining but does not need specific direction about inlining limits.

Option | Effect
--- | ---
inline-level(Linux* and macOS) or Ob (Windows*) | Specifies the level of inline function expansion. Note that the option /Ob2 on Windows* is equivalent to -inline-level=2 on Linux* and macOS. Allowed values are 0, 1, and 2.
[Q]ip-no-inlining | Disables only inlining enabled by the [Q]ip, [Q]ipo, or Ob2 options.
[Q]ip-no-pinlining | Disables partial inlining enabled by the [Q]ip or [Q]ipo options. No other IPO optimizations are disabled.
setting inline-debug-info for the debug option | Indicates that the source position information for an inlined function should be retained, rather than replaced, by that of the call which is being inlined.

## Developer Directed Inline Expansion of User Functions

In addition to the options that support compiler directed inline expansion of user functions, the compiler also provides compiler options and directives that allow you to more precisely direct when and if inline function expansion should occur.

The compiler measures the relative size of a routine in an abstract value of intermediate language units, which is approximately equivalent to the number of instructions that will be generated. The compiler uses the intermediate language unit estimates to classify routines and functions as relatively small, medium, or large functions. The compiler then uses the estimates to determine when to inline a function; if the minimum criteria for inlining is met and all other things are equal, the compiler has an affinity for inlining relatively small functions and not inlining relative large functions.

Typically, the compiler targets functions that have been marked for inlining based on the following:

- Procedure-specific inlining directives: Tells the compiler to inline calls within the targeted procedure if it is legal to do so. For example, !DIR$ ATTRIBUTES INLINE, !DIR$ ATTRIBUTES FORCEINLINE.

The following developer directed inlining options and directives provide the ability to change the boundaries used by the inliner to distinguish between small and large functions.

In general, you should use the [Q]inline-factor option before using the individual inlining options listed below; this single option effectively controls several other upper-limit options.

If your code hits an inlining limit, the compiler issues a warning at the highest warning level. The warning specifies which of the inlining limits have been hit, and the compiler option and/or directives needed to get a full report. For example, you could get a message as follows:

    Inlining inhibited by limit max-total-size.  Use -qopt-report -qopt-report-phase=ipo for full report.

Messages in the report refer directly to the command line options or directives that can be used to overcome the limits.

The following table lists the options you can use to fine-tune inline expansion of functions. The directives associated with the options are documented in the Effect column.

Option | Effect
--- | ---
[Q]inline-factor | Controls the multiplier applied to all inlining options that define upper limits: inline-max-size, inline-max-total-size, inline-max-per-routine, and inline-max-per-compile. While you can specify an individual increase in any of the upper-limit options, this single option provides an efficient means of controlling all of the upper-limit options with a single command. By default, this option uses a multiplier of 100, which corresponds to a factor of 1. Specifying 200 implies a factor of 2, and so on. Experiment with the multiplier carefully. You could increase the upper limits to allow too much inlining, which might result in your system running out of memory.
[Q]inline-force-inline | Instructs the compiler to force inlining of functions suggested for inlining whenever the compiler is capable doing so. Without this option, the compiler treats functions declared with the ATTRIBUTES INLINE directive as merely being recommended for inlining. When this option is used, it is as if they were declared with the ATTRIBUTES FORCEINLINE directive.
[Q]inline-min-size | Redefines the maximum size of small routines; routines that are equal to or smaller than the value specified are more likely to be inlined.
[Q]inline-max-size | Redefines the minimum size of large routines; routines that are equal to or larger than the value specified are less likely to be inlined.
[Q]inline-max-total-size | Limits the expanded size of inlined functions. You can also use !DIR$ ATTRIBUTES OPTIMIZATION_PARAMETER:"INLINE_MAX_TOTAL_SIZE=N” to control the size an individual routine can grow through inlining.
[Q]inline-max-per-routine | Limits the number of times inlining can be applied within a routine. You can also use !DIR$ ATTRIBUTES OPTIMIZATION_PARAMETER:"INLINE_MAX_PER_ROUTINE=N” to control the number of times inlining may be applied to a routine.
[Q]inline-max-per-compile | Limits the number of times inlining can be applied within a compilation unit. The compilation unit limit depends on the whether or not you specify the [Q]ipo compiler option. If you enable IPO, all source files that are part of the compilation are considered one compilation unit. For compilations not involving IPO each source file is considered an individual compilation unit.

Parent topic: Interprocedural Optimization

## See Also

fpic compiler option
ip, Qip compiler option
ipo, Qipo compiler option
prof-use, Qprof-use compiler option
debug (Linux* OS) compiler option
debug (Windows* OS) compiler option
Zi, Z7, Zl compiler option
inline-level, Ob compiler option
ip-no-pinlining, Qip-no-pinlining compiler option
inline-factor, Qinline-factor compiler option
inline-forceinline, Qinline-forceinline compiler option
inline-max-per-compile, Qinline-max-per-compile compiler option
inline-max-per-routine, Qinline-max-per-routine compiler option
inline-max-total-size, Qinline-max-total-size compiler option
inline-max-size, Qinline-max-size compiler option
inline-min-size, Qinline-min-size compiler option