Inline Transformation: Difference between revisions

Jump to navigation Jump to search
Line 65: Line 65:


Additionally, MSVC supports '''Link-Time Code Generation (LTCG)''', enabled with <code>/GL</code> (compile for whole-program optimization) and <code>/LTCG</code> (link with whole-program optimization). When using LTCG, MSVC’s linker can inline functions across module boundaries (object files) because it has access to the entire program’s intermediate code. This is analogous to GCC/Clang’s LTO. In fact, MSVC will perform cross-module inlining under LTCG even for functions not marked inline, if profitable <ref name="ms_inline">Inline Functions (C++) | Microsoft Learn https://learn.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=msvc-170</ref>. This allows inlining of functions from libraries or other translation units that would not be visible to the compiler otherwise.
Additionally, MSVC supports '''Link-Time Code Generation (LTCG)''', enabled with <code>/GL</code> (compile for whole-program optimization) and <code>/LTCG</code> (link with whole-program optimization). When using LTCG, MSVC’s linker can inline functions across module boundaries (object files) because it has access to the entire program’s intermediate code. This is analogous to GCC/Clang’s LTO. In fact, MSVC will perform cross-module inlining under LTCG even for functions not marked inline, if profitable <ref name="ms_inline">Inline Functions (C++) | Microsoft Learn https://learn.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=msvc-170</ref>. This allows inlining of functions from libraries or other translation units that would not be visible to the compiler otherwise.
== Code Examples ==
Below are simple C++ examples illustrating inline transformation in code for different compilers. In each case, the goal is to show how to declare a function so that the compiler will inline it, and how the call is then replaced by the function’s body.
<syntaxhighlight lang="cpp">// Example 1: Using inline and always_inline in GCC/Clang
#include <cstdio>
// Hint to compiler: inline, and force inline even if not optimizing
inline __attribute__((always_inline)) int add(int a, int b) {
    return a + b;
}
int main() {
    int x = 5, y = 7;
    // The call to add() will be expanded inline (no actual function call at runtime)
    int result = add(x, y);
    std::printf("result = %d\n", result);
}</syntaxhighlight>
In the above code, <code>add</code> is declared with both <code>inline</code> and the GCC/Clang-specific <code>__attribute__((always_inline))</code>. Under GCC or Clang, this ensures that whenever <code>add(x,y)</code> is used, the compiler will substitute the <code>return a + b;</code> logic directly at the call site. For instance, at optimization level <code>-O2</code> or higher, the generated machine code for the call in <code>main</code> will just compute <code>x + y</code> and store it in <code>result</code>, with no function call overhead. (If you compile this with <code>gcc -O2 -S</code> to assembly, you would see that it contains no call instruction for <code>add</code> – the code is inlined.) The <code>always_inline</code> attribute here forces inlining even if we didn’t use <code>-O2</code>, but note that GCC requires the function to be marked <code>inline</code> as well to avoid linkage issues. In practice, you would typically use <code>always_inline</code> for functions in headers or those that you ''must'' inline for performance or correctness reasons.
<syntaxhighlight lang="cpp">// Example 2: Using __forceinline in MSVC
#include <cstdio>
__forceinline int multiply(int a, int b) {
    return a * b;
}
int main() {
    int p = 3, q = 4;
    // The call to multiply() will be inlined by MSVC in an optimized build (/O2)
    int prod = multiply(p, q);
    std::printf("prod = %d\n", prod);
}</syntaxhighlight>
In this MSVC example, the function <code>multiply</code> is declared with <code>__forceinline</code>. In an optimized compilation (with <code>/O2</code>, which implies <code>/Ob2</code>), the MSVC compiler will inline the body of <code>multiply</code> at the call site in <code>main</code>. That means the compiled code for <code>main</code> will effectively just compute <code>3 * 4</code> and print the result, with no actual call/return for <code>multiply</code>. If compiled in a debug configuration (/Od, which implies <code>/Ob0</code>), the compiler would ignore the <code>__forceinline</code> and generate a regular function call (since inline expansion is globally disabled in that case). This example demonstrates the syntax for forcing inline in MSVC. When examining the assembly output in an optimized build, you would see no call to <code>multiply</code>; instead, the instructions for the multiplication are directly inside <code>main</code>.
These examples are simplistic, but they show the syntax and effect of inline expansion. In real-world usage, you might inline small math functions, accessor functions, or other performance-critical routines. All major compilers will remove the function-call overhead and embed the logic directly, as shown above, when inlining is applied.


== Challenges and Limitations ==
== Challenges and Limitations ==
Bots, Bureaucrats, Interface administrators, smwadministrator, smwcurator, smweditor, Administrators
2,558

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu