Repository navigation
Pad the code after a label for what the branches to it leave in flight. - #10
Merged
Merged
Conversation
The scheduler pads each basic block for the results still in flight from the code before it in the program, and for nothing that a branch into the block leaves in flight: the clip flags from a clipw on the other side of a join were read three cycles after it, a register loaded just before a loop's label or in a branch's delay slot one to three cycles after the load, and a VI loaded before a join was tested four cycles after. The padding for the code that falls into a label runs one cycle short as well, so the same reads came one cycle early on that path too: a vertex colour's w lane moved in right before a join was stored a cycle before the move landed, and the store got the lane's old value. Each branch now records what its target inherits: the latencies still pending when it is taken, relative to the cycle the target's first instruction issues, as the most any branch to the label leaves. The program is emitted again with those merged into the emitter's own tracker at the labels, and the emitter pads the scheduled slots for whatever the schedule did not see, until the records stop growing; padding only moves a branch further from the writes before it, so they do. The schedule itself is computed once. Tests: test/integration/test_cross_block_latency.cpp (6 cases, 5 fail on master). Corpus: 16 of the 47 programs that compile change, all by added nop pairs: 11 of the 12 ps2gl fixtures, ps2gl's scei and 4 repros; the rest, quake2 and Tyra among them, are byte-identical. 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.
The emitter pads each basic block for the latencies still in flight from the code before it in program order. It pads for nothing that a branch into the block leaves in flight. Its padding for the code that falls into a label is also one cycle short.
Three of the resulting hazards are not interlocked, so they silently read old values:
fcandafter a join read the flags 3 cycles after aclipwon the other path; they land after 4.fmandafter a join had the same problem.VF registers and VI loads are interlocked. For them, the missing padding only turns a nop into a stall at the same cycle, so the timing doesn't change. The fix pads them too, because the emitter's tracker models them like everything else.
Fix
VuLatencyTracker::mergecombines the records.Effect
On a local corpus of 46 programs, against current master:
scei, and 4 small repros.Tests
test/integration/test_cross_block_latency.cpp, 6 cases; the first 5 fail on master without this change:clipwon every path into a join;