https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127889

            Bug ID: 127889
           Summary: Excessive compile time at -O3: -fno-inline is 185x
                    faster
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: babendrissou at gmail dot com
  Target Milestone: ---

Created attachment 65836
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65836&action=edit
program input file

Compile time at -O3 is dominated by inlining: -fno-inline is 185x faster

Component: rtl-optimization (LRA; triggered by inlining -- ipa also defensible)
Keywords:  compile-time-hog
Severity:  normal -- compile-time hog, not wrong code
Attached:  gcc-inline-hog.i (140,590 bytes, preprocessed)


SUMMARY
-------

On the attached single translation unit, gcc 16.2.0 spends 292.8 s (4 min
53 s) at -O3.  Adding -fno-inline brings the same compile down to 1.58 s, a
185x speedup.  It is also faster than -O2 (4 s).

clang 23.1.3 compiles the same file in 2.2 s at -O3.

The compile completes and emits no diagnostics; the only symptom is
wall-clock time.


REPRODUCE
---------

  $ gcc -O3 -std=gnu11 -w -c gcc-inline-hog.i -o /dev/null
      292.8 s

  $ gcc -O3 -fno-inline -std=gnu11 -w -c gcc-inline-hog.i -o /dev/null
      1.58 s

No -I, no libraries, one translation unit.  -w only silences -Wunused-*
warnings.


VERSION AND SYSTEM
------------------

gcc -v:

  Using built-in specs.
  COLLECT_GCC=gcc
 
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-linux-gnu/16.2.0/lto-wrapper
  Target: x86_64-linux-gnu
  Configured with: /usr/src/gcc/configure --build=x86_64-linux-gnu
                   --disable-multilib --enable-languages=c,c++,fortran,go
  Thread model: posix
  Supported LTO compression algorithms: zlib zstd
  gcc version 16.2.0 (GCC)

System: x86_64-linux-gnu, Linux 5.4.0, 40 cores, 62 GB RAM.  No swapping.
Stock upstream GCC 16.2.0 from the FSF release tarball, not vendor-patched.


WHERE THE TIME GOES
-------------------

-ftime-report on the attached file.  One pass accounts for most of it:

    pass                          -O2         -O3
    ---------------------------  ------    --------
    LRA hard reg assignment      0.01 s    178.91 s   (62%)
    load CSE after reload          ~0       34.61 s   (12%)
    reload CSE regs              0.05 s     17.54 s    (6%)
    tree VRP                     0.25 s      8.98 s    (3%)
    tree DSE                     0.01 s      8.73 s    (3%)
    LRA non-specific               ~0        5.79 s    (2%)
    integrated RA                0.26 s      1.74 s    (1%)
    ---------------------------  ------    --------
    TOTAL                        3.88 s    288.54 s

"callgraph functions expansion" is 99.9% of total, i.e. essentially all time
is per-function compilation rather than IPA.  LRA hard register assignment
alone grows from 0.01 s to 178.91 s -- superlinear in function size, applied
to a function that inlining has made very large.


ONLY INLINING MATTERS
---------------------

23 other -O3 options were disabled individually; none had any effect,
including -fno-tree-vrp, -fno-tree-dse, -fno-tree-pre, -fno-gcse-after-reload,
-fno-ipa-cp-clone, -fno-ipa-sra, -fno-ipa-pta, every loop pass, both
vectorisers and both schedulers.  Nor -fno-ipa-cp, -fno-indirect-inlining,
-fno-partial-inlining.


THE INLINE PARAMETERS ARE NOT THE TRIGGER; THE LEVEL IS
-------------------------------------------------------

-O2 and -O3 differ in exactly five inline parameters:

    parameter                          -O2     -O3
    --------------------------------   ---     ---
    early-inlining-insns                 6      14
    inline-heuristics-hint-percent     200     600
    inline-min-speedup                  30      15
    max-inline-insns-auto               15      30
    max-inline-insns-single             70     200

Reverting each individually at -O3, and all five together, does NOT help.
Conversely, on a larger testcase from the same generator:

    -O2                                                      55 s
    -O2 + all 14 -O3-enabled flags AND all 5 params          56 s
    -O3                                                    1615 s

So the trigger is not expressible as a command-line option combination; it
appears to depend on internal "optimize >= 3" tests or level-derived cost
thresholds.  Inlining volume is still implicated: throttling it hard at -O3
(--param=max-inline-insns-single=1 --param=max-inline-insns-auto=1
--param=early-inlining-insns=0) compiles in 10 s.  The -O2 thresholds are
simply not low enough to avoid the blow-up at -O3, while being harmless at -O2.


NOT A REGRESSION
----------------

Every gcc release tested is affected, so there is no good version to bisect
against:

    gcc 11.5.0      affected
    gcc 12.5.0      affected
    gcc 13.5.0      affected
    gcc 14.4.0      affected
    gcc 15.3.0      affected
    gcc 16.2.0      affected
    clang 23.1.3    not affected


VALIDITY OF THE TESTCASE
------------------------

 - Valid C; -Wall -Wextra reports only -Wunused-* warnings.
 - Runs under -fsanitize=undefined,address with no sanitizer diagnostic.
 - Self-contained: standard headers only, no -I.

Reply via email to