Repository navigation
Give spilled bundles a register in the loops where they are used - #270
Open
EvanCarroll wants to merge 2 commits into
Open
EvanCarroll wants to merge 2 commits into
EvanCarroll wants to merge 2 commits into
Conversation
… instructions Make the fuzz generator emit instructions that clobber nearly every register of a class, the way a call does, so that spill bundles in the fuzzer-generated functions actually reach the loop-region second chance pass. One register per operand of the clobbered class stays free at the top of the file so that every preferred register is clobbered, keeping the instruction itself allocatable.
When a spill bundle that is live across a call fails the whole-range second chance, take the loops where its vregs are used, outermost first, and try to give each piece in the loop one register via a zero-cost probe. If the region contains a call, only non-preferred registers are probed. Pieces crossing a full clobber point or whose vreg has no use in the loop stay on the stack. After a successful probe, a vreg's pieces are kept only if its value is already in the spill slot on every way into the loop or it would be stored back at no more than one loop exit. Move insertion skips the store into a slot that already holds the value at loop exits and on block-parameter edges.
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
When a spill bundle that is live across a call fails the whole-range second
chance, take the loops where its virtual registers are used — outermost first —
and try to give each piece in the loop one register via a zero-cost probe (no
evictions). If the loop region contains a call, only non-preferred registers
are probed since the call clobbers preferred ones anyway. Pieces crossing a
point that clobbers every allocatable register, or whose vreg has no use in the
loop, stay on the stack.
Once a region fits, each vreg's pieces are kept in a register only if:
block-parameter edges to targets outside the loop).
Otherwise the pieces go back to the stack. Every piece of a vreg that is in its
spill slot on entry is flagged, and move insertion skips the redundant store
into that slot at loop exits and on block-parameter edges.
This fixes #268 at
MAX_SPLITS_PER_SPILLSET = 2: the issue's inner loop (twovpmaddwdinstructions) goes from 2 stack references to 0, with no increaseto the split limit.
Results vs limit 2 (origin/main 4a23344)
wasm_i32_4x1wall-clock (median μs, 512/2048/512×2048)How it works
try_allocating_regs_for_spilled_bundles, for each spillbundle that is live across a call.
are used, collect the bundle's pieces that fall inside the loop.
zero eviction cost. In regions containing a call, only non-preferred
registers are probed.
value defined inside the loop is kept only if it exits by at most one edge;
a value live into the loop is kept and flagged as already in its spill slot
if every predecessor outside the loop stores it there.
flag and skips stores that would write a value back to a slot that already
holds it.
Correctness
cargo testcases each; 15,682 loop regions allocated, 10,091 stores skipped, all clean
ion: 10 min × 6 workers (186k runs, no crash)cargo test --test wast -- simd: 158 pass