perf: spill slot free-list reuse (Issue #5)#9
Merged
Conversation
Task A: when consume_use drops a value's use_cnt to 0, the value's spill slot (if any) is returned to g_spill_free rather than left permanently dead. The key insight: free only from consume_use (the true death point), not from regalloc_free which is also called for register eviction where the value still has live uses. Task B: in regalloc_alloc and ensure_spilled, pop a recycled slot from g_spill_free before growing sp_top. Reduces peak spill depth in functions with many short-lived spilled values. - 401/401 conformance tests pass - Self-host converges at 2,001,998 bytes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
consume_usenow returns a dead value's spill slot tog_spill_freewhen use count reaches 0. The slot is freed only here — not inregalloc_free— becauseregalloc_freeis also called for register eviction where the value still has live uses and its spill slot must survive.regalloc_allocandensure_spilledcheckg_spill_freefirst before growingsp_top. For functions with many short-lived spilled values, peak spill depth shrinks and the stack frame stays denser.Key correctness insight
regalloc_freeis called from two contexts:consume_use(use_cnt → 0): value is truly dead → safe to recycle its slotlower_mod_magicline 17208: evicting a register to make room for MULQ/IDIV clobbers — value still has uses; freeing its slot here causes corruptionFirst attempt freed the slot in
regalloc_freedirectly: 17 conformance failures (output mismatch) from values evicted for MULQ/IDIV whose recycled slots got overwritten by another spill before the original value was reloaded. Fixed by restricting the free to theconsume_usepath.Test plan
arith_combined,fixedpoint_basic,math_mod_expressionall pass (these exercise the MULQ/IDIV eviction path that was the original bug)Closes #5