Repository navigation
Conversation
The register allocator walks the program path by path. The path that takes a conditional branch is a copy of the state before it, and the copy was made without the block's outputs, so a value assigned before the branch and left alone on that path never got its out_vf or out_vi register. And an output's live range ended at its last access instead of at the exit, so a temporary needed after that could take its register before the program ended; an input passed through to an output untouched had no range at all. Copy the outputs into the branch states, and let the exit read the outputs in the control-flow pass: each read joins the writes that reach it, is live from them to the end of the block, and takes the register its directive names, which reports a conflict when the value it sees is an input in another register. Tests: test/integration/test_exit_outputs.cpp (4 cases, all fail on master). Co-Authored-By: Claude Fable 5.1 <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.
Follow-up to #11.
Problem
A code block's
out_vf/out_vioutputs could leave in the wrong register, or be overwritten before the exit, in two ways:BranchState's copy constructor copied the inputs but not the outputs. A value assigned before the branch and left alone on the taken path never got its output register:compiled the
moveasmove VF02, VF01, so the taken path left with VF05 never written.add fOut, fA, fAthenadd fT, fA, fA/sq fT, 0(vi00)gavefTVF05, the registerout_vf fOut(vf05)names). An input passed straight through to an output had no range at all.Fix
completeLiveRanges, the exit reads every output: each read joins the writes that reach it, is live from them to the end of the block, and takes the register its directive names. When the value it sees is an input in another register, that is reported:error: Register conflict: fA has to be in both VF01 and VF05.Tests
test/integration/test_exit_outputs.cpp, 4 new cases:Effect on generated code
None of the ps2gl fixtures, Tyra's 15 programs or quake2-ps2's programs use outputs: all compile byte-identically to master (a5e9dbe). The test suite and an ASan/UBSan build of the suite and those programs are clean.