Repository navigation
Conversation
An unresolved JALR promoted every instruction of its function to an indirect fallback entry, although a register call returns to its link address like JAL. The resume entry it already queues is all the caller needs; the callee is found through the function table at run time. A JALR that links into $zero does not return and still falls back like JR, and register calls no longer appear in the fallback promotion report. A switch whose table LUI the compiler hoisted into a saved register, with the low half formed into another register by ADDIU rt, rs, %lo, never matched the table search. That shape is now accepted when it names a table listed under [jump_tables], so unconfigured code behaves as before. KFIV with exact function boundaries and jump tables: 634 fallback functions (103,858 entries) -> 0. With the Ghidra map: 1,352 (119,442) -> 150 (6,046). 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.
Two changes to
ControlFlowAnalyzerthat stop functions being promoted to indirect fallback entries when the analyzer already has what it needs.1. A register call no longer promotes its caller to fallback entries
An unresolved
JALRused to setneedsIndirectFallback. That turned every instruction of the calling function into an entry point and an indirect fallback entry. A register call returns to its link address the same wayJALdoes:pc + 8as a resume entry, and that is the only place control comes back to.So an unknown call target is no reason to make the rest of the caller re-enterable.
Behaviour that is unchanged:
JALRstill goes through the jump-table search, so a register call that does resolve to local targets keeps them.JALRwhose link register is$zerodoesn't link, so it is still treated likeJRand falls back as before.recordIndirectFallbackPromotion) no longer lists register calls among the jumps that caused a promotion.This reverses the expectation in the existing test "unresolved JALR marks internal labels as indirect fallback resume entries" (added in #128). I've rewritten that test to assert the new contract:
A new test pins the
$zero-link case.2. Hoisted table LUI resolves against a configured
[jump_tables]entryGCC sometimes hoists a switch table's
luiinto a saved register far above the dispatch. It then forms the low half into a different register:The table search only matched a
luiinto theadduoperand itself, so this shape always fell back. The analyzer now also followsaddiu rt, rs, %lo(withrs != rt) back to theluiofrs. It accepts the result only when the address names a table listed under[jump_tables], so code without that config behaves exactly as before. Two new tests cover the shape:Results (King's Field IV, SLUS-20318)
I regenerated KFIV from this branch with exact function boundaries and configured jump tables:
SQRT.Semission, which comes from an unrelated local patch.Overlap with #279
#279 (also mine, "Fix continuation ownership for overlapping entry wrappers") touches entry handling too, but in different files:
function_table_emitter.cppandps2_recompiler.cpp.control_flow_analyzer.cpp.Both add tests to
code_generator_tests.cpp, in separate places: this PR's tests sit with the other control-flow analysis tests, and #279's hunk starts later in the file. They should merge in either order without conflicts.Testing
ps2_recompandps2x_testsbuild.ps2x_tests(run from the repo root): 440/440 pass.🤖 Generated with Claude Code