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.