Skip to content

Avoid a heap allocation in TerminatorEdges::AssignOnReturn [-0.13%] - #64

Draft
xmakro wants to merge 1 commit into
perf/base-0713from
perf/terminator-edges-smallvec
Draft

Avoid a heap allocation in TerminatorEdges::AssignOnReturn [-0.13%]#64
xmakro wants to merge 1 commit into
perf/base-0713from
perf/terminator-edges-smallvec

Conversation

@xmakro

@xmakro xmakro commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Call terminators have at most one return target and Yield at most two, yet building their edges heap-allocated a boxed slice on every visit, repeated by every dataflow analysis. Use inline SmallVec storage; InlineAsm with many targets still spills.

The inline capacity of 2 is load-bearing and counter-intuitive. SmallVec<[BasicBlock; 4]> is exactly the same 24 bytes (the union already reserves 16 bytes for the heap variant), so on size grounds capacity 4 looks strictly better. It is not: measured alone, capacity 4 gives +0.01% while capacity 2 gives -0.13%. Same struct size, different codegen — the inline array is 8 vs 16 bytes to initialize and move. Do not "simplify" this constant upward without re-measuring.

Result: -0.13% geomean, cargo check -0.32%, ripgrep check -0.25%, 0 regressed cells. This is the only change of five in this batch whose isolated measurement clears 0.25% on any cell.

Measured in isolation against a clean base (ThinLTO stage2, glibc, instructions:u, full scenario, 5 crates x 3 profiles = 15 cells). This change was measured alone, not as part of a batch.

Reviewed adversarially before submission; findings that survived are reflected in the code and described above.

Call terminators have at most one return target and Yield at most two,
yet building their edges heap-allocated a boxed slice on every visit,
repeated by every dataflow analysis. Use inline SmallVec storage;
InlineAsm with many targets still spills to the heap.

The inline capacity of 2 is load-bearing: SmallVec<[BasicBlock; 4]> is
the same 24 bytes (the union already reserves 16 for the heap variant),
but measured at +0.01% versus -0.13% for capacity 2, so the larger
inline array is not free despite the identical size.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant