Thread

  1. Changes in inline behavior on O2 optimization level for GCC 10+

    Alexey Makhmutov <a.makhmutov@postgrespro.ru> — 2025-07-27T21:48:49Z

    GCC 10 introduced some changes to its handling of functions inline 
    optimization. These changes are described in its changelist 
    (https://gcc.gnu.org/gcc-10/changes.html) as following:
      > Inter-procedural optimization improvements:
      > ...
      > -finline-functions is now enabled at -O2 and was retuned for better 
    code size versus runtime performance trade-offs. Inliner heuristics was 
    also significantly sped up to avoid negative impact to -flto -O2 compile 
    times.
    
    Parameter 'inline-functions' was disabled by default in GCC 9 at O2 
    optimization level, so compiler was considering only functions marked 
    with 'inline' keyword as suitable for inline optimization. This behavior 
    was changed in GCC 10: now this option is enabled at the O2 level, so 
    even functions not explicitly marked as eligible for inline may be still 
    optimized in such way. To compensate influence of this change on 
    compiling time and resulting code size a set of threshold parameters 
    were changed. In particular, following parameters were changed:
    * 'early-inlining-insns' from 14 to 6 ("Specify growth that the early 
    inliner can make. In effect it increases the amount of inlining for code 
    having a large abstraction penalty.")
    * 'max-inline-insns-single' from 200 to 70 ("This number sets the 
    maximum number of instructions (counted in GCC’s internal 
    representation) in a single function that the tree inliner considers for 
    inlining. This only affects functions declared inline and methods 
    implemented in a class declaration (C++).")
    * 'max-inline-insns-auto' from 30 to 15 ("When you use 
    -finline-functions, a lot of functions that would otherwise not be 
    considered for inlining by the compiler are investigated. To those 
    functions, a different (more restrictive) limit compared to functions 
    declared inline can be applied (--param max-inline-insns-auto).")
    * 'inline-min-speedup' from 15 to 30 ("When estimated performance 
    improvement of caller + callee runtime exceeds this threshold (in 
    percent), the function can be inlined regardless of the limit on --param 
    max-inline-insns-single and --param max-inline-insns-auto.")
    
    The notable change here is related to decrease of 
    'max-inline-insns-single' parameter value. GCC 10+ now may decide to 
    avoid optimizing functions with explicit 'inline' attribute if it is 
    large enough to violate the new threshold. This mean that some functions 
    which were inlined in GCC 9 / O2 builds will not be inlined in GCC 10+ / 
    O2 builds. In particular, GCC 9 build of current master shows only 15 
    instances of functions violating old threshold value (see attached 
    'not-inlined-gcc-9.txt' file), while GCC 10 build has 174 cases for new 
    threshold (see 'not-inlined-gcc-10.txt'). Note, that this applies only 
    to O2 builds, while O3 level uses old threshold values.
    
    The primary goal of this message is just to raise an awareness of this 
    change and its possible influence on resulting builds.
    
    Theoretically speaking, this change is not an issue by itself, as each 
    compiler is in its right to adjust its optimization logic. Certain build 
    pipeline could always have adjusted parameters if its maintainer is 
    unsatisfied with default compiler heuristics. Inlining for functions 
    marked with 'inline' is not guaranteed anyway (GCC 9 was already 
    deciding to skip some of these functions as was shown above) and O2 
    level is not the most aggressive optimization level in GCC as well. 
    However, the GCC / O2 build is the most common configuration for Linux 
    builds, so it's worth looking on whether code generated on this level is 
    matching developers expectations. In particular, for some functions it 
    may be beneficial to use 'pg_attribute_always_inline' instead of plain 
    'inline' if function body is large enough to violate the new thresholds.
    
    Thanks,
    Alexey
  2. Re: Changes in inline behavior on O2 optimization level for GCC 10+

    Peter Geoghegan <pg@bowt.ie> — 2025-07-28T18:27:40Z

    On Sun, Jul 27, 2025 at 5:48 PM Alexey Makhmutov
    <a.makhmutov@postgrespro.ru> wrote:
    > The primary goal of this message is just to raise an awareness of this
    > change and its possible influence on resulting builds.
    
    I believe that clang works in the same way, and has for some time now.
    "clang -mllvm -debug" output shows debug instrumentation that can
    demonstrate that clang may inline functions that are not declared
    "static inline" (and decline to inline functions that are). As I
    understand it, to clang, the "inline" directive just lowers the
    threshold at which a function will be inlined.
    
    > Theoretically speaking, this change is not an issue by itself, as each
    > compiler is in its right to adjust its optimization logic. Certain build
    > pipeline could always have adjusted parameters if its maintainer is
    > unsatisfied with default compiler heuristics.
    
    "pg_attribute_always_inline" can be used to force the compiler to
    inline a function. I'd be very surprised if GCC 10 failed to honor the
    underlying  "__attribute__((always_inline))" function attribute.
    
    -- 
    Peter Geoghegan