Repository navigation
Keep values carried around a loop live past its inner branches. - #9
Merged
Merged
Conversation
The register allocator walks each path through a code block, and stops a path at a branch the path has already taken. A loop's second trip is never walked past its first inner branch, so a value written in one trip and read after that branch in the next has no range around the back edge, and a later temporary can take its register: iaddiu VI01, VI01, 1 ; iPtr, read again after the inner branch iaddiu VI01, VI00, 7 ; iT2 Values loaded before a --cont loop and read after an inner branch lose their registers the same way. Tyra's static pipeline programs load their GIF tags once and continue with MSCNT for each further buffer, so from the second buffer on the tags were overwritten by vertex colours. After the walk, follow each block's control flow back from every read to the writes that reach it, lane by lane, and join them into one alias live over the tokens in between, as a complete walk would have. Where the walk was complete this adds nothing, and the code is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
The register allocator walks each path through a code block, and stops a path at a branch it has already taken (or after
--bthresvisits). A loop's second trip is therefore never walked past its first inner branch. A value written in one trip and read after that branch in the next trip gets no live range around the back edge, and a later temporary can take its register:Values loaded before a
--contloop and read after an inner branch lose their registers the same way. Two real programs are affected:general:material_spec, loaded before the directional-light loop, is overwritten inside it.Fix
After the walk,
completeLiveRangesfollows each block's control flow back from every read to the writes that reach it, lane by lane. It joins them into one alias that is live over the tokens in between, as a complete walk would have. Inputs count as written at the block's entry; a broadcast operand keeps only its lane live. Where the walk was already complete this adds nothing, and the code is unchanged.Effect
On a local corpus of 46 programs (ps2gl, Tyra, quake2-ps2, the openvcl examples), against current master:
textured_triangles, Tyrastapip_as_is_c,stapip_as_is_tc,stapip_cull_candstapip_cull_tc, ps2glgeneral,general_nospec,general_pv_diff,general_pv_diff_tri,general_triandindexed, and one small repro.Tests
test/integration/test_loop_liveness.cpp, 4 cases:--contloop keeps its register through the loop;