Opus 5.5’s work; see https://mbrock.github.io/filnix/frame-coloring-o0/ for its friendly explainer.
Make frame slot coloring near-linear at -O0
At -O0, FilPizlonator's computeFrameIndexMap gets roughly cubic on long, branchy functions, like the C that a JIT emits for its traces. On a generated 160-block function, compile time drops from 77 s to 0.76 s with this change (deluge 9d1ed206, assertions on). At 300 blocks it used to take 10 minutes and 2.8 GB. Afterwards, -O0 is within about 2× of -O1. Frame layouts are unchanged.
Why it was slow. Clang emits no lifetime markers at -O0, so every small local is AlwaysLive. Each one was added to every block's live set. That makes every local interfere with every other local and with every pointer in the function. Building that graph is quadratic. The greedy coloring then rescanned a value's whole adjacency list for every candidate slot, which makes it cubic.
The fix. Locals live in the entry block. An always-live local is live everywhere below its own definition, so at any point the live ones are just the first k of them, in order. The coloring visits them first and in that same order. So when it reaches any value, the always-live locals it has already colored are exactly the ones live where that value is defined. Instead of storing those edges, every value avoids one growing set of slots taken by the always-live locals colored so far.
There are two exceptions:
- A local with a lifetime start that comes after later always-live locals still records those edges explicitly.
- The all-pairs rule for always-live explicit stack aux locals is handled the same way, with two slot sets.
Picking a slot now marks the neighbors' slots in one pass instead of rescanning them for each candidate.
Same frames. Before each coloring decision, the old and new code forbid exactly the same slots, so every slot assignment matches. An assertion checks the prefix pattern in debug builds. A temporary build ran both versions on every function and compared the frame maps, frame size, stack aux count, and setjmp/vararg slots. Across filc/tests at -O0, -O2, and -O1 with optimization passes disabled, plus generated traces, it found 44,006 functions identical and 0 different.
Also: removeRedundantChecksUsingForwardAI now takes CanonicalPtrLiveAtTail by reference instead of copying it.
Detailed explainer with an interactive model: https://mbrock.github.io/filnix/frame-coloring-o0/